18static char SccsId[] =
"%W% %G%";
50#define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
56#if defined(HAVE_LIBREADLINE)
58#include <readline/history.h>
59#include <readline/readline.h>
61static int ReadlineGetc(
int);
63static const char *history_file;
65#define READLINE_OUT_BUF_MAX 256
67static Int usable_readline(USES_REGS1) {
69 if ((!(GLOBAL_Stream[StdInStream].status & Tty_Stream_f) ||
70 !(GLOBAL_Stream[StdOutStream].status & Tty_Stream_f))) {
73 if (getenv(
"PMIX_ID")) {
76 if (getenv(
"INSIDE_EMACS")) {
88typedef struct scan_atoms {
93static char *atom_enumerate(
const char *prefix,
int state) {
95 struct scan_atoms *
index;
100 index = (
struct scan_atoms *)malloc(
sizeof(
struct scan_atoms));
105 index = LOCAL_search_atoms;
110 while (catom != NIL || i < AtomHashTableSize) {
117 READ_LOCK(HashChain[i].AERWLock);
118 catom = HashChain[i].Entry;
119 READ_UNLOCK(HashChain[i].AERWLock);
123 READ_LOCK(ap->ARWLock);
125 if (strstr(ap->StrOfAE, prefix) == (
char *)ap->StrOfAE) {
127 index->atom = ap->NextOfAE;
128 LOCAL_search_atoms =
index;
129 READ_UNLOCK(ap->ARWLock);
132 catom = ap->NextOfAE;
133 READ_UNLOCK(ap->ARWLock);
136 LOCAL_search_atoms = NULL;
141static char *atom_generator(
const char *prefix,
int state) {
142 char *s = atom_enumerate(prefix, state);
145 char *copy = malloc(1 + strlen(s));
155typedef struct chain {
160static char *predicate_enumerate(
const char *prefix,
int state,
char *buf0,
170 m0.
NextME = CurrentModules;
171 if (mod->AtomOfME == AtomIDB)
175 p = LOCAL_SearchPreds;
176 cmod = (p->ModuleOfPred != PROLOG_MODULE ? p->ModuleOfPred : TermProlog);
177 mod = Yap_GetModuleEntry(cmod);
182 p = p->NextPredOfModule;
187 LOCAL_SearchPreds = NULL;
190 if (mod->AtomOfME == AtomIDB)
195 char *c = RepAtom(ap = NameOfPred(p))->StrOfAE;
196 if (strlen(c) > strlen(prefix) && strstr(c, prefix) == c &&
197 !(p->PredFlags & HiddenPredFlag)) {
198 LOCAL_SearchPreds = p;
199 arity_t ar = p->ArityOfPE;
201 if (Yap_IsPrefixOp(AbsAtom(ap), &l, &r) && ar == 1) {
208 strncat(buf0,
"(", MAX_PATH);
212 LOCAL_SearchPreds = NULL;
216static char *predicate_generator(
const char *prefix,
int state) {
218 char *buf = malloc(PATH_MAX + 1);
219 char *s = predicate_enumerate(prefix, state, buf, PATH_MAX);
222 char *copy = malloc(1 + strlen(s));
232static char **prolog_completion(
const char *text,
int start,
int end) {
233 char **matches = NULL;
234 const char *pt = text + strlen(text), *pt0 = pt;
236 while (--pt >= text) {
237 if (isalnum(pt[0]) || pt[0] ==
'_')
242 matches = rl_completion_matches(pt + 1, predicate_generator);
247 while (isspace(text[i++]) && i <= end)
251 if ((strstr(p,
"[") == p) || (strstr(p,
"compile(") == p) ||
252 (strstr(p,
"consult(") == p) || (strstr(p,
"load_files(") == p) ||
253 (strstr(p,
"reconsult(") == p) || (strstr(p,
"use_module(") == p) ||
254 (strstr(p,
"cd(") == p))
255 matches = rl_completion_matches((
char *)p,
256 rl_filename_completion_function);
259 return rl_completion_matches((
char *)text, atom_generator);
262void Yap_ReadlineFlush(
int sno) {
263 if (GLOBAL_Flags && trueGlobalPrologFlag(READLINE_FLAG)) {
264 if (GLOBAL_Stream[sno].status & Tty_Stream_f &&
265 GLOBAL_Stream[sno].status & Output_Stream_f) {
271bool Yap_readline_clear_pending_input(
StreamDesc *s) {
272 if (GLOBAL_Flags && trueGlobalPrologFlag(READLINE_FLAG)) {
273#if HAVE_RL_CLEAR_PENDING_INPUT
274 rl_clear_pending_input();
277 free((
void *)s->u.irl.buf);
279 s->u.irl.ptr = s->u.irl.buf = NULL;
286 if (GLOBAL_Flags && trueGlobalPrologFlag(READLINE_FLAG)) {
287 if (GLOBAL_Stream[0].status & (Input_Stream_f | Tty_Stream_f) &&
288 is_same_tty(s->file, GLOBAL_Stream[0].file)) {
292 s->status |= Readline_Stream_f;
298extern bool Yap_Embedded;
300bool Yap_InitReadline(Term enable) {
302 if (enable != TermTrue || !usable_readline()) {
304 setBooleanGlobalPrologFlag(READLINE_FLAG,
false);
307 GLOBAL_Stream[StdInStream].u.irl.buf = NULL;
308 GLOBAL_Stream[StdInStream].u.irl.ptr = NULL;
309 GLOBAL_Stream[StdInStream].status |= Readline_Stream_f;
317 if (read_history(s) != 0) {
318 FILE *f = fopen(s,
"a");
323 rl_readline_name =
"YAP Prolog";
324 rl_attempted_completion_function = prolog_completion;
327 setBooleanGlobalPrologFlag(READLINE_FLAG,
true);
328 return Yap_ReadlineOps(GLOBAL_Stream + StdInStream);
331#if !HAVE_RL_SET_SIGNALS
332#define rl_clear_signals()
333#define rl_set_signals()
337static bool getLine(
int inp) {
339 rl_instream = GLOBAL_Stream[inp].file;
340 const unsigned char *myrl_line = NULL;
342 Yap_set_sigaction(SIGINT,Yap_ReadlineForSIGINT);
343 LOCAL_PrologMode |= ConsoleGetcMode;
345 myrl_line = (
unsigned char *)
readline(LOCAL_Prompt);
347 Yap_set_sigaction(SIGINT,Yap_HandleSIGINT);
348 LOCAL_PrologMode &= ~ConsoleGetcMode;
349#if HAVE_RL_PENDING_SIGNAL
350 if (rl_pending_signal()) {
351 LOCAL_PrologMode |= InterruptMode;
354 if (LOCAL_PrologMode & InterruptMode) {
357 LOCAL_newline =
true;
359 strncpy(LOCAL_Prompt, RepAtom(LOCAL_AtPrompt)->StrOfAE, MAX_PROMPT);
361 if (myrl_line == NULL)
363 if (myrl_line[0] !=
'\0' && myrl_line[1] !=
'\0') {
364 add_history((
char *)myrl_line);
365 history_truncate_file(history_file, 300);
366 write_history(history_file);
368 s->u.irl.ptr = s->u.irl.buf = myrl_line;
370 LOCAL_PrologMode |= ConsoleGetcMode;
371 LOCAL_PrologMode &= ~ InterruptMode;
381static int ReadlineGetc(
int sno) {
384 bool fetch = (s->u.irl.buf == NULL);
388 if (!GLOBAL_Flags || falseGlobalPrologFlag(READLINE_FLAG)) {
389 Yap_DefaultStreamOps(s);
394 LOCAL_PrologMode |= ConsoleGetcMode;
396 return console_post_process_eof(s);
399 const unsigned char *ttyptr = s->u.irl.ptr, *myrl_line = s->u.irl.buf;
400 if (!myrl_line) ch =
'\n';
405 free((
void *)myrl_line);
406 s->u.irl.ptr = s->u.irl.buf = NULL;
407 }
else { s->u.irl.ptr ++;
410 return console_post_process_read_char(ch, s);
421int Yap_ReadlinePeekChar(
int sno) {
426 const unsigned char *ttyptr = s->u.irl.ptr;
437 ch = s->u.irl.ptr[0];
442 LOCAL_newline =
true;
444 LOCAL_newline =
false;
452int Yap_ReadlineForSIGINT(
void) {
456 const unsigned char *myrl_line = s->u.irl.buf;
457 if ((LOCAL_PrologMode & ConsoleGetcMode) && myrl_line != NULL) {
459 free((
void *)myrl_line);
464 myrl_line = (
const unsigned char *)
readline(
"Action (h for help): ");
470 free((
void *)myrl_line);
480bool Yap_InitReadline(Term enable) {
482 setBooleanGlobalPrologFlag(READLINE_FLAG,
false);
487static Int has_readline(USES_REGS) {
return usable_readline(); }
489void Yap_InitReadlinePreds(
void) {
490 Yap_InitCPred(
"$has_readline", 0, has_readline,
491 SafePredFlag | HiddenPredFlag);
494void Yap_CloseReadline(
void) {
496 write_history(history_file);
497 history_truncate_file(history_file, 300);
const char * Yap_AbsoluteFile(const char *spec, bool ok)
generate absolute path, if ok first expand SICStus Prolog style
@ readline
readline(boolean, changeable) }
Module property: low-level data used to manage modes.
struct mod_entry * NextME
Module local flags (from SWI compat)
int(* stream_getc)(int)
function the stream uses for writing a character
int(* stream_wpeek)(int)
check if the next character is available
int(* stream_peek)(int)
function the stream uses for parser