Dear SWI-Prolog users,
SWI-Prolog 10.1.12 is ready for download. The list of changes is
extensive. Please test as some regression is not unlikely, notably
on Windows. Highlights:
Core
-
Windows file name case handling has been changed from downcase
to use disk case (case preserving). You can restore the old
behaviour usingswipl -Dfile_name_case_handling=case_insensitive. -
Fixed Windows arithmetic flaw: expressions that contains big
numbers and whose result fits in a tagged integer, but not
in a 32-bit Windowslongremained big integers. Numerically,
these are the same as their canonical tagged counterpart, but
they fail on unification and==/2. -
Support INRIAs crmath library for correct rounding floats.
This patch allows configuration usingcmake -DUSE_CRMATH=ON. -
Option processing now uses library(option) or the C API
consistently. This allows for using dicts for options everywhere.
This patch also completes the predicate_options/1 declarations and
extends the linter to find suspicious operations on options lists.
These are preparing steps to resolve the ordering issue with
option lists. -
The compiler (also assert/1, etc.) now avoids C stack recursion.
This allows it to compile much deeper nested structures and raise
a properresource_error(memory)exception when running out of
memory. -
phrase_from_file/3 got as(chars) option to call DCGs compiled to
process literals as character lists. -
Fixed crash in debugger on using
das command (set print depth). -
Fixed (hopefully) dif/2 on (some) cyclic terms as well as avoid
non-termination on some unifications. -
Added push_prolog_flag/2 and pop_prolog_flag/1 (Ciao compatible).
-
Added library(random_terms) to generate complex terms with
controlled properties and probabilities. -
Fixed auto-loading Janus (py_*) predicates.
-
Added code-signing for Windows. Actual signing waits for approval
of the current process by SignPath. Hopefully next release.
Packages
-
archive_open/4 now uses a filters(+List) and formats(+List) option
instead of repeating filter(+Filter) and format(+Format). Backward
compatibility is implemented. -
library(crypto) got support for Ed25519 signatures. Fixed compilation
using modern OpenSSL for single threading. -
Janus now provides access to built-in classes as
builtins:<class>.
Fix for lost exception in invalid py_call/3.
GUI
-
Added library(xdot) and demo. This uses Graphviz (
dot) for
rendering graphs and display them in an xpce window. Provides
panning and zooming as well as clicking and menus on nodes and
edges. -
To support the above, library(pan_zoom) got a fix and several
graphical classes now have more precise event hit testing. Also
added support for colour gradient filling. -
Fixed transferring rational numbers to xpce (as floats).
-
Cleanup relaying printing from the xpce thread (
main) to the
first Epilog console. Simpler and also handles normal write to
these streams. -
Improve handling of BMP symbol glyphs (dingbats, misc symbols)
in Epilog. -
Prettier scroll bars on Windows.
Enjoy — Jan
SWI-Prolog Changelog since version 10.1.11
-
ENHANCED: win_process_modules/1: use disk case Used to downcase the
file names. -
FIXED: Drive letters on Windows are now normalized as upper case.
As we now normalize on the disk case and (thus) paths are typically
mixed case, we better use the Windows uppercase default for drive
letters as well. Reported by Paulo Moura. -
DOC: Describe the initial view of the Prolog Navigator Co-Authored-By:
Claude Opus 4.8 noreply@anthropic.com Claude-Session:
https://claude.ai/code/session_013EGUkPkGnzYjZUQtYF3tH4 -
ADDED: Process -D flags that the boot sequence depends on before
starting Prolog apply_defines/0 applies -D options after the boot
files have been loaded, which is too late for a flag the boot sequence
itself depends on. Prolog flags listed in early_defines are now
picked from the raw argv by setEarlyDefines(), which runs before
initPaths(), and are left out of the list handed to apply_defines/0.
Add a flag to that table to handle it early; -Dhome=Dir is a candidate. -
ENHANCED: Windows: normalise file names to their on-disk case,
not lower case On case-preserving file systems (the Windows default)
SWI-Prolog now normalises a file name to the case in which it is stored
on disk rather than down-casing it. So absolute_file_name/2 and
working_directory/2 return e.g. ‘c:/Users/Paulo Moura/…’ instead
of ‘c:/users/paulo moura/…’. The result is still a single normal
form per physical file, which source tracking relies on, but it is
readable and matches what the user sees in the file manager. Set the
flag file_name_case_handling to case_insensitive to restore the old
down-casing behaviour. -
FIXED: file_name_case_handling flag reported a value inconsistent
with its setting currentFileNameCaseHandling() did not match
setFileNameCaseHandling(): on a case-preserving system (the Windows
default) it reported case_sensitive, and it could never report
case_preserving. Rewrite the getter to mirror the two flag bits the
setter uses. -
FIXED: #1511 Failure to normalize bigint to tagged int on Windows.
This happened when using GMP for integers that do not fit in a long
but do fit in a tagged integer. -
FIXED: crmath build failed on old compilers not knowing -march=x86-64-v3
Upstream core-math adds -march=x86-64-v3 unconditionally on x86_64.
This microarchitecture level is only known to gcc >= 11 and clang >=
12; older compilers error out. Drop the flag in our crmath.cmake layer
when check_c_compiler_flag() reports it is unsupported. It is only
a tuning hint, so dropping it loses AVX2 tuning but not correctness. -
FIXED: predicate_options drift check failed where foreign source
locations are unavailable On platforms such as WASM predicate_location/2
does not resolve foreign (C) predicates to their source file, so
the drift check scanned no C files and reported every option array
as stale. Gate the check on a drift_testable/0 probe that verifies
a foreign predicate can be located, skipping the drift test otherwise. -
FIXED: predicate_options drift check failed on single-threaded builds
The thread option declarations in library(dialect/swi/syspred_options)
referred to predicates that do not exist without O_PLMT, so the
predicate_options drift test flagged their (unreachable) C option
arrays as stale. Guard the thread-only declarations and the matching
c_option_array/2 mappings with :- if(current_prolog_flag(threads,
true)). -
FIXED: setCloseOnExec() silently failed on missing fd / failing fcntl
set_stream/2 close_on_exec now raises a permission_error when the
stream has no OS file descriptor and a system_error (preserving errno)
when fcntl()/SetHandleInformation() fails, instead of failing silently. -
FIXED: set_stream/2 close_on_exec silently succeeded on unsupported
platforms setCloseOnExec() returned -1 where close-on-exec is
unavailable, which set_stream/2 treated as success. Raise a
not_implemented(feature, close_on_exec) exception instead and return
bool. -
CLEANUP: remove unused setBoolean() setBoolean() had no callers
anywhere in the tree. -
CLEANUP: int → bool for boolean by-value function parameters Type
the boolean flag parameters of setCloseOnExec(), declareModule()
(allow_newfile), PopTty() (do_free), lookupSourceFile()/get_mutex()/
intern_indirect() (create) and trie_intern_indirect() (add) as bool.
Callers already pass true/false; the $declare_module local now reads
with PL_get_stdbool_ex(). -
CLEANUP: local int → bool for booleans read with PL_get_stdbool_ex()
Convert local int helpers that only hold a two-valued boolean to
C11 bool, reading them with the new PL_get_stdbool_ex() instead of
PL_get_bool_ex(). -
ADDED: C API support for C11
booltype. This adds PL_get_stdbool(),
PL_get_stdbool_ex() and adds the type OPT_STDBOOL to PL_scan_options. -
ENHANCED: Support INRIAs crmath library for correct rounding floats.
This patch allows configuration usingcmake -DUSE_CRMATH=ON.
This downloads and builds thecrmath.alibrary and replaces the
explicit up and downward rounding insrc/pl-arith.cto achieve
a safe interval with correct functions. -
CLEANUP: use $option/2 instead of raw memberchk/2 for option access
in boot Replace memberchk/2 on option lists with the bootstrap
$option/2, which also handles dict options. Behaviour is unchanged
for classical option lists. Affects load option handling in init.pl,
the answer_write_options queries in toplevel.pl and the version tag
in messages.pl. -
ADDED: predicate_options drift check and order-sensitive-access linter -
check_raw_option_access/0,1: an opt-in linter (not part of check/0) that
reports order-sensitive option handling: raw memberchk/2 on option
lists
(Category A) and [Opt|Tail] overrides passed to rightmost-wins
builtins
(Category B). The clause analysis is strengthened accordingly:
descend
into (If->Then)/(If*->Then), propagate option-list-ness through
append/3
and merge_options/3, and seed the declared option arguments of the
head. - FIXED: check_predicate_option/3 left a choicepoint despite
being det. - A drift check (tests/library/test_predicate_options.pl)
verifying that
every option in a core C PL_option_t array is declared, wired
into the
swipl:library ctest. -
ENHANCED: predicate_options declarations for built-in option predicates
Mirror the PL_option_t arrays of more built-in option predicates in
library(dialect/swi/syspred_options): thread_wait/2, thread_update/2,
transaction/2, engine_create/4 and the low-level zip predicates.
Also complete options that were already scanned by C but not declared,
found by the new drift check: open/4 unicode_atoms; read_term/3
var_prefix, back_quotes, quasi_quotations, dotlists, unicode_atoms;
read_clause/3 unicode_atoms; write_term/3 dotlists, portrayed,
back_quotes, integer_format, float_format; create_prolog_flag/3 local. -
DOC: remove unused code that’s the same as the documentation
-
ADDED: #667 phrase_from_file/3: as(Type) argument, phrase_from_stream/3,
stream_to_lazy_codes/2 and stream_to_lazy_chars/2 Allow
library(pure_input) to work with chars lists as well as codes lists. -
CLEANUP: drop compileClauseGuarded() and its C_STACK_OVERFLOW_GUARDED
wrapper compileBody(), analyseVariables2(), setVars(), compileArgument()
and compileArithArgument() no longer recurse on the C stack,
so the SIGSEGV-catching guard around the compiler is redundant.
Fold compileClauseGuarded() back into compileClause() and remove the
cleanupCompile() helper the guard used. -
ENHANCED: compileArgument() iterative via segstack Fold the recursive
argument walk into an explicit state machine over a segstack of ca_frame
records. Frame kinds: CA_MIDDLE tracks progress through args[0..N-2]
of a compound (advance on resume, or transition to last-arg handling
when done); CA_LAST_POP emits the closing H_POP/B_POP after the
non-right last-arg sub-compilation. The list right-chain tail-jump
(wasgoto right_recursion) becomes a plaingoto next_arg. -
ENHANCED: compileArithArgument() iterative via segstack Fold the
recursive arithmetic-argument walk into a state machine over a
segstack of aa_frame records. Each function application pushes a
frame capturing the operator’s fdef/index/arity and how many operands
are still pending; operands are compiled right-to-left just like
the original loop; the closing A_ADD / A_MUL / A_FUNCn is emitted
when the last operand completes. Push failure calls outOfCore(),
matching the setVars() pattern. -
ENHANCED: setVars() iterative via segstack Walk the term with an
explicit segstack of pending arg pointers rather than C-stack recursion.
compileBody() calls setVars() on both branches of every disjunction, so
deeply nested (A;B;C;…) clauses recursed setVars() to the same depth
as the term and overflowed the C stack. Segstack push failure calls
outOfCore(), matching the pattern used elsewhere for void-returning
term walkers. -
ENHANCED: analyseVariables2() iterative via segstack Fold the recursive
shape into an explicit state machine over a segstack of av_frame
records. Frame kinds match the recursive call-sites: AV_ARG_LOOP
for the default N-arg descent, AV_SUBCLAUSE_LOOP for the islocal +
subclausearg loop, AV_SEMI_AFTER_LEFT / _AFTER_RIGHT for the two-branch
semicolon analysis with branch_vars save/restore, and AV_NOT_AFTER
for the + singleton pass. Depth is tracked in a per-frame field so
cycle checks fire on the same paths as before. Segstack allocation
failure returns MEMORY_OVERFLOW, which analyse_variables() already
turns into an ERR_NOMEM resource_error. -
ENHANCED: compileBody() iterative via segstack Fold the recursive
shape into an explicit state machine over a segstack of resume frames.
Each control functor pushes a frame capturing its phase-specific state
(saved cut, VarTables, C_JMP/C_OR patch offsets, target_module) and the
post-processing to run when the sub-compilation returns. Push failure
returns MEMORY_OVERFLOW, which compileClauseGuarded() converts to a
resource_error after resetVars() has restored setVarInfo() tags on
the stack; the unwind restores ci->colon_context and ci->at_context
so the caller sees consistent state. -
FIXED: crash on the debugger “depth” command without argument The
default depth was passed as a plain C integer rather than a tagged
Prolog word, creating a bogus float term that crashes clause indexing. -
FIXED: absolute_file_name/3 to enumerate all solutions while loading
a file If a file is being loaded, ‘$chk_file’/5 searches relative to
the directory of the file being loaded. This search was guarded by
an if-then-else to implement the deprecated fallback to the working
directory, killing the choice points of the file candidates. As a
result, solutions(all) only produced the first candidate. Now uses
a soft cut. -
TEST: Randomised property test for dif/2 Generate a random ground
term T with library(random_terms), produce a generalisation G by
replacing a random subset of subterms with fresh variables (recorded
asV=Value), and optionally alias two of those variables so G also
carries a sharing constraint. Postdif(G, T), apply a random plan
of matching and/or clash bindings, then require the observed outcome
to match the prediction: -
ENHANCED: dif/2 canonical propagation via unifiable/3 on accumulated
lists Reimplement the pending-unifier simplification along the lines
flagged by the @tbd in the previous dif_c_c_l/3 comment: instead of
dedup-ing Var=Val pairs list-wise, split the pending set into left-
and right-hand-side lists and call unifiable/3 to compute a most
general unifier for the whole set at once. -
FIXED: #919 dif/2 loops on cyclic terms The pending unifier stored
on an OrNode could contain bothX=YandY=Xfor the same pair of
unbound variables, because unifiable/3 sometimes returns a chained
form (e.g.[E=[], C=E]) alongside a pre-existing reverse entry
(E=C). simplify_ornode_/3 sorts by the first argument only, so the
reverse-duplicate never becomes adjacent and its dedup clause never
fires, driving the algorithm into an infinite oscillation. -
FIXED: Too strict checking in restoreStandardStream() Introduced in
9d40a82ad7fbf8d4f9aa24f72080036db0936705 -
FIXED: WASM build was broken by 3d79bc7caee4c08e941496dfb5f2c70f9b8224d3
This commit modified how the build home is detected, breaking teh
WASM build. -
FIXED: single-threaded build of push_prolog_flag/2 and pop_prolog_flag/1
copy_prolog_flag() was defined only under O_PLMT but is called
unconditionally by push_prolog_flag/2. Move the guard so it is
compiled in all configurations. Also move the now-unused in_local
tracking in pop_prolog_flag/1 inside the O_PLMT block. -
ENHANCED: use push_prolog_flag/2 for xref-flag scoping
boot/autoload.pl exports/5, library/prolog_xref.pl with_xref/1 and
library/prolog_source.pl read_directives. Drops the fallback for
“xref flag might not exist” and the state term threading OldXref,
both handled by push/pop. -
ADDED: push_prolog_flag/2 and pop_prolog_flag/1 Thread-local, nestable
save/restore of Prolog flag values. Both go through the existing
set_prolog_flag/2 code path, so type checks, read-only checks,
thread-local COW, and side effects (character escapes, module bits,
boolean fast mask, …) stay consistent. The push stack lives
inside the prolog_flag struct as a linked list of snapshot frames.
A FF_PUSH_ABSENT sentinel records that the flag did not exist at push
time; pop then removes the local entry. -
FIXED: PL_get_term_value: classify numeric terms; raise on double
overflow PL_get_term_value() previously reported PL_INTEGER for
rationals and bignums but left val.i as garbage (get_int64 silently
misread MPQ storage as MPZ). Now it dispatches via get_number(): -
DOC: CODE_SIGNING: add signtool/osslsigncode verification commands
Document the exact commands users can run on Windows, Linux and macOS
to verify the Authenticode signature and trusted timestamp on the
Windows installer. -
ADDED: library(random_terms) — random Prolog term generator
Generates terms suitable for stress-testing predicates that handle
arbitrary structures: variant checks, factorisation, unification,
copy vs share, etc. The generator aggressively mixes: -
FIXED: generate INDEX.pl for library files referenced with a source path
prefix add_index() skipped any file whose source path contained a ‘/’,
which was intended to exclude files destined for library subdirectories.
Those are already dispatched through their own PL_LIB_SUBDIR iterations,
so the guard only did harm: it also rejected a top-level PL_LIBS
file whose source path happens to include a directory component,
e.g. swipy’s janus/janus.pl. As a result home/library/ext/swipy had no
INDEX.pl and the janus predicates were not autoloadable via the index. -
FIXED: macOS (MacPorts) build: include <xlocale.h> for
newlocale()/uselocale() On the MacPorts CommandLineTools MacOSX14.sdk,
<locale.h> only declares locale_t/newlocale()/uselocale()/freelocale()
when USE_EXTENDED_LOCALES is set (__DARWIN_C_LEVEL >=
__DARWIN_C_FULL). There the feature level ends up below FULL,
so the declarations are hidden even though check_function_exists()
sets HAVE_NEWLOCALE/HAVE_USELOCALE (the symbols do live in libc).
This broke the fill_locale_from_name() code added for #1093.
Package RDF
- CLEANUP: use option/2 for embedded option in rdf.pl Replace memberchk/2
on the option list with option/2, which also accepts Name=Value and
dict options. Behaviour is unchanged for classical option lists.
Package archive
-
CLEANUP: archive: filters/formats list options + PL_scan_options()
Repeating the filter/format option to support multiple filters/formats
forced a hand-rolled option loop that accumulates into a mask.
Introduce filters(List) and formats(List) options: archive_open/4 now
folds any (possibly repeated) filter/compression/format options into
these lists in Prolog, raising a deprecation warning for the repeated
singular form. -
FIXED: archive_open/4 could leak the file stream on close_parent(false)
When archive_open/4 is given a file (not a stream), it opens
the file itself and must close it together with the archive.
It prepended close_parent(true), but archive_open_stream/4 resolves
options rightmost-wins, so a caller-supplied close_parent(false)
defeated the override and leaked the stream. Use merge_options/3 so
close_parent(true) takes precedence regardless of order.
Package clib
-
ENHANCED: process_create/3 uses PL_scan_options() Replace the
hand-rolled option loop in parse_options() with PL_scan_options().
detached and window scan as OPT_BOOL and priority as OPT_INT straight
into the p_options struct; the remaining options are OPT_TERM so the
nested values (pipe(Stream), std, null and the env list) still reach
get_stream()/parse_environment() unchanged. Drops the now-unused
option-name atoms. -
CLEANUP: use PL_scan_options() in alarm/4, ossp_uuid/2 and
process_wait/3 Convert the hand-rolled option loops:- time.c alarm4_gen: remove/install bool flags (removes the now-unused
local pl_get_bool_ex helper). - uuid.c pl_uuid: version/format and the dns/url/oid/x500 namespace
options, scanned as terms for their validation. - process.c process_wait: timeout/release, using OPT_UNKNOWN_ERROR
to keep raising domain_error on unknown options.
- time.c alarm4_gen: remove/install bool flags (removes the now-unused
-
CLEANUP: modernise clib error handling to use the public C API -
Replace context-free pl_error(NULL, 0, NULL, ERR_TYPE|ERR_ARGTYPE|
ERR_DOMAIN|ERR_EXISTENCE|ERR_RESOURCE, …) calls with the equivalent
PL_type_error/PL_domain_error/PL_existence_error/PL_resource_error,
which report the actual calling predicate as the error context.
pl_error() is kept for errno mapping (ERR_ERRNO), ERR_NOTIMPLEMENTED,
ERR_SYNTAX and calls carrying an explicit predicate/message context.- break_form_argument() now raises errors directly (PL_resource_error /
PL_syntax_error) and returns bool instead of ad-hoc ERROR_* integer
codes that pl_cgi_get_form() had to map back to exceptions. Removes
the ERROR_* defines from form.h. - Type the form-decoding callback
(add_to_form/break_form_argument) as
bool, matching mp_add_to_form/break_multipart. - Simplify
unify_number() with PL_put_term_from_chars(), which takes a
length so the value no longer needs copying into a NUL-terminated
buffer.
- break_form_argument() now raises errors directly (PL_resource_error /
-
CLEANUP: use PL_scan_options() in open_hash_stream/3 Replace the
hand-rolled option loop with PL_scan_options(). The algorithm option
is scanned as a term and passed straight to get_hash_algorithm/2.
Behaviour is unchanged; unknown options follow the unknown_option flag
(ignored by default). -
CLEANUP: use PL_scan_options() in udp_receive/4 and udp_send/4 Replace
the hand-rolled option loops with PL_scan_options(), matching the
existing pl_host_address() usage in this file. as, encoding and
max_message_size are scanned as terms and passed straight to get_as/2,
get_representation/2 and the range check. Unknown options follow
the unknown_option flag (ignored by default). -
CLEANUP: use PL_scan_options() in open_memory_file/4 Replace the
hand-rolled option loop with PL_scan_options(). The encoding
option is scanned as a term and passed straight to get_encoding/2.
Behaviour is unchanged; unknown options follow the unknown_option flag
(ignored by default). -
CLEANUP: use PL_scan_options() in sha_hash/3 and friends Replace the
hand-rolled option loop with PL_scan_options(). algorithm and encoding
are scanned as terms; the algorithm term is reused directly for the
HMAC-SHA domain_error. Behaviour is unchanged; unknown options follow
the unknown_option flag (ignored by default). -
CLEANUP: use PL_scan_options() in md5_hash/3 Replace the hand-rolled
option loop with PL_scan_options() using the string-name PL_OPTION()
form. The encoding option is scanned as a term so its value can be
validated and reported in a domain_error without reconstructing it.
Behaviour is unchanged; unknown options follow the unknown_option flag
(ignored by default). -
CLEANUP: use option/2 for option access in socket.pl and
prolog_server.pl Replace raw memberchk/2 and a member/2 *-> soft-cut
idiom on option lists with option/2, which also accepts Name=Value
and dict options. Behaviour is unchanged for classical option lists.
Package cpp
-
DOC: remove unused code that’s the same as the documentation
-
ENHANCED: use push_prolog_flag/2 for stack_limit save/restore in
with_small_stacks/2 Depends on push_prolog_flag/2 and pop_prolog_flag/1
in swipl-devel.
Package cql
- CLEANUP: use option/2 for option access in sql_write.pl Replace the
~44 raw memberchk/2 calls on the Options list with option/2, which
also accepts Name=Value and dict options. Behaviour is unchanged
for classical option lists.
Package http
-
CLEANUP: use PL_scan_options() in stream_range_open/3 and cgi_open/4
Convert the hand-rolled option loops:- stream_range.c: size (nonneg) and onclose (a recorded
module-qualified callback), scanned as terms. - cgi_stream.c: the request option, using OPT_UNKNOWN_ERROR to keep
erroring on unknown options.
- stream_range.c: size (nonneg) and onclose (a recorded
-
CLEANUP: use PL_scan_options() in http stream filters; drop http_error.c
Convert the hand-rolled option loops of http_chunked_open/3,
multipart_open/3 and ws_open/3 to PL_scan_options(). Remove
http_error.c: its type/domain/existence/permission/instantiation_error
and get_int_ex helpers are replaced by the public
PL_*_error()/PL_get_integer_ex() API, and the debug hook
(http_stream_debug/1) moves into http_stream.c. -
CLEANUP: use option/2 for option access in http predicates Replace
raw memberchk/2 (and a member/2 *-> idiom) on option lists with
option/2, which also accepts Name=Value and dict options. Files:
http_parameters.pl, http_dispatch.pl, thread_httpd.pl, ax.pl and
http_pwp.pl. Sites that inspect non-option lists, multi-argument
options or backtrack over repeated terms are left on memberchk/2
and member/2. -
TEST: proxy: fix startup race between server thread and control assert
start_http_proxy/1 and start_socks_server/1 asserted the control record
after thread_create/3. If the newly spawned accept-loop reached
its first http_proxy_control(_, Self, ) (or + socks_control(,
Self, _)) check before the assert committed, the guard flipped, the
loop exited, and setup_call_cleanup/3 closed the listening socket
— after which the test dialing the proxy port saw ECONNREFUSED.
Manifested as sporadic “All TCP connections via HTTP” failures on CI. -
TEST: proxy: factor shared shutdown into stop_control_thread/4
Both stop_http_proxy_server/0 and stop_socks_server/1 do the same
close(ControlWrite) / tcp_connect wake / thread_join dance to shut
down their worker thread. Extract it into stop_control_thread/4.
Package json
- CLEANUP: use option/2 for json_object option in http_json.pl Replace
memberchk/2 on the option list with option/2, which also accepts
Name=Value and dict options. Behaviour is unchanged for classical
option lists.
Package libedit
- ENHANCED: use push_prolog_flag/2 in with_quote_flags/3 Depends on
push_prolog_flag/2 and pop_prolog_flag/1 in swipl-devel.
Package mqi
-
CLEANUP: use option/2 for unix_domain_socket check in mqi.pl Replace
memberchk/2 on the option list with option/2, consistent with the
surrounding option/3 calls. Behaviour is unchanged for classical
option lists. -
ENHANCED: use push_prolog_flag/2 for tmp_dir save/restore Also fixes
the case where tmp_dir is not currently set: the previous code would
fail on current_prolog_flag/2. push_prolog_flag/2 handles the absent
case and pop_prolog_flag/1 removes the flag again.
Package odbc
-
DOC: odbc_query/4 options cannot be given as a dict Document that the
statement option list is handled by a dedicated routine (needed for the
two-argument findall/2 option) and therefore must be a list, not a dict. -
DOC: note set_statement_options() does not use PL_scan_options()
Explain that the option loop is hand-written because findall(Template,
Row) is an arity-2 option, and that these options therefore cannot
be given as a dict. -
ENHANCED: odbc_connect/3 uses PL_scan_options() Replace the hand-rolled
option loop in pl_odbc_connect() with PL_scan_options(). A value-level
get_typed_ex() (and matching get_ex() macros) mirror the existing
get_arg_ex() helpers so the scanned option values keep their
original type checks. The five after-connect options (auto_commit,
null, access_mode, cursor_type, wide_column_threshold) are rebuilt
with PL_cons_functor() and handed to odbc_set_connection() as before.
Package pcre
- CLEANUP: use option/2 for capture_type option in pcre.pl Replace
memberchk/2 on the option list with option/2, which also accepts
Name=Value and dict options. Behaviour is unchanged for classical
option lists.
Package pengines
- CLEANUP: use option/2 for answer option in pengines.pl Replace
memberchk/2 on the create-event option list with option/2, which
also accepts Name=Value and dict options. Behaviour is unchanged
for classical option lists.
Package pldoc
-
CLEANUP: use option/2 for module/public options in doc_html.pl Replace
memberchk/2 on the option list with option/2, which also accepts
Name=Value and dict options. Behaviour is unchanged for classical
option lists. -
FIXED: #45 doc_htmlsrc source view leaking / into rendered
structured comments In source_to_html/3, /* … */ fragments
produced by colour_fragments/2 include the trailing newline after /.
end_of_comment//1 in doc_wiki.pl matched "/" but did not consume
trailing whitespace, so phrase/2 failed and split_lines//2 backtracked
to render */ as an ordinary content line at the end of the rendered
comment block.
Package plunit
-
CLEANUP: use option/2 for fixme option in plunit.pl Replace memberchk/2
on the test option list with option/2, which also accepts Name=Value
and dict options. Behaviour is unchanged for classical option lists. -
ENHANCED: use push_prolog_flag/2 for occurs_check in run_test_once/6
Depends on push_prolog_flag/2 and pop_prolog_flag/1 in swipl-devel.
Package semweb
-
CLEANUP: use PL_scan_options() in rdf_transaction/3 and the turtle
parser Convert the hand-rolled option loops:- rdf_db.c rdf_transaction: the snapshot option.
- turtle.c create_turtle_parser: base_uri, anon_prefix, graph, format
and on_error, scanned as terms and applied to the parser state. - turtle.c turtle_parse: parse and count.
-
CLEANUP: use option/2 for option access in rdf_db.pl Replace
raw memberchk/2 on option lists (graph, db, document_language,
convert_typed_literal) with option/2, which also accepts Name=Value
and dict options. Behaviour is unchanged for classical option lists. -
ENHANCED: use push_prolog_flag/2 for agc_margin save/restore rdf_load/2
and no_agc/1 (rdf_persistency).
Package sgml
-
DOC: sgml_parse/2 options cannot be given as a dict Document that
the option list is handled by a dedicated routine (needed for the
two-argument call(Event, Pred) option) and therefore must be a list,
not a dict. -
DOC: note sgml_parse/2 does not use PL_scan_options() Explain that
the option loop is hand-written because call(Type, Goal) is an arity-2
option, and that these options therefore cannot be given as a dict. -
CLEANUP: use PL_scan_options() in new_sgml_parser/2 and open_dtd/3
Convert the hand-rolled option loops for the dtd option of
new_sgml_parser/2 and the dialect option of open_dtd/3. sgml_parse/2
is left hand-rolled: it has a call(Type, Goal) option of arity 2,
which PL_scan_options() cannot express.
Package ssl
-
ENHANCED: _ssl_context/4 uses PL_scan_options() Replace the hand-rolled
first-pass option loop in pl_ssl_context() with PL_scan_options(),
using OPT_UNKNOWN_IGNORE so the malleable options still fall through to
parse_malleable_options(). The two options whose values are processed
in complex ways are refactored into get_crls() and get_cert_key_pairs()
helpers that take the value term; password/require_crl scan as
OPT_STRING/OPT_BOOL and the remaining values as OPT_TERM. Drops the
now-unused option-name atoms and the unused get_file_arg() helper. -
CLEANUP: use PL_scan_options() in the crypto option loops Convert
the hand-rolled option loops in crypto4pl.c:- hash_options: algorithm, hmac, close_parent and encoding.
- parse_options: encoding and padding (the atom-as-encoding shorthand
is kept).
-
MODIFIED: ed25519_sign/4 and ed25519_verify/4 default to encoding(utf8)
This matches Scryer Prolog. Unlike ecdsa_sign/4 and rsa_sign/4,
which default tohexbecause they are typically applied to a hash
of the data, Ed25519 signs the data itself. -
TEST: Ed25519 and X25519 against the RFC 8032 and RFC 7748 test
vectors Also documents the new predicates in the crypto library manual. -
ADDED: load_private_key/3 and load_public_key/2 support
Ed25519 and X25519 Ed25519 private keys are unified as
private_key(ed25519(KeyPair)), where KeyPair is the hexadecimal PKCS#8
v2 key pair that ed25519_sign/4 of library(crypto) accepts. X25519 keys
are unified as x25519(Hex), which curve25519_scalar_mult/3 accepts.
This allows using keys created withopenssl genpkey -algorithm ed25519
(or x25519). -
ADDED: #156 Ed25519 signatures and X25519 key exchange library(crypto)
now provides ed25519_new_keypair/1, ed25519_seed_keypair/2,
ed25519_keypair_public_key/2, ed25519_sign/4, ed25519_verify/4,
curve25519_generator/1 and curve25519_scalar_mult/3. The API is
that of Scryer Prolog’s library(crypto). Key pairs are PKCS#8 v2
(RFC 8410), the format used byopenssl genpkey -algorithm ed25519. -
FIXED: single-threaded build of crypto4pl crypto_lib_init() sat
inside an #ifdef _REENTRANT block but is called unconditionally from
install_crypto4pl(). OpenSSL >= 1.1.0 is thread safe, so the guard
is dead — drop it and keep the stub compiled in all configurations.
Package swipy
-
ENHANCED:
builtins' resolves to the builtins module, not its dict Previously the special-cased atombuiltins’ returned
PyEval_GetBuiltins(), which is the builtins dict. That worked
for arity>=1 calls via builtin_function() (which does dict lookup) but
made py_call(builtins:list, X, [py_object(true)]) raise AttributeError,
since the dict has no attribute `list’. -
FIXED: py_call/N leaked exception from the initial-target probe
py_eval() probes the first argument as a Python object or module.
If that probe failed with an exception (e.g. PyImport_Import(“list”)
raising ModuleNotFoundError) but the fallback builtins path then
succeeded, py_call/N returned success with the exception still pending,
triggering `did not clear exception’. Propagate the exception instead.
Package tipc
- CLEANUP: use PL_scan_options() in tipc_receive/4 Replace the hand-rolled
option loop with PL_scan_options(). as is scanned as a term for its
domain check; nonblock uses OPT_BOOL, so it is accepted both as the
bare atom and as nonblock(Bool).
Package utf8proc
-
BUILD: doc generation racing ahead of foreign plugin builds
-
CLEANUP: use PL_scan_options() for the unicode mapping flags
get_map_mask() accepted a list of bare atom flags (stable, compose, …)
OR-ed into a mask. These are now scanned with PL_scan_options() as
arity-0 OPT_BOOL options (so a flag may also be written flag(true)),
using OPT_UNKNOWN_ERROR to keep raising domain_error(unicode_mapping,
_) on an unknown flag. An integer mask is still accepted directly.
Package xpce
-
CLEANUP: Changed timer time to
num(wasreal) and use xpce int
for SDL reference. -
ENHANCED: timer: keep a scheduled timer alive and destroy it when done
A scheduled timer now holds a code reference to itself, so a timer
that is not referenced from elsewhere can simply be created and started: -
FIXED: toc_directory: crash if the directory disappeared ->update
deletes the node if its directory no longer exists (common under
e.g. /proc), after which ->refresh and ->expand_all continued to use
the freed node. -
ENHANCED: Prolog Navigator: virtual root for multiple Windows drives
If the loaded source files have no common directory because they are
spread over multiple Windows drives, the new class toc_roots provides
a virtual root (“This computer”) holding these drives. Pressing “up”
on a drive root now creates this node as well. -
ENHANCED: Prolog Navigator starts from the loaded source files The
Navigator is now rooted at the common directory of all loaded source
files and initially shows only the loaded files and the directories
leading to them, rather than browsing the file system from the
working directory. -
ENHANCED: Windows: flat scroll bars with a thin thumb The `win’
look now fills the trough with the light system colour and draws the
thumb in a darker shade at about 1/5th of the width of the scroll bar,
widening to 1/3th while the pointer is inside the bar. This replaces
the dark trough with a raised 3-D bubble and is much closer to the
native Windows look. -
FIXED: SDL: generate area_enter and area_exit events for windows
SDL only reports enter and leave for its native windows, which are
our frames. As xpce windows never received these events, PceWindow
<->has_pointer was never updated and the <->pointed chain of a window
was only maintained as long as the pointer stayed in the same window. -
FIXED: Epilog terminal wide glyph right half wiped by placeholder
r_clear The paint-run segmentation in rlc_paint_text() split segments
on flags.raw, but a wide char’s base has flags.width=2 while its
code-0 placeholder has flags.width=0, so base and placeholder ended
up in separate segments. The placeholder’s own r_clear/paint step
(chunk width = cw) then wiped the right half of the glyph the base had
just drawn. The same latent split applies to width-0 combining marks
following their base. Followers (code==0 placeholders or width==0
combiners) now stay in the current base’s segment regardless of
flags.raw, since they inherit the base’s styling and armed status. -
FIXED: Epilog terminal draws BMP symbol glyphs (dingbats, misc symbols)
as 2 cells uchar_display_width() classifies from static Unicode
tables + host wcwidth, which reports width 1 for BMP symbol blocks
(Dingbats U+2700-U+27BF, Misc Symbols U+2600-U+26FF, Misc Technical,
some arrows) that emoji-presenting fonts actually render at ~2 cells
wide, breaking the terminal grid. rlc_put() now consults the font’s
own measured advance via c_width() when the static classification
is width 1 and the char is non-ASCII, promoting to width 2 when
the glyph exceeds 1.5x the base cell width. Reuses the SDL font’s
existing lazy per-code-point width cache, so the Pango measurement
happens at most once per (font, char). -
CLEANUP: Remove hacks to redirect xpce messages to Epilog. As we
now rebind the main threaduser_outputanduser_errorstreams, we
no longer need hacks to redirect messages printed by xpce. If such
messages are generated in a thread, they are printed in the Epilog
console of that thread. If they are generated in the main (gui) thread,
they are redirected to the main Epilog console. Deleting this console
causes subsequent output to go to the process stdout/stderr streams. -
ENHANCED: Rebind main thread output to Epilog window. Rather than
intercepting print_message/2 to redirect messages from the GUI
(main) thread to the Epilog console, we rebind theuser_outputand
user_errorof themainthread to the main Epilog console. -
ADDED: date<-time_zone and date<-dst; use numeric offset in <-rfc_string
<-time_zone returns the local zone as a numeric offset (default) or as
the abbreviation (with @on). <-dst reports whether daylight-saving
time is in effect. <-rfc_string now emits the numeric offset,
matching RFC 5322 3.3 which obsoletes zone abbreviations. -
FIXED: Non-functioning Epilog Help/GUI demos menu. The code behind
this item was broken and a functioning entry is in the GUI menu. -
ADDED:
xdot->loadto accept either a file or a string. Instead, we
pipe the string through graphviz, This now used by random_terms_demo.pl
to avoid the need for temporary files. -
ENHANCED: use push_prolog_flag/2 for flag scoping with_hyperlink_term/1
(epilog.pl) and auto_call/1 (swi_compatibility.pl, autoload flag). -
FIXED: xpce numeric conversion: rationals, bignums, fractional nums
Two related fixes plus a test suite: -
ADDED: xdot_group url slot populated from graphviz URL/href Nodes and
edges now expose their graphviz URL attribute (or its href alias) as a
urlslot. Click handlers wired via <-node_clicked and <-edge_clicked
can fetch it with get(Group, url, URL). -
ADDED: Random terms demo Uses library(random_terms) with
library(graphviz_term) to generate random Prolog terms and visualise
them as graphs. A dialog exposes the generator parameters as sliders
(int/float) plus text_items for functors and atoms. The xdot_window
is configured with natural_zoom 1.5 so small terms fill the pane. -
ADDED: library(graphviz_term), converting Prolog terms into
.dot
files Emits Graphviz digraphs where each compound is a node whose HTML
label (shape=plaintext,<TABLE>/<TD PORT="aN">) carries a soft
pastel palette: a bold steel-blue functor cell plus per-primitive-
type backgrounds for integer, float, rational, atom, string, var,
and shared / cyclic back-references. Colours can be overridden by
redefining type_color/2. -
ENHANCED: xdot_window: <->natural_zoom slot for ->fit Adds a
natural_zoom slot (num, default 1.0). ->fit uses it as the preferred
scale: when the graph fits the visible area at natural_zoom that scale
is used; otherwise ->fit falls back to the shrink-to-fit behaviour.
Setting natural_zoom above 1.0 lets small graphs be enlarged on ->fit. -
REMOVED: library(pce_edit), providing pce_edit/1. Editing xpce
objects is provided by the hookable edit/1 infrastructure. -
ADDED: library(xdot) + demo — graphviz pan/zoom viewer New Prolog
library and xpce demo that renders graphviz-laid-out graphs as XPCE
graphicals. -
FIXED: edit/1 support for xpce classes.
-
ENHANCED: colour: <-fade(factor) — same RGB with alpha multiplied
New send/get method colour<-fade(factor=[0.0..1.0]) → colour returns a
colour with the same RGB and alpha := alpha * factor, clamped to 0..255.
Complements <-hilite and <-reduce; uses the same associateColour
caching so repeated calls with the same factor return the same object. -
ENHANCED: ellipse, circle: shape-precise ->in_event_area + ->inside
Share ellipseNormDistance() (in ellipse.c, exported via proto.h):
the normalised distance of a point from the centre of the ellipse
inscribed in an axis-aligned bounding box. <= 1 means inside;
semi-axes clamped to 1 to survive degenerate 0-width shapes. -
ENHANCED: path: precise event hit-test, ->inside, ref manual Register
inEventAreaPath via setInEventAreaFunctionClass so events land on
the actual path rather than its bounding rectangle: -
ENHANCED: bezier_curve: precise event hit-test on the curve Register
inEventAreaBezier via setInEventAreaFunctionClass so the graphical
class dispatcher runs a shape-accurate hit test after the bounding-box
pre-filter, mirroring what class line already does with inEventAreaLine. -
ADDED: xpce: class gradient with cairo linear/radial rendering Native
cairo-backed gradient class usable as fill_pattern: -
FIXED: pan_zoom: zoom around cursor when figure isn’t at (0,0) The zoom
formula used the cursor position in window coords as the fixed point,
which only matches the figure’s origin when the figure is displayed at
(0,0). Subtract the figure’s display position so the scale pivots
on the actual cursor location regardless of where the figure lives
in its parent.
Package yaml
- CLEANUP: use PL_scan_options() in yaml_emitter_create/3 Convert
the hand-rolled option loop for the canonical and unicode options,
scanned as terms so the “unicode defaults to true when not given”
behaviour is preserved.
Package zlib
- CLEANUP: use PL_scan_options() in zopen/3 Replace the hand-rolled
option loop with PL_scan_options(). format and level are scanned as
terms for their domain checks; close_parent and multi_part use OPT_BOOL.