<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">It all works beautifully, as expected but when I use CTRL-D it balks with this output:<div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">*** Mercury runtime: caught segmentation violation ***</font></div><div class=""><font face="Courier New" class="">cause: address not mapped to object</font></div><div class=""><font face="Courier New" class="">address involved: 0x0</font></div><div class=""><font face="Courier New" class="">This may have been caused by a stack overflow, due to unbounded recursion.</font></div><div class=""><font face="Courier New" class="">exiting from signal handler</font></div><div class=""><font face="Courier New" class="">[1]    68417 segmentation fault  ./felt -r</font></div></div><div class=""><br class=""></div><div class="">I have attached the full FFI code at the end. I’ve tried to work it through. The source code for the input function is here:</div><div class=""><br class=""></div><div class="">I studied the source code, it is using fgets() which returns NULL on end-of-file and I thought I was managing that just fine!</div><div class="">Does Mercury have something to with this e.g. a SIGINT handler or something that might be clashing with the linenoise-ng code I wonder ?</div><div class=""><br class=""></div><div class="">The calling code in my REPL loop is as follows:</div><div class=""><br class=""></div><div class=""><font face="Courier New" class="">:- pred run_loop(<br class="">    command_line.felt_options::in,<br class="">    replcon::in, replcon::out,<br class="">    io::di, io::uo) is det.<br class=""><br class="">run_loop(Options, !Repl, !IO) :-<br class="">    ln_read(prompt, Line, LineNull, !IO),<br class="">    io.format("LNG: NULL:%d, len:%d, \n", [i(LineNull), i(length(Line))], !IO),<br class="">    (if LineNull = 1 then<br class="">        io.format("\n%sBe excellent to one another.\n",<br class="">             [s(prompt)], !IO)<br class="">    else<br class="">        execute(Line, !Repl, !IO),<br class="">        run_loop(Options, !Repl, !IO)<br class="">    ).</font></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">I shall continue to investigate but The Boss wants me to mow the lawns first :|</div><div class="">Sean</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">%---------------------------------------------------------------------------%<br class="">%<br class="">%   LINENOISE library support.<br class="">%<br class="">    % I am using the linenoise-ng variant that supports UTF-8. It can be<br class="">    % found here, it builds and executes without error.<br class="">    % <a href="https://github.com/arangodb/linenoise-ng" class="">https://github.com/arangodb/linenoise-ng</a><br class=""><br class="">:- pragma foreign_decl("C", "#include <linenoise.h>").<br class=""><br class="">:- pred ln_setup(string::in, int::in, io::di, io::uo) is det.<br class="">:- pred ln_shutdown(string::in, io::di, io::uo) is det.<br class="">:- pred ln_read(string::in, string::out, int::out, io::di, io::uo) is det.<br class="">:- pred ln_free(string::in, io::di, io::uo) is det.<br class=""><br class="">    % ln_read: Reads and returns a single line.<br class="">    % Line is unified with whataver the library read from stdin.<br class="">    % LineNull is unified with 1 if NULL(CTRL+D) is detected, else 0.<br class="">    % If the line is not empty then we automatically add it to the history.<br class="">    %<br class="">:- pragma foreign_proc(<br class="">    "C",<br class="">    ln_read(Prompt::in, Line::out, LineNull::out, IOin::di, IOout::uo),<br class="">    [will_not_throw_exception, promise_pure],<br class="">    "<br class="">    char* line = linenoise((const char*)Prompt);<br class="">    if (line) {<br class="">        linenoiseHistoryAdd(line);<br class="">        LineNull = 0;<br class="">        Line = line;<br class="">    } else {<br class="">        LineNull = 1;<br class="">    }<br class="">    printf(\"leaving, strlen() is %d\\n\", strlen(line));<br class="">    IOout = IOin;<br class="">    "<br class="">).<br class=""><br class="">    % ln_free: Release a previosuly read line.<br class="">    % In order to prevent memory leaks, after the REPL has dealt with the<br class="">    % user input this must be called to hand the memory back to the pool.<br class="">    %<br class="">:- pragma foreign_proc(<br class="">    "C",<br class="">    ln_free(Line::in, IOin::di, IOout::uo),<br class="">    [will_not_throw_exception, promise_pure],<br class="">    "<br class="">    free(Line);<br class="">    IOout = IOin;<br class="">    "<br class="">).<br class=""><br class="">    % ln_setup: Initialise a linenoise session.<br class="">    % I have chosen the to always have multiline modfe enabled as it is<br class="">    % probably the `expected` way it should operate by the user.<br class="">    % HistoryFile contains the name of the persisence file when ending.<br class="">    % HistoryMax contains the limit on the history size to maintain.<br class="">    %<br class="">:- pragma foreign_proc(<br class="">    "C",<br class="">    ln_setup(HistoryFile::in, HistoryMax::in, IOin::di, IOout::uo),<br class="">    [will_not_throw_exception, promise_pure],<br class="">    "<br class="">    linenoiseHistorySetMaxLen(HistoryMax);<br class="">    linenoiseSetMultiLine(1);<br class="">    linenoiseHistoryLoad((const char*)HistoryFile);<br class="">    IOout = IOin;<br class="">    "<br class="">).<br class=""><br class="">    % ln_shutdown: Stop using the linenoise library.<br class="">    % HistoryFile contains the file to save session history into.<br class="">    % After saving, we then formally release the history session memory.<br class="">    %<br class="">:- pragma foreign_proc(<br class="">    "C",<br class="">    ln_shutdown(HistoryFile::in, IOin::di, IOout::uo),<br class="">    [will_not_throw_exception, promise_pure],<br class="">    "<br class="">    linenoiseHistorySave((const char*)HistoryFile);<br class="">    linenoiseHistoryFree();<br class="">    IOout = IOin;<br class="">    "<br class="">).<br class=""><br class=""></font></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>