It has been a while since the last release. That doesn’t mean nothing
happened as you can find in the long ChangeLog below. Highlights:
Fixed several reported issues
Improved clause indexing performance, in particular for predicates
with a lot of clauses where some argument has only a few possible
values. In such cases failure on a value that does not appear in
any clause could be slow.
Many changes in (console) I/O handling, wait and (xpce) event
dispatching.
Added library(editline), the BSD command line editor to the Windows
version. This provides saved history and Prolog-sensitive completion
to swipl.exe running in the console.
Dropped 32-bit Windows support. Everything has to end at some point.
It is getting increasingly hard to get all dependencies (Python/Janus
never existed for 32-bit). The upcoming SDL/Cairo/Pango based xpce
no longer supports 32-bit systems.
Updated the build docker for the Windows version to use Fedora 42 as
base image.
The last four changes are all related to upgrading xpce and replacing the
GUI versions (Qt and native Windows swipl-exe) by SWI-Prolog+xpce.
Enjoy --- Jan
SWI-Prolog Changelog since version 9.3.24
PORT: Discontinue 32-bit windows builds.
PORT: Support library(editline) (libedit) on Windows. This provides
cross-platform commandline editing with Prolog-sensitive completion.
ADDED: Windows: tty_size/2 to also work on Windows consoles.
WASM: Deal with new PL_prompt_string() API
MODIFIED: Signature for PL_promot_string() and PL_prompt_next() These
API functions now use the Prolog stream as argument to facilitate
better support for Windows.
ADDED: IOSTREAM* control message to get the Windows HANDLE
FIXED: wait_for_input/3: use Swinsock() from pl-stream.c rather than
a local macro This ensures proper error messages if the input is not
a socket.
MODIFIED: PL_dispatch() and friends now use IOSTREAM* instead
of int. This is a first step to merge simultaneous handling of
console outout and GUI dispatching for POSIX systems and Windows to
a common design.
WINE: Waiting for windows console input now works for wine.
PORT: Make installing INDEX.pl files work on Windows. Concurrency
may cause sharing violations. This patch retries renaming the index
file several times.
FIXED: Possible early reclaim of closure blob after unwrapping
a predicate. PL_unregister_atom() was called twice.
ADDED: Incorporate epilog into the toplevel. These patches prepare
for the XPCE based swipl-win. May be started by using the sdl
branch of xpce and run as
swipl -Depilog [arg ...]
ADDED: ‘$run_state’/1 to query the current run state Can be used to
detect code is running as part of the cleanup hooks.
BUILD: Use SDL_VIDEODRIVER=dummy for running Prolog steps This
makes sure the new SDL based xpce does not try to open graphics and
is harmless on other targets.
FIXED: Move swipl-win history support to library(win_menu). This
library is loaded as source and thus conditional compilation applies.
library(prolog_history) is compiled to .qlf. Now the code is also
where it belongs.
FIXED: When generating _X variable names, avoid query variable names.
Consider the below example by Jan Burse. Using _A in the answer is
at least confusing. We must not only skip variable names that appear
in the projection, but also variable names from the query that are
not in the projection.
?- length(L,2), f(L) = R, S = [_A].
L = [_A, _B],
R = f([_A, _B]),
S = [_A].
FIXED: Terminal REPL loop using thread_exit(io_error) on an io_error
during read.
FIXED: Termination of a REPL loop due to error state of the streams
This did not properly close the query, crashing the system in the
thread cleanup.
FIXED: thread_join/2: could leave L_THREAD mutex locked on error.
ADDED: Allow thread_signal/2 to raise native signals by number.
This can be used to raise e.g. SIGINT in a thread to debug it.
FIXED: enable_line_editing/3 to avoid conditional compilation.
This is needed to make library(threadutil) work as .qlf module.
FIXED: write/1,2 to take rational number syntax from module user.
Before, only write_term/2,3 supported “natural” rational number syntax.
FIXED: Make the stream macros Suser_input safe when called from a
non-Prolog thread Called from a non-Prolog thread caused these macros
to crash. They now return NULL. The main-thread I/O can be obtained
using Sinput, Soutput or Serror.
ADDED: Allow hooking into the terminal link generation.
FIXED: Various details for the sys app
ADDED: Prolog flag linux
FIXED: QLF format to store references to predicates in the current
module by functor. Otherwise, if a predicate is imported the clause
will point at the import location, bypassing the predicate resolution
that happens when loading the source.
BUILD: Avoid cmake warnings.
ENHANCED: jiti_list/0,1 - Provide collision stats - Order predicates
alphabetically - Use tty hyperlinks when supported to allow jumping
to the definition
FIXED: ansi_hyperlink/3: Fix position logic Make sure the column admin
is not updated when writing the escape sequences. This allows mixing
with format/1-3 tag specifiers.
ENHANCED: Make sure that small clause index tables have no collisions.
ENHANCED: Use Fibonacci hashing for clause indexes.
ENHANCED: Index performance on common arguments. Given a predicate
with many clauses that has one or more arguments with only a few
possible values and (thus) many clauses in the hash buckets for each
of these values force fast failure when using a query with a value
that does not appear in that argument.
For example, suppose we have a business database that records the legal
status in one of the columns (arguments). A query with a non-existing
lega status should fail quickly. In the old system, the small number
of values could easily lead to a hash colission, causing the system to
try all clauses with the legal status of the collision.
This issue was reported by Abramo Bagnara
FIXED: #1364 nb_set_to_list/2 could skip elements.
FIXED: version/1: avoid redefined warning.
FIXED: ansi_get_color/2: avoid errors on swipl-win (Qt)
Package clib
COMPAT: Use new PL_dispatch() API.
ENHANCED: uri_file_name/2, mode (+,-): Allow for file://host/…
If host is the same as gethostname/1 reports.
Package cpp
PORT: Deal with new PL_prompt_string() and PL_prompt_next() API.
COMPAT: Use new PL_dispatch() API.
Package http
ENHANCED: Use url(URL) for HTTP startup message.
FIXED: http_time_stamp/2 in mode (-,_+).
FIXED: json_skip_ws/3: Pass exception.
FIXED: http_open/3: when applying a transfer filter, do not close
the output Instead, create a new stream pair from the transfer filter
stream and the output stream.
SECURITY: Make http handlers read remaining request data for Keep-alive
When using a Keep-alive connection the core HTTP infrastructure now
ensures that, if the request has a request body (Content-length)
exactly this number of bytes is read from the input before returning
the stream to the Keep-alive mechanism.
This prevents crafted content to generate additional HTTP requests.
FIXED: http_open/3: only catch error(Formal, Context).
FIXED: Multipart reader to update stream position data of
parent stream. This is a tentative fix, lacking a test case.
It still looses the line count/pos. That could be fixed by calling
S__fupdatefilepos_getc() on all processed data.
Not getting the point but (example with up-arrow key):
$ /Applications/SWI-Prolog9.3.25.app/Contents/MacOS/swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.3.25)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [library(editline)].
true.
?- ^[[A^[[A^[[A^[[A
As noted this only happens to me on 9.3.23 and later.
Library editline provides the (default) commandline editor that makes e.g., the up-arrow key work. There has been no change to this stuff for 9.3.24. There have been a lot of changes for 9.3.25, fixing bugs (see Having all sorts of problems with libeditline - #13 by alanbur), supporting Windows and modifications to the APIs that handle GUI events while waiting for the console.
Now, are we only talking about the arrow keys, or does the whole library not work? Does TAB completion work? Can you edit in the history using Emacs keys ^B/^F for backward/forward, ^P^N for up/down?
Anyone else facing this? Relevant info could be the MacOS version (libedit.dylib comes from the OS) and the console/terminal you are using.
Edit There have been changes for 9.3.22 that modify the conditions on when the library is actually enabled. Try calling
?- el_wrap.
Does this enable the arrow keys and editing? If so, please trace through editline:el_wrap_if_ok to see why it is not enabled.
That is only mildly useful For one thing, nothing changed to this package in version 9.3.23 and 9.3.24. For 9.3.22 changes where made to allow for creating editline.qlf, which implies we cannot enable/disable parts of the library using conditional compilation. That could affect whether or not the library is actually enabled.
It is really hard to say something sensible when behind a system where all works as expected. I’d read through the library and possibly trace a little to see what is going on. You can start Prolog ensuring this library is not loaded using
swipl -Dno-readline
Now there should be no history editing. Now, I can load
?- [library(editline)].
And line editing should work. The library initializes itself by calling el_wrap_if_ok/0, so see why that does (not) work. I normally check it works by typing
?- statis<TAB>
which should expand to
?- statistics.
Not working arrow keys can have more reasons, such as the terminal capabilities not being detected properly. For that reason you can use ^P to get to the previous command. That should not depend on the terminal detection.
So this is progress. Following this procedure, arrow keys, forward delete, cursor positioning, and TAB completion all work. In fact everything I normally do seems to be back in working order. As to why, I have no idea.
root@mx:/usr/local/swipl-devel/build# ninja
[405/1551] Building C object packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/display.c.o
FAILED: packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/display.c.o
/usr/bin/cc -Dplugin_pl2xpce_EXPORTS -I/usr/local/swipl-devel/build/packages/xpce -I/usr/local/swipl-devel/packages/xpce/src -I/usr/include/freetype2 -I/usr/local/swipl-devel/src/os -I/usr/local/swipl-devel/src -O2 -gdwarf-2 -g3 -fPIC -fvisibility=hidden -Wall -DHAVE_CONFIG_H -DSWI -D__SWI_PROLOG__ -std=gnu11 -MD -MT packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/display.c.o -MF packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/display.c.o.d -o packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/display.c.o -c /usr/local/swipl-devel/packages/xpce/src/win/display.c
/usr/local/swipl-devel/packages/xpce/src/win/display.c: In function ‘getDPIDisplay’:
/usr/local/swipl-devel/packages/xpce/src/win/display.c:394:43: error: ‘NAME_dpi’ undeclared (first use in this function); did you mean ‘NAME_pie’?
394 | Any rc = getClassVariableValueObject(d, NAME_dpi);
| ^~~~~~~~
| NAME_pie
/usr/local/swipl-devel/packages/xpce/src/win/display.c:394:43: note: each undeclared identifier is reported only once for each function it appears in
In file included from /usr/local/swipl-devel/packages/xpce/src/win/display.c:36:
/usr/local/swipl-devel/packages/xpce/src/win/display.c: At top level:
/usr/local/swipl-devel/packages/xpce/src/win/display.c:1254:6: error: ‘NAME_dpi’ undeclared here (not in a function); did you mean ‘NAME_pie’?
1254 | IV(NAME_dpi, "[size|int]", IV_NONE,
| ^~~~~~~~
/usr/local/swipl-devel/packages/xpce/src/h/kernel.h:895:35: note: in definition of macro ‘IV’
895 | #define IV(n, t, f, g, s) { n, t, f, NULL, (Name) g, s }
| ^
/usr/local/swipl-devel/packages/xpce/src/win/display.c:1272:6: error: ‘NAME_wmClass’ undeclared here (not in a function); did you mean ‘NAME_noClass’?
1272 | IV(NAME_wmClass, "[name]", IV_BOTH,
| ^~~~~~~~~~~~
/usr/local/swipl-devel/packages/xpce/src/h/kernel.h:895:35: note: in definition of macro ‘IV’
895 | #define IV(n, t, f, g, s) { n, t, f, NULL, (Name) g, s }
| ^
[410/1551] Building C object packages/xpce/CMakeFiles/plugin_pl2xpce.dir/src/win/frame.c.o
ninja: build stopped: subcommand failed.
root@mx:/usr/local/swipl-devel/build#
hum, completely off topic, but did you know that ninja has a clean tool ?
ninja -t clean packages/xpce/all
For anyone using ninja often, make sure to look up the other ninja “tools”:
$ ninja -t list
ninja subtools:
browse browse dependency graph in a web browser
clean clean built files
commands list all commands required to rebuild given targets
inputs list all inputs required to rebuild given targets
deps show dependencies stored in the deps log
missingdeps check deps log dependencies on generated files
graph output graphviz dot file for targets
query show inputs/outputs for a path
targets list targets by their rule or depth in the DAG
compdb dump JSON compilation database to stdout
recompact recompacts ninja-internal data structures
restat restats all outputs in the build log
rules list all rules
cleandead clean built files that are no longer produced by the manifest
100% tests passed, 0 tests failed out of 81
Total Test time (real) = 17.59 sec
root@mx:/usr/local/swipl-devel/build# ninja install
[34/35] Install the project...
-- Install configuration: "PGO"
-- Set runtime path of "/root/lib/swipl/bin/x86_64-linux/swipl" to "/root/lib/swipl/lib/x86_64-linux"
-- Set runtime path of "/root/lib/swipl/lib/x86_64-linux/libswipl.so.9.3.24" to "/root/lib/swipl/lib/x86_64-linux"
-- Set runtime path of "/root/lib/swipl/bin/x86_64-linux/swipl-ld" to "/root/lib/swipl/lib/x86_64-linux"
It seems library(readline) is no longer functional. I have no clue since when this is the case as it is not the default for several years. Maybe you know?
In any case, the current development ask for some reconsiderations. Let me tackle that in a separate topic.
I didn’t keep track of the version I was using before it broke, but I think it is safe to assume that 9.3.22 was working fine. I assume the recent editline work for xpce somehow affected readline.
Good be. The current plan is to discontinue the GNU readline based command line editor. The question is whether that is acceptable. The main reasons are
License issues (GNU readline is GPL, turning everything you run while using this library into GPL).
GNU readline has always proven to be a hard thing to maintain, though in recent years it seems to have stabilized. But, there are several half-baked clones around that we cannot use. This requires quite a bit of CMake logic to avoid trying to use one of them
GNU readline can only have one instance and we’d like to use the same beast everywhere. I managed to get that working using libedit
One command line editor means less maintenance.
So, how many people would get how unhappy if we discontinue libreadline?
Have a look at library(editline). You’ll see that it defines and binds commands from Prolog. You can define the multifile hook editline:el_setup/1 to add your own commands.
It reads an init file based on the “program name” swipl. That can probably be used to use vi. That is surely possible as it is the default Possibly we should also wrap part of el_set() to provide more control. I’m sure you can figure out what needs to be done to make you happy and and send patches
When I created the libedit interface, libedit was way less powerful than readline. For example, the ^R history search was written in Prolog as it was not available. This seems built-in now. Also on my wish list is completion on variable names and smarter general completion. It now completes on atoms and file names without paying attention to the context of the thing being expanded.