SWI-Prolog Changelog since version 10.1.10
This release provides several improvements required by the SWI-Prolog
MCP server (pack mcp): support for HTTP SSE (Server Sent Events) and
additional APIs for various normally interactive tools (help,
profiler, coverage analysis, linter (check/0)) to allows LLMs to use
the stdin MCP server to query running Prolog processes.
The Windows version should now be able to run from a UNC path.
A major cleanup of open issues (dropped from 134 to less than 60) on
GitHub. Most were closed as already fixed, irrelevant, stale, etc.
A handful has been fixed.
Enjoy --- Jan
Highlights
-
FIXED:
PL_initialise()no longer changes the process
LC_NUMERIClocale (#1093), so embedders keep the C locale for
atof()andprintf("%f"). -
FIXED: clause indexing bug where a deep list index preempted
a deterministic primary argument, leaving a spurious choice point
(#1386). -
FIXED:
wrap_predicate/4on meta-predicates now carries the
module/determinism qualification, so tracingfoldl/4and friends
resolves higher-order goals in the correct module (#1245). -
FIXED: Windows UNC support for relative file names and shared
object loading;absolute_file_name/3,access_file/2,
open_shared_object/2anduse_foreign_library/1now work when
the working directory is a UNC path. -
FIXED:
nb_setval/2did not duplicate a plain attributed
variable (#1359). -
FIXED:
is_stream/1crash on a standard stream alias whose
slot isNULL. -
FIXED:
PL_get_stream()verifies the returned stream has the
requested input/output mode (#1233) and rejects invalid modes. -
FIXED:
PL_get_text()with onlyCVT_STRINGnow raises
type_error(string, X). -
FIXED:
number_string/2type error (#695). -
FIXED (clib):
process_create/3restores the signal mask in
the child beforeexec, so the new process’sITIMER_PROFtimer
actually delivers ticks andprofile/1no longer divides by zero. -
FIXED (pack): dependency resolution now considers already
installed packs when a pack’srequiresis only discovered after
download (e.g. installed from a URL). -
FIXED (xpce terminal): DEC application cursor mode sent digit
0instead of capitalO, so every arrow key inviminsert
mode dropped back to normal mode and ran the wrong command. -
ADDED (http):
library(http/sse)server-sent events helper,
honouring thehttp:corssetting. -
ADDED:
prolog_edit:locations/2andhelp_apropos/4. -
DOC: clarified
absolute_file_name/3default behaviour when
the spec resolves to a directory (#782), and--home/ thehome
Prolog flag in both the manual and theswipl(1)man page (#793). -
BUILD: detect Intel-Mac Homebrew at
/usr/localfor dependency
paths, fixing a broken Ninja graph on Intel Macs. Cross-build
Prolog steps use a native friend with correctlibraryand
foreignsearch paths (#1503).Enjoy — Jan
Full ChangeLog
-
FIXED: #726 Less confusing message for unbound type in a
type_error(Expected,Found) error. -
BUILD: Setup library and foreign search paths in the build tree For
cross-compilation using the native friend to run the Prolog steps
of build, we need to setuplibraryto point at the current (cross)
target andforeignto point at the directories holding the foreign
modules of the native friend. -
BUILD: #1503 Simplify the way we setup paths for running in the
build directory. The now aproach should notably fix getting paths
setup correctly for running the Prolog build steps using a native
friend, providing the ability to do cross building where we cannot
run the cross-compiled executable and therefore use a native friend
to perform these steps. -
FIXED: #1093 PL_initialise() no longer mutates the process LC_NUMERIC
locale initLocale() used to call setlocale(LC_NUMERIC, “”) to bootstrap
the default PL_locale from localeconv(). As a side effect it changed
the embedder’s process-wide decimal separator, breaking atof()
and printf(“%f”) in host code that expects the C locale. Read the
environment’s numeric conventions via newlocale()/uselocale() (POSIX
2008) instead, with a save/setlocale/restore fallback under L_LOCALE
for platforms without them. locale_create/3 uses the same helper. -
FIXED: #1386 candidate deep list index preempting deterministic primary
For a small static predicate whose primary argument discriminates
but whose non-primary compound argument shares a top-level functor
across clauses, set_candidate_indexes() emits a list hash index on
the compound argument. At call time existing_hash() matched that
index (top-level functor bound), the deep drill entered a sub-list
whose inner arguments were variables, and the recursion fell back
to next_clause_unindexed(), leaving a spurious choice point on the
non-matching clause. -
FIXED: #1245 wrap_predicate/4 supervisor to carry meta/det qualification
prefix. $c_wrap_predicate/5 installed a bare S_CALLWRAPPER supervisor,
bypassing the S_MQUAL/S_LMQUAL prefix that chainPredicateSupervisor()
normally prepends for meta-predicates. Tracing a meta-predicate such
as foldl/4 therefore lost the caller-module context on higher-order
arguments, so the wrapped goal looked up prolog_trace:my_plus/3 rather
than user:my_plus/3. -
FIXED: PL_get_stream() invalid mode detection.
-
FIXED: #1233 PL_get_stream() to verify returned stream has correct
(input/output) mode. -
FIXED: #1359 nb_setval/2 did not duplicate a plain attvar.
-
DOC: #782 absolute_file_name/3 default behavior when spec resolves to a
directory The docs claimed the predicate “only returns non-directories”
unless file_type(directory) is given or access is none. Since the
default access is none, that “unless” clause covers the default –
but readers naturally miss it. Also, the file_type section stated
the opposite of what the code does regarding when file_type(regular)
is the default. -
DOC: #793 clarify --home and the
homeProlog flag Explain what
the home directory is used for (boot.prc, library/) and distinguish
the two forms of --home: with =DIR sets the home directory (and
adds SWI_HOME_DIR to the environment); without argument reports
the located home directory. Cross-reference the --home option,
thehomeProlog flag, and the findhome section from each other.
Update both the swipl(1) man page and the user manual. -
FIXED: Windows: UNC support for relative file names and shared object
loading. When the process working directory is a UNC path (e.g. set
via a Windows shortcut’s “Start in” field), resolving a relative
file name via absolute_file_name/3, access_file/2 and friends failed,
and open_shared_object/2, use_foreign_library/1 could not load DLLs
identified by a UNC path. -
FIXED: #695 number_string/2: correct type error.
-
FIXED: PL_get_text() with only
CVT_STRINGto return
type_error(string, X) -
FIXED: pack installer: consider installed packs when resolving
dependencies When installing a pack whose requires only becomes known
after download (e.g. installed from a URL), download_plan/3 recursed
into pack_resolve/5 with only the just-downloaded plan as Existing,
losing the list of locally installed packs. Dependencies already
satisfied by an installed pack were then presented as fresh installs
and, if the user declined, the whole install failed. -
FIXED: require_prolog_version/2: Git version comparison.
-
BUILD: detect Intel-Mac Homebrew at /usr/local for dependency paths On
Intel Macs, Homebrew installs to /usr/local rather than /opt/homebrew.
The auto-detection in Darwin.cmake only checked /opt/homebrew,
so Intel Mac users fell through to MACOSX_DEPENDENCIES_FROM=None,
leaving LibArchive (and OpenSSL, BDB) unfound by CMake. This caused
a broken man/archive file dependency in the Ninja build graph and a
ninja failure. -
ADDED: prolog_edit:locations/2, provide data access to location
discovery. -
ADDED: help_apropos/4, providing access to the apropos database.
-
FIXED: is_stream/1: crash when querying a standard stream alias whose
slot is NULL. In a thread created without PL_THREAD_CUR_STREAMS the
protocol slot is never copied, and freeStream() also resets it to
NULL when the protocol stream is closed. get_stream_handle() then
dereferenced LD->IO.streams[n] without a NULL check. The downstream
code already treats NULL as “no such stream”, so just guard the
SIO_CMAGIC test.
Package clib
- FIXED: process_create/3: restore signal mask in child before
exec SIGPROF is blocked around fork() to keep profiler ticks from
interrupting it, but the previous mask was only restored in the parent.
The child therefore inherited SIGPROF blocked across execve(), so the
new process’s ITIMER_PROF profiler ran but no ticks were ever delivered.
profile/1 then divided by zero in prolog_profile:show_profile_/1.
Package cpp
- TEST: Fixed PL_get_stream() calls asking for the wrong in/out stream.
Package http
-
ADDED: library(http/sse): honour http:cors setting in sse_open/0,1
Browser-based EventSource clients on a different origin need an
Access-Control-Allow-Origin response header. sse_open/0,1 now calls
cors_enable/0 from library(http/http_cors), so the existing http:cors
setting controls whether the header is emitted. Non-browser clients
and same-origin pages are unaffected (default setting is ). -
ADDED: library(http/sse): high-level helper for Server-Sent Events
sse_open/0,1 emits the response headers and switches the CGI output
stream into event_stream transfer mode. sse_send/1,2 writes events
given as a dict (with optional event, data, id, retry and comment
keys), an atom/string, or a list of events, splitting multi-line data
on ‘\n’ into separate “data:” lines. sse_comment/1,2 emits a heartbeat. -
FIXED: cgi_stream: stop emitting a second header block when an
event_stream handler returns For event_stream responses the headers are
sent by cgi_hook(send_header) when the transfer encoding is selected,
and each subsequent write is flushed straight through to the client.
cgi_close() was still calling the send_header hook again, producing
a spurious extra HTTP header block at the end of the body. Skip the
call for event_stream; the chunked path is already special-cased.
Package xpce
-
FIXED: terminal: send capital ‘O’, not digit ‘0’, in DECCKM arrow
keys In DEC application cursor mode (DECCKM, \e[?1h), arrow / Home /
End should send SS3 sequences \eOA \eOB \eOC \eOD \eOH \eOF, but we
sent the digit zero instead of capital O. Vim enables DECCKM via
terminfo’s smkx, so every arrow press in insert mode bounced vim out
of insert mode and ran “0” / “A” as normal-mode commands. -
ENHANCED: terminal: DCS swallow, CSI intermediate bytes and OSC 10/11
Vi/vim probes the terminal with sequences our parser did not recognise,
which surfaced asESCP,ESC\,Unknown ANSI CSI: \e[0%andUnknown OSC command: 11messages, and left vim guessing the colour scheme.
Handle them: -
FIXED: Prevent help_message window from being destroyed.