Error during compilation (V9.3.32):

I checked out via “git checkout V9.3.32” from “https://github.com/SWI-Prolog/swipl-devel” and compiled in a build directory via cmake and make:


[ 65%] Building C object src/CMakeFiles/swiplobjs.dir/pl-funct.c.o
/home/ox_external_source/sources_external/swi-prolog-github/swipl-devel/src/pl-funct.ic:320:9: error: ‘ATOM_xpceref’ undeclared here (not in a function); did you mean ‘ATOM_spare’?
  320 | FUNCTOR(ATOM_xpceref, 1),
      |         ^~~~~~~~~~~~
/home/ox_external_source/sources_external/swi-prolog-github/swipl-devel/src/pl-funct.c:296:25: note: in definition of macro ‘FUNCTOR’
  296 | #define FUNCTOR(n, a) { n, a }
      |                         ^
make[2]: *** [src/CMakeFiles/swiplobjs.dir/build.make:212: src/CMakeFiles/swiplobjs.dir/pl-funct.c.o] Fehler 1
make[2]: *** Es wird auf noch nicht beendete Prozesse gewartet....
make[1]: *** [CMakeFiles/Makefile2:2708: src/CMakeFiles/swiplobjs.dir/all] Fehler 2
make: *** [Makefile:182: all] Fehler 2

I get the same error message in V9.3.31. I just tried out master and now I get

[ 92%] Generating odbc.bib
Error copying file (if different) from "/home/ox_external_source/sources_external/swi-prolog-github/swipl-devel/packages/odbc/odbc.bib" to "odbc.bib".
make[2]: *** [packages/odbc/CMakeFiles/odbc.doc.html.dir/build.make:93: packages/odbc/odbc.bib] Fehler 1
make[1]: *** [CMakeFiles/Makefile2:10315: packages/odbc/CMakeFiles/odbc.doc.html.dir/all] Fehler 2
make: *** [Makefile:182: all] Fehler 2

I just touched the missing file and recompiled and installed it. But It shows version nr 9.3.20-1-g1ded30f09-DIRTY after the start.

That can only mean master is not the current development branch.

Ok, I cloned in a completely new directory and built again (master, 9.3.32-16-g508550cf3). Flawless install.

But editline doesn’t work as expected. Remember: never touch a running readline.

swipl doesn’t read the ~/.editrc

It is. I guess something when wrong updating (some modified file in the day?), you did not update the submodules, … If this happens again, try git status, git log or git describe to verify all is clean an at the intended version.

Good question. Maybe it doesn’t. You can load it explicitly using

 ?- el_source(user_input, _).

The second argument is the file to load. If unbound it should read ~/.editrc.

P.s. No need to install, you can just run swipl or swipl-win from the src directory inside the build directory. That allows for running multiple versions compiled with different options easily.

1 Like

Ok there was still an entry in the ~/.config/swi-prolog/init.pl

:- set_prolog_flag( readline, readline).

That was the reason for the missing history.

And I’m using now :- el_bind(user_input, ['-v']). in the config file (it works), but this doesn’t work in a .pl file.

el_source(user_input, _). doesn’t work in the config file.

But it read the ~/.editrc on el_source(user_input, '/home/ox/.editrc'). So it could work.

Ok. Added a warning for that.

What do you mean with “config file” and “.pl file”.

The way to configure the library is by defining editline:el_setup/1. This is called when the library is initialised for a stream. E.g.

:- multifile editline:el_setup/1

editline:el_setup(Stream) :-
     el_bind(user_input, ['-v']),
     el_source(user_input, _).

Of course, this must be loaded before the editline is activated on Stream. The normal init.pl file is loaded early enough.

A variable should work as it passes NULL to el_source(), which claims

el_source()
Initialize editline by reading the contents of file. el_parse() is called for each line in file. If file is NULL, try $EDITRC and if that is not set $HOME/.editrc. Refer to editrc(5) for details on the format of file. el_source() returns 0 on success and -1 on error.

I cannot reproduce the error I which I had. Currently it works when My file starts with:

#!/usr/local/bin/swipl -s

:- el_bind(user_input, ['-v']).

But of course it is no longer needed since it works with the init.pl file.

The warning is ok. But I believe I made an observation mistake. I startet swipl in the homedirectory and saw the history (after I commented out the readline directive in the init.pl) but my projecthistory in a project directory was gone before that. And now I understood that we have a history pro directory.

And there was a time when I saw the raw codings per keypress in the console (with the old readline directive) but even that I cannot reproduce.

But I remember there were still old binaries running in parallel (idle). Maybe that created some effects. idk.

Readline provided me a marker (ins, cmd) which showed me in which vi state the current commandline is. I hope I find something similar in editline.

That has been the case for a long time, also with readline AFAIK. The queries of another project are rarely useful …

What does that mean?

History is saved on program exit. That is one of the things I still have my doubt about. It works fine for a single instance, but if you run multiple instances of Prolog in the same directory you only have the history of the last one you closed. Should we instead simply add the last command to the history file immediately? That also ensures the history is preserved in case of a hard crash.

I don’t know. The underlying libedit seems to be under active development. Besides, you can program it from Prolog :slight_smile: Checkout the Prolog API and if it does not provide what you are after (I fear that is the case here) the C API for libedit. You can also raise a feature request with the original BSD project.

So, now it’s reproducible:

When I have in the ~/.config/swi-prolog/init.pl

:- set_prolog_flag( readline, readline).
:- el_bind(user_input, ['-v']).

Then I see a warning

$ swipl
ERROR: /home/ox/.config/swi-prolog/init.pl:23:
ERROR:    editline:el_bind/2: Domain error: `libedit_input' expected, found `user_input'
Warning: /home/ox/.config/swi-prolog/init.pl:23:
Warning:    Goal (directive) failed: user:el_bind(user_input,['-v'])
Welcome to SWI-Prolog (threaded, 64 bits, version 9.3.32-16-g508550cf3)
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).

Warning: [Thread main] library `library(readline)' does not exist

and I have “raw keypresses” on cursor keys and esc in the console like ^[[D^[[A^[[C^[[B^[ (and no history) .

But that’s ok with the new readline warning.

When I have in the ~/.config/swi-prolog/init.pl

:- el_source(user_input, _).

‘~/.editrc’ is not read.

When I call it directly, it is only read when I provide the filename.

?- el_source(user_input, _).
true.

?- el_source(user_input, '.editrc').
true.
$ inotifywait .editrc 
Setting up watches.
Watches established.
.editrc OPEN # on el_source(user_input, '.editrc').

When I call el_source(el, NULL) from a c program then ~/.editrc isn’t read.
When I call el_source(el, "/home/ox/.editrc") from a c program it is read.

The first case is, what pl_source from ./packages/libedit/libedit4pl.c is doing, when term_t file is a variable.

I’m on debian 11 And I use

ii libedit-dev:amd64 3.1-20191231-2+b1 amd64 BSD editline and history libraries (development files)

As far as I understand should el_source(el, NULL) read the ~/.editrc file but it don’t . So it is actually not a bug of Swi Prolog. But Swi Prolog relies on that.

As I said, the config file is read before commandline editing is enabled. That allows you to disable it, load something else, etc. (and in the old days select readline). So, to configure editline you have to use the library hook that is called after editline is activated on a stream. Copying from my earlier post:

Now it seems el_source/2 is broken due to a broken C library, At least, yours is not compatible with the docs of mine. In Fedora 42, el_source(user_input, _) does what it promises to do. The Ubuntu 22.04 docs are the same as the Fedora docs for el_source().

This is the code of of the el_source function of libedit-3.1-20191231 :

int
el_source(EditLine *el, const char *fname)
{
        FILE *fp;
        size_t len;
        ssize_t slen;
        char *ptr;
        char *path = NULL;
        const wchar_t *dptr;
        int error = 0;

        fp = NULL;
        if (fname == NULL) {
#ifdef HAVE_ISSETUGID
                if (issetugid())
                        return -1;

                if ((fname = getenv("EDITRC")) == NULL) {
                        static const char elpath[] = "/.editrc";
                        size_t plen = sizeof(elpath);

                        if ((ptr = getenv("HOME")) == NULL)
                                return -1;
                        plen += strlen(ptr);
                        if ((path = el_calloc(plen, sizeof(*path))) == NULL)
                                return -1;
                        (void)snprintf(path, plen, "%s%s", ptr,
                                elpath + (*ptr == '\0'));
                        fname = path;
                }
#else
                /*
                 * If issetugid() is missing, always return an error, in order
                 * to keep from inadvertently opening up the user to a security
                 * hole.
                 */
                return -1;
#endif
        }
...

It returns -1 if fname == NULL and if I don’t have the issetugid call which seems to come originally from openbsd.

It is still the same in

https://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libedit/el.c?rev=1.101.4.1;content-type=text%2Fplain

So I expect that I cannot fix it with an update of the libeditline2 libs.

We are getting a little off topic. There are quite a few different versions of this library floating around in various OSes. Looking at the Fedora sources, they provided a Linux friendly implementation of finding ~/.editrc. One could raise this as an issue with Debian as the docs claim this works, but the implementation doesn’t. Anyway, simply use this:

expand_file_name('~/.editrc', [File]),
el_source(user_input, File).
2 Likes