Did you know ... Search Documentation:
Title for pldoc(default)
Branch: development (switch to stable),
version to version

SWI-Prolog Changelog from version 10.1.7 to 10.1.8

[May 28 2026]

  • DOC: macOS .pkg installer build, signing, notarization and cert renewal Add doc/MacOSXInstaller.md: an end-to-end, reproducible guide to building the signed and notarized macOS .pkg --- one-time keychain and Developer-ID/notarytool setup, the build invocation, result verification, certificate renewal, and the failure modes hit on the Apple-Silicon + macOS 26 host.
  • ADDED: macOS: `ninja pkg' builds a signed, notarized split-layout .pkg installer Add a `pkg' target producing a single Developer-ID-signed and Apple-notarized .pkg that delivers swipl-win.app to /Applications and swipl.framework to /Library/Frameworks.
  • ADDED: macOS: swipl.framework and the split swipl-win.app bundle layout Package the macOS runtime as a standalone swipl.framework and arrange the split bundle layout the installer ships: swipl-win.app in /Applications, swipl.framework in /Library/Frameworks.

[May 25 2026]

  • FIXED: Reset cached JIT index decisions when the supervisor changes. The per-argument assessed flags, jiti_tried, pindex_verified, fixed_indexes and unindexed memoize index decisions for the current clause shape. A supervisor change is the signal that this shape has changed enough that those verdicts may be stale. Without a reset, a "not indexable" verdict made on a transient state (e.g., while an autoload triggered through trapUndefined() re-enters Prolog) could stick and disable JIT indexing for the eventual stable clause set.

[May 18 2026]

  • MODIFIED: PL_predicate() now takes UTF-8 strings as argument.
  • DOC: Modernized calc.c, cacl.pl example. Replaceing PR 1493

[May 17 2026]

  • DOC: Unicode bracket-pair atoms are consistent with {} Document that an empty Unicode bracket pair (optionally layout-only) reads as the two-character atom, that atom before '(' is a functor, and '<open><close>'(X) writes as <open>X<close> with the bare atom unquoted, all governed by the brace_terms write option.
  • TEST: Unicode bracket-pair atoms (read/write consistency with {}) Covers empty/layout pair reading as the atom, '<o><c>'(X) as a compound, unquoted bare-atom output, write_canonical functor form, round-tripping and that {} is unchanged.
  • ENHANCED: Make Unicode bracket-pair atoms consistent with {} A matching Unicode bracket pair (Ps/Pe) now behaves like {}: an empty pair, optionally with layout in between, reads as the atom '<open><close>' (and as a functor when followed by '('), while '<open><close>'(X) writes as <open>X<close> and the bare atom is written unquoted. E.g. ⟨⟩ reads as '⟨⟩', ⟨⟩(x) as '⟨⟩'(x), and '⟨⟩'(hello) writes as ⟨hello⟩.

[May 15 2026]

  • FIXED: Avoid crash trying to destroy a running engine from another thread.

[May 13 2026]

  • ADDED: code_type/2 and char_type/2 property pattern_syntax Exposes Unicode UAX #31 Pattern_Syntax membership through the standard ctype dispatch. Useful for libraries that want to align tokenisation or quoting with the immutable syntax set, and for inspecting which code points the write_term/2 pattern_syntax_solo option will treat as stable.
  • ADDED: write_term/2 option pattern_syntax_solo, used by write_canonical/1 A new boolean write_term/2 option quotes single-character atoms whose code point is not in the immutable UAX #31 Pattern_Syntax set, so atoms like '€', '·', '🎉' round-trip safely across Unicode versions instead of relying on classifications that may shift in future releases. write_canonical/1 enables the option by default; plain write/1 and writeq/1 are unchanged.
  • FIXED: compare/3 on wide atoms must order by code point, not code unit On platforms with 16-bit wchar_t (Windows), a supplementary character is stored as a UTF-16 surrogate pair whose lead unit lives in U+D800..U+DBFF. compareUCSAtom() compared raw wchar_t values, so a non-BMP atom like '\U0001D11E' wrongly ordered below BMP atoms in U+DC00..U+FFFF — e.g. compare(C, '\U0001D11E', '豈') (with U+F900) returned < on Windows where Linux (32-bit wchar_t) gave the correct >.
  • FIXED: Reject surrogate code points in UTF-8 and UTF-16 stream decoders. A well-formed UTF-8 sequence never encodes a surrogate (RFC 3629), and a well-formed UTF-16 sequence never produces a lone trail surrogate. Both decoders previously let such malformed input through, so a file containing the bytes ED A0 80 read with encoding(utf8) would deliver U+D800 as a code point — leaking an invalid Unicode value into atoms and strings even though the new PL_get_char / Sputcode checks reject surrogates everywhere else.
  • FIXED: Reject UTF-16 surrogate code points at every Prolog API surface. Extends the recent fix to atom_codes/2 to put_code/1,2, put_char/1,2, put/1,2 and the format/2,3 ~c directive: PL_get_char() and the ~c argument check now use VALID_CODE_POINT(), so a lone surrogate is rejected with type_error(character_code, Code) (or format_argument_type for ~c) before it can reach the stream layer. As defence in depth, Sputcode() in pl-stream.c now calls reperror() on a surrogate before encoding-specific handling, preventing foreign callers from emitting invalid UTF-8 or raw-wchar bytes via Sputcode(0xD800, s).
  • FIXED: Do not allow surrogate pair code points in atom_codes/2.

[May 12 2026]

  • FIXED: Solo characters do not needs quotes
  • MODIFIED: Code walker not to track below call/1. This allows using call(Goal) in places that are false possitives for the detection of undefined predicates.

[May 11 2026]

  • FIXED: Confusable detection when using zero-arity compounds.
  • ENHANCED: char_type/2 and code_type/2 accept prolog_solo The kernel has a f_is_prolog_solo helper (and a corresponding SOLO category in the syntax map) but did not expose it through the char_type/2 catalogue. Register prolog_solo alongside prolog_symbol, prolog_atom_start and friends in src/os/pl-ctype.c, with a new atom in src/ATOMS, and document the class in the char_type/2 reference (man/builtin.plx).
  • ENHANCED: library(check) gets list_confusable_identifiers/{0,1} A new consistency check that walks every clause in the modules in module_class (default [user]) and warns on atoms whose written form is a UTS #39 spoof:
  • ENHANCED: '\''$needs_quotes'\''/1 + fix unquoted_atom for UCS atoms Exposes the kernel's own quote decision as a semidet '\''$needs_quotes'\''/1 so library code (notably library(check)'s confusable-identifier linter) can ask "would writeq quote this atom?" without re-parsing the name.

Package clib

[May 28 2026]

  • FIXED: bsd-crypt.c: unconditional include of "crypt.h" breaks build when no system crypt.h is available On glibc >= 2.39 the crypt() function is no longer in libc; when libcrypt-dev is also absent (e.g. some PPA build chroots), CMake's HAVE_CRYPT and HAVE_LIBCRYPT both fail and the build falls back to the bsd-crypt.c implementation, which then failed because it unconditionally included "crypt.h". The DES_ONLY define already excludes the only consumers of anything declared there, so guard the include with HAVE_CRYPT_H, matching the pattern in crypt.c.

Package cpp

[May 19 2026]

  • DOC: document the PlEncoding API in pl2cpp.plx Document the PlEncoding enum and the ENC_INPUT/ENC_OUTPUT defaults, the trailing-PlEncoding constructor/method forms and the deprecated argument-order constructors. Add a PlFunctor section and state that PlModule/PlPredicate/PlFunctor/PlCompound functor names are UTF-8. Replace the stale EncLatin1/EncUTF8/EncLocale enumerators, correct the unify_*() wrapper descriptions and escape & for the PDF build.

Package http

[May 28 2026]

  • TEST: proxy: reserve the `unused' port by holding a bound (unlistened) socket Concurrent ctest jobs that allocate ports dynamically (bind to port 0) could grab the port the proxy tests had pre-allocated for the `unused' role, causing connections that should be refused to instead succeed against an unrelated test server. Keeping a bound socket on that port for the duration of the suite reserves the port number while still producing ECONNREFUSED on connect(), since no tcp_listen/2 is called. SO_REUSEADDR is intentionally omitted on the held socket.

Package libedit

[May 20 2026]

  • ADDED: Bind Ctrl+Left/Right to word motion Maps the xterm sequences ESC[1;5D and ESC[1;5C, sent by the Epilog terminal, to ed-prev-word and em-next-word. In vi mode the same sequences are also bound in the command (alternative) keymap to vi-prev-word and vi-next-word.

Package ltx2htm

[May 12 2026]

  • FIXED: #8 Handling e.g., \\const{\%h}

Package pldoc

[May 18 2026]

  • CLEANUP: As we go through luatex, we no longer need utf8proc as dependency

Package utf8proc

[May 17 2026]

  • ADDED: library(uniname) exporting unicode_name/2 Wraps the compact name table in a SWI plugin (uniname4pl.c) and a library (uniname.pl). unicode_name(?CodePoint, ?Name) is nondet: (+,-) is the semidet forward name, (-,+) the semidet reverse lookup, and (-,-) enumerates every named code point on backtracking via a stateful foreign iterator (no quadratic blow-up; >100k solutions in ~50 ms). Registered as the utf8proc:uniname ctest.
  • ADDED: Prototype compact Unicode code-point -> name table Adds etc/gen_uniname.pl, the generated uniname_data.{c,h} and a small decoder (uniname.c) implementing the ICU / GNU libunistring scheme: algorithmic ranges (Hangul synthesised from Jamo; CJK/Tangut and every PREFIX-<cphex> family derived from the code point) carry no per-code- point data, and the remaining ~34.6k names are stored as a flat LEB128 stream of a code-point delta plus frequency-ordered word ids into a shared word table.

[May 11 2026]

Package xpce

[May 25 2026]

  • FIXED: Hold a code reference on Frame across the FLASH_END SDL event flash_end_callback() pushes MY_EVENT_FLASH_END carrying a raw FrameObj pointer. Same UAF shape as the Timer case: if the frame is destroyed and reused before the consumer in CtoEvent() runs, the F_FREED check reads stale memory. Take a code reference around the queue and skip the push entirely when the frame is already being freed.
  • FIXED: Hold a code reference on Timer across the SDL event queue tm_callback() pushes MY_EVENT_TIMER carrying a raw Timer pointer. If the Timer is destroyed and its memory freed/reused before the main thread consumes the event, the F_FREEING|F_FREED check in sdl_timer_event() reads stale memory. Mirror the FDWatch pattern: addCodeReference() before SDL_PushEvent(), delCodeReference() in the consumer so the object stays in F_FREEING (memory alive) until the queued event is drained.
  • FIXED: Register Epilog pty slave_fd as a drainable console (POSIX) So that ws_discard_input() drops keystrokes the user typed at an Epilog terminal window while a modal confirmer is up. Uses tcflush(TCIFLUSH) on the slave fd, which drops kernel-buffered bytes without consuming them and therefore does not race with the Prolog engine reading the same fd.
  • FIXED: Register stdin as a drainable console when it is a terminal So that ws_discard_input() drops pending bytes typed at the terminal while a modal confirmer is up. Skipped silently when stdin is redirected (e.g. Epilog spawning swipl with stdin closed).
  • FIXED: ws_discard_input() reads stale fd after socket-based dispatch hook Replace the static dispatch_fd cache with a small console registry, populated by the host on init (stdin) and by terminal.c for Epilog ptys. ws_dispatch() now only watches an fd transiently for the duration of one call, never caching it as a global; ws_discard_input() iterates the registry and uses tcflush()/FlushConsoleInputBuffer() instead of read(), avoiding races with engines reading the same fd.

[May 20 2026]

  • ADDED: Send xterm Ctrl+Left/Right escape sequences from the terminal Ctrl modifier on cursorLeft/cursorRight now produces ESC[1;5D / ESC[1;5C so libedit (or any xterm-compatible reader) can bind these to word motion.

[May 17 2026]

  • ADDED: PceEmacs: normalize_region/normalize_buffer M-x commands to apply a Unicode normalization form (nfc, nfd, nfkc, nfkd) to the region or the whole buffer. Conditional on the optional library(unicode).
  • ADDED: PceEmacs/epilog: insert_symbol command (C-x 8 RET / C-x 8 s) C-x 8 is a prefix in PceEmacs and the epilog terminal; it opens the symbol picker targeting the invoking editor/terminal.
  • ADDED: library(pce_symbol_picker) for picking Unicode symbols A non-modal singleton (and modal pick_symbol/1) to browse Unicode blocks and curated code ranges, type the picked symbol into the focused window, and remember recents. Supports code_range/3 user ranges, matching pairs, and a filter that searches either block names or Unicode character names.
  • FIXED: man class hierarchy: correct builtin/user class icons
  • ADDED: display_manager <->focus_message: hook on keyboard-focus change Fires the given message when a frame gains or loses the keyboard focus, so tools can track the active application window.
  • ENHANCED: text<-pointed: add round option (caret vs hit-test) <-pointed takes an extra argument selecting caret-style rounding (snap to nearest gap) versus exact hit-testing.
  • ENHANCED: text_item: optional clear-field image Add a ->clear_image slot to class text_item. When set (use @default for the standard clear-text.svg icon), a clickable image appears at the right of the entry field while it is non-empty; clicking it clears the field. The space is reserved as soon as the image is set so the field does not reflow when the icon appears. Restricted to style `normal'.

[May 15 2026]

  • ADDED: window->pdf: print the full window contents Graphical->pdf saves <-area, i.e. only the visible part of a window. Override it on window to use <-bounding_box (the union of all graphicals) so scrolled or oversized content is printed in full, with the page offset so the bounding box maps onto the page.
  • FIXED: graphical->pdf: negate the page offset pdfGraphical() created a page sized to <-area but set d_offset() to +area->x,+area->y. Since drawing primitives add the offset, a graphical at a non-zero position was shifted off the page, producing a blank PDF. Negate the offset so the graphical's area maps onto the page origin.
  • FIXED: text<-pointed: hit-test with Pango layout, not per-char c_width get_pointed_text() summed c_width() per character to map a click to a character index. For proportional fonts and strings needing font fallback (e.g. the symbol picker showing emoji/Greek/math), that sum drifts from the actual rendered glyph positions, so clicks selected the wrong symbol.

[May 14 2026]

  • FIXED: xpce printf %c: handle non-ASCII code points Routed %c through snprintf which collapses the int argument to a single byte and produced invalid UTF-8 for any code point above 0x7F. Handle %c separately: Put() takes a uchar_t (uint32_t) which already carries a full code point, and put_void_str promotes the target string to wide as needed. Width and left-align flags from the format spec are still honoured.