<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>