YAP 7.1.0
console.c
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: readline.c *
12* Last rev: 5/2/88 *
13* mods: *
14* comments: Input/Output C implemented predicates *
15* *
16*************************************************************************/
17
27/*
28 * This file includes the interface to the console IO, tty style. Refer also to
29 the readline library.
30 * @defgroup console Support for console-based interaction.
31 * @ingroup InputOutput
32
33 */
34
35#include "sysbits.h"
36
37static Int prompt(USES_REGS1);
38static Int prompt1(USES_REGS1);
39
40static int ConsoleGetc(int);
41static int ConsolePutc(int, int);
42
43
44
45bool Yap_DoPrompt(StreamDesc *s) {
46 if (LOCAL_newline) {
47 return false;
48 }
49 return true;
50}
51
52
53/* check if we read a newline or an EOF */
54int console_post_process_read_char(int ch, StreamDesc *s) {
55 /* the character is also going to be output by the console handler */
56 console_count_output_char(ch, GLOBAL_Stream + LOCAL_c_error_stream);
57 if (ch == '\r') {
58 s->linestart = s->charcount;
59 LOCAL_newline = true;
60} else
61 if (ch == '\n') {
62 CACHE_REGS
63 ++s->linecount;
64 ++s->charcount;
65 s->linestart = s->charcount;
66 LOCAL_newline = true;
67 } else if (ch != EOF) {
68 CACHE_REGS
69 ++s->charcount;
70 LOCAL_newline = false;
71 }
72 return ch;
73}
74
75bool is_same_tty(FILE *f1, FILE *f2) {
76#if HAVE_TTYNAME
77 char buf1[MAX_PATH], buf2[MAX_PATH];
78 return ttyname_r(fileno(f1), buf1, MAX_PATH - 1) ==
79 ttyname_r(fileno(f2), buf2, MAX_PATH - 1);
80#endif
81 // assume a single console, for now
82 return true;
83}
84
85static Int is_same_tty2(USES_REGS1) { /* 'prompt(Atom) */
86 int sni = Yap_CheckStream(ARG1, Input_Stream_f, "put/2");
87 int sno = Yap_CheckStream(ARG2, Output_Stream_f, "put/2");
88 bool out = (GLOBAL_Stream[sni].status & Tty_Stream_f) &&
89 (GLOBAL_Stream[sno].status & Tty_Stream_f) &&
90 is_same_tty(GLOBAL_Stream[sno].file, GLOBAL_Stream[sni].file);
91 UNLOCK(GLOBAL_Stream[sno].streamlock);
92 UNLOCK(GLOBAL_Stream[sni].streamlock);
93 return out;
94}
95
96void Yap_ConsoleOps(StreamDesc *s) {
97 /* the putc routine only has to check it is putting out a newline */
98 s->stream_putc = ConsolePutc;
99 s->stream_getc = ConsoleGetc;
100#if USE_READLINE
101 /* if a tty have a special routine to call readline */
102 if ((s->status & Readline_Stream_f) && trueGlobalPrologFlag(READLINE_FLAG)) {
103 if (Yap_ReadlineOps(s))
104 return;
105 }
106#endif
107}
108
109/* static */
110static int ConsolePutc(int sno, int ch) {
111 StreamDesc *s = &GLOBAL_Stream[sno];
112 if (ch == 10) {
113#if MAC || _WIN32
114 fputs("\n", s->file);
115#else
116 putc('\n', s->file);
117#endif
118 LOCAL_newline = true;
119 } else
120 putc(ch, s->file);
121#if MAC || _WIN32
122 fflush( NULL );
123#endif
124 console_count_output_char(ch, s);
125 return ((int)ch);
126}
127
128/* send a prompt, and use the system for internal buffering. Speed is
129 not of the essence here !!! */
130static int ConsoleGetc(int sno) {
131 CACHE_REGS
132 register StreamDesc *s = &GLOBAL_Stream[sno];
133 int ch;
134
135 /* keep the prompt around, just in case, but don't actually
136 show it in silent mode */
137 if (Yap_DoPrompt(s)) {
138 if (!silentMode()) {
139 char *cptr = LOCAL_Prompt, ch;
140 Yap_clearInput(LOCAL_c_error_stream);
141 strncpy(LOCAL_Prompt, (char *)RepAtom(LOCAL_AtPrompt)->StrOfAE, MAX_PROMPT);
142 /* use the default routine */
143 while ((ch = *cptr++) != '\0') {
144 GLOBAL_Stream[StdErrStream].stream_putc(StdErrStream, ch);
145 }
146 }
147 }
148#if 0
149#if HAVE_SIGINTERRUPT
150 siginterrupt(SIGINT, TRUE);
151#endif
152 LOCAL_PrologMode |= ConsoleGetcMode;
153 ch = fgetc(s->file);
154#if HAVE_SIGINTERRUPT
155 siginterrupt(SIGINT, FALSE);
156#endif
157 if (LOCAL_PrologMode & InterruptMode) {
158 Yap_external_signal(0, YAP_INT_SIGNAL);
159 LOCAL_PrologMode &= ~ConsoleGetcMode;
160 LOCAL_newline = TRUE;
161 if (LOCAL_PrologMode & AbortMode) {
162 Yap_Error(ABORT_EVENT, TermNil, "");
163 LOCAL_ErrorMessage = "Abort";
164 return EOF;
165 }
166 goto restart;
167 } else {
168 LOCAL_PrologMode &= ~ConsoleGetcMode;
169 }
170#else
171 LOCAL_PrologMode |= ConsoleGetcMode;
172 ch = fgetc(s->file);
173 LOCAL_PrologMode |= ConsoleGetcMode;
174#endif
175 LOCAL_PrologMode &= ~ InterruptMode;
176 if (ch == EOF)
177 return console_post_process_eof(s);
178 return console_post_process_read_char(ch, s);
179}
180
189static Int prompt1(USES_REGS1) { /* prompt1(Atom) */
190 Term t = Deref(ARG1);
191 Atom a;
192 if (IsVarTerm(t) || !IsAtomTerm(t))
193 return (FALSE);
194 LOCAL_AtPrompt = a = AtomOfTerm(t);
195 if (strlen((char *)RepAtom(a)->StrOfAE) > MAX_PROMPT) {
196 Yap_Error(SYSTEM_ERROR_INTERNAL, t, "prompt %s is too long",
197 RepAtom(a)->StrOfAE);
198 return (FALSE);
199 }
200 strncpy(LOCAL_Prompt, (char *)RepAtom(a)->StrOfAE, MAX_PROMPT);
201 return (TRUE);
202}
203
210static Int prompt(USES_REGS1) { /* prompt(Old,New) */
211 Term t = Deref(ARG2);
212 Atom a;
213 if (!Yap_unify_constant(ARG1, MkAtomTerm(LOCAL_AtPrompt)))
214 return (FALSE);
215 if (IsVarTerm(t) || !IsAtomTerm(t))
216 return (FALSE);
217 a = AtomOfTerm(t);
218 if (strlen(RepAtom(a)->StrOfAE) > MAX_PROMPT) {
219 Yap_Error(SYSTEM_ERROR_INTERNAL, t, "prompt %s is too long",
220 RepAtom(a)->StrOfAE);
221 return false;
222 }
223 strncpy(LOCAL_Prompt, (char *)RepAtom(LOCAL_AtPrompt)->StrOfAE, MAX_PROMPT);
224 LOCAL_AtPrompt = a;
225 return (TRUE);
226}
227
234static Int ensure_prompting(USES_REGS1) { /* prompt(Old,New) */
235 if (!LOCAL_newline) {
236 GLOBAL_Stream[2].stream_wputc(2, 10); // hack!
237 }
238 return true;
239}
240
241int Yap_GetCharForSIGINT(void) {
242 CACHE_REGS
243 int ch;
244#if USE_READLINE
245 if (trueGlobalPrologFlag(READLINE_FLAG) ||
246 (ch = Yap_ReadlineForSIGINT()) == 0)
247#endif
248 { /* ask for a new line */
249 fprintf(stderr, "Action (h for help): ");
250 ch = getc(stdin);
251 /* first process up to end of line */
252 while ((fgetc(stdin)) != '\n')
253 ;
254 }
255 LOCAL_newline = TRUE;
256 fflush(NULL);
257 return ch;
258}
259
260void Yap_InitConsole(void) {
261 CACHE_REGS
262 LOCAL_newline = true;
263 Yap_InitCPred("prompt", 1, prompt1, SafePredFlag | SyncPredFlag);
264 Yap_InitCPred("prompt1", 1, prompt1, SafePredFlag | SyncPredFlag);
265 Yap_InitCPred("$is_same_tty", 2, is_same_tty2,
266 SafePredFlag | SyncPredFlag | HiddenPredFlag);
267 Yap_InitCPred("prompt", 2, prompt, SafePredFlag | SyncPredFlag);
268 Yap_InitCPred("$ensure_prompting", 0, ensure_prompting,
269 SafePredFlag | SyncPredFlag);
270}
int(* stream_getc)(int)
function the stream uses for writing a character
Definition: YapStreams.h:256