1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5 1992 Stephen R. Whiteley
6 ****************************************************************************/
7
8 /*
9 * Initial lexer.
10 */
11
12 /***************************************************************************
13 To implement command completion under DOS, one must define TIOCSTI in
14 os_msdos.h, and add routines mygetc() and ioctl() which do the right
15 things, i.e., allow stuffing characters into the input buffer. In DOS,
16 ^A and ^Z call the abort routine in interactive mode. ^D signals command
17 match printing and can be first on a line unlike in UNIX. Beware that
18 some compilers supply an ioctl() routine which won't work here, if this
19 is the case, you may have to define ioctl to something else in os_msdos.h.
20 ****************************************************************************/
21
22 #include "spice.h"
23 #include "cpdefs.h"
24 #include <errno.h>
25
26 #include <sys/types.h>
27
28 #ifdef HAVE_SGTTY_H
29 #include <sgtty.h>
30 #else
31 #ifdef HAVE_TERMIO_H
32 #include <termio.h>
33 #else
34 #ifdef HAVE_TERMIOS_H
35 #include <termios.h>
36 #endif
37 #endif
38 #endif
39
40 #include "ftegraph.h"
41
42 #ifdef __STDC__
43 static void prompt(void);
44 #else
45 static void prompt();
46 #endif
47
48 FILE *cp_inp_cur = NULL;
49 int cp_event = 1;
50 bool cp_interactive = true;
51 bool cp_bqflag = false;
52 char *cp_promptstring = NULL;
53 char *cp_altprompt = NULL;
54 char cp_hash = '#';
55
56 static int numeofs = 0;
57
58 #define ESCAPE '\033'
59
60 /* Return a list of words, with backslash quoting and '' quoting done.
61 * Strings en(void) closed in "" or `` are made single words and returned,
62 * but with the "" or `` still present. For the \ and '' cases, the
63 * 8th bit is turned on (as in csh) to prevent them from being recogized,
64 * and stripped off once all processing is done. We also have to deal with
65 * command, filename, and keyword completion here.
66 * If string is non-NULL, then use it instead of the fp. Escape and EOF
67 * have no business being in the string.
68 */
69
70 #define newword cw->wl_word = copy(buf); \
71 cw->wl_next = alloc(struct wordlist); \
72 cw->wl_next->wl_prev = cw; \
73 cw = cw->wl_next; \
74 bzero(buf, BSIZE_SP); \
75 i = 0;
76
77
78 wordlist *
cp_lexer(string)79 cp_lexer(string)
80
81 char *string;
82 {
83 int c;
84 int i, j;
85 wordlist *wlist = NULL, *cw = NULL;
86 char buf[BSIZE_SP], linebuf[BSIZE_SP], d;
87
88 if (cp_inp_cur == NULL)
89 cp_inp_cur = cp_in;
90
91 if (!string && cp_interactive) {
92 cp_ccon(true);
93 prompt();
94 }
95 nloop:
96 i = 0;
97 j = 0;
98 bzero(linebuf, BSIZE_SP);
99 bzero(buf, BSIZE_SP);
100 wlist = cw = alloc(struct wordlist);
101 cw->wl_next = cw->wl_prev = NULL;
102 for (;;) {
103 if (string) {
104 c = *string++;
105 if (c == '\0')
106 c = '\n';
107 if (c == ESCAPE)
108 c = '[';
109 }
110 else
111 c = DevGetchar(cp_inp_cur);
112 gotchar:
113 if ((c != EOF) && (c != ESCAPE) && (c != 4)) /* SRW - 4 added */
114 linebuf[j++] = c;
115 if (c != EOF && c != 4) /* SRW - ditto */
116 numeofs = 0;
117 if (i == BSIZE_SP - 1) {
118 fprintf(cp_err, "Warning: word too long.\n");
119 c = ' ';
120 }
121 if (j == BSIZE_SP - 1) {
122 fprintf(cp_err, "Warning: line too long.\n");
123 if (cp_bqflag)
124 c = EOF;
125 else
126 c = '\n';
127 }
128 if (c != EOF)
129 c = strip(c); /* Don't need to do this really. */
130
131 /* "backslash" quoting */
132 if (c == '\\' && DIR_TERM != '\\' || c == '\026' /* ^V */ ) {
133 c = quote(string ? *string++ : DevGetchar(cp_inp_cur));
134 linebuf[j++] = strip(c);
135 }
136
137 if ((c == '\n') && cp_bqflag)
138 c = ' ';
139 if ((c == EOF || c == 4) && cp_bqflag) /* SRW - 4 added */
140 c = '\n';
141 if ((c == cp_hash) && !cp_interactive && (j == 1)) {
142 if (string)
143 return (NULL);
144 while (((c = DevGetchar(cp_inp_cur)) != '\n') &&
145 (c != EOF));
146 goto nloop;
147 }
148 switch (c) {
149
150 case ' ':
151 case '\t':
152 if (i > 0) {
153 newword;
154 }
155 break;
156
157 case '\n':
158 if (i) {
159 buf[i] = '\0';
160 cw->wl_word = copy(buf);
161 }
162 else if (cw->wl_prev) {
163 cw->wl_prev->wl_next = NULL;
164 tfree(cw);
165 }
166 else {
167 cw->wl_word = NULL;
168 }
169 goto done;
170
171 case '\'':
172 while (((c = (string ? *string++ :
173 DevGetchar(cp_inp_cur))) != '\'')
174 && (i < BSIZE_SP - 1)) {
175 if ((c == '\n') || (c == EOF) || (c == ESCAPE))
176 goto gotchar;
177 else {
178 buf[i++] = quote(c);
179 linebuf[j++] = c;
180 }
181 }
182 linebuf[j++] = '\'';
183 break;
184
185 case '"':
186 case '`':
187 d = c;
188 buf[i++] = d;
189 while (((c = (string ? *string++ : DevGetchar(cp_inp_cur)))
190 != d) && (i < BSIZE_SP - 2)) {
191 if ((c == '\n') || (c == EOF) || (c == ESCAPE))
192 goto gotchar;
193 else if (c == '\\') {
194 linebuf[j++] = c;
195 c = (string ? *string++ :
196 DevGetchar(cp_inp_cur));
197 buf[i++] = quote(c);
198 linebuf[j++] = c;
199 }
200 else {
201 buf[i++] = c;
202 linebuf[j++] = c;
203 }
204 }
205 buf[i++] = d;
206 linebuf[j++] = d;
207 break;
208
209 case EOF:
210 case 4: /* ^D */
211
212 if (cp_interactive && !cp_nocc &&
213 (string == NULL)) {
214 #ifdef notdef
215 /* ^D logout */
216 if (j == 0) {
217 if (cp_ignoreeof && (numeofs++
218 < 23)) {
219 fputs(
220 "Use \"quit\" to quit.\n",
221 stdout);
222 }
223 else {
224 fputs("quit\n", stdout);
225 cp_doquit();
226 }
227 goto done;
228 }
229 #endif
230 cp_ccom(wlist, buf, false);
231 wl_free(wlist);
232 (void) fputc('\r', cp_out);
233 prompt();
234 for (j = 0; linebuf[j]; j++)
235 #ifdef TIOCSTI
236 /* SRW - below was cp_out, a bug */
237 (void) ioctl(fileno(cp_in), TIOCSTI,
238 linebuf + j);
239 #else
240 fputc(linebuf[j], cp_out); /* But you can't edit */
241 #endif
242 goto nloop;
243 }
244 else { /* EOF during a source */
245
246 if (cp_interactive) {
247 fputs("quit\n", stdout);
248 cp_doquit();
249 goto done;
250 }
251 else
252 return (NULL);
253 }
254 case ESCAPE:
255 if (cp_interactive && !cp_nocc) {
256
257 fputs("\b\b \b\b\r", cp_out);
258 prompt();
259 for (j = 0; linebuf[j]; j++)
260 #ifdef TIOCSTI
261 /* SRW - below was cp_out, a bug */
262 (void) ioctl(fileno(cp_in), TIOCSTI,
263 linebuf + j);
264 #else
265 fputc(linebuf[j], cp_out); /* But you can't edit */
266 #endif
267 cp_ccom(wlist, buf, true);
268 wl_free(wlist);
269 goto nloop;
270 } /* Else fall through */
271
272 default:
273 /* We have to remember the special cases $<, $&, $#&, $?& */
274 if ((cp_chars[c] & CPC_BRL) && (i > 0)) {
275 switch (c) {
276
277 case '<':
278 if (buf[i-1] == '$')
279 break;
280 { newword; }
281 break;
282
283 case '&':
284 if (buf[i-1] == '$')
285 break;
286 if (i > 1 && (buf[i-1] == '#' || buf[i-1] == '?') &&
287 buf[i-2] == '$')
288 break;
289 { newword; }
290 break;
291
292 default:
293 { newword; }
294 }
295 }
296
297 buf[i++] = c;
298
299 /* have to also catch <=, >=, and <> */
300
301 if (cp_chars[c] & CPC_BRR) {
302 switch (c) {
303
304 case '<':
305 if (i > 1 && buf[i-2] == '$')
306 break;
307
308 case '>':
309 d = c;
310 if (string) {
311 c = *string++;
312 if (c == '\0')
313 c = '\n';
314 if (c == ESCAPE)
315 c = '[';
316 }
317 else
318 c = DevGetchar(cp_inp_cur);
319
320 if (c == '=' || (d == '<' && c == '>')) {
321 buf[i++] = c;
322 linebuf[j++] = c;
323 { newword; }
324 break;
325 }
326 { newword; }
327 goto gotchar;
328
329 case '&':
330 if (i > 1 && buf[i-2] == '$')
331 break;
332 if (i > 2 && (buf[i-2] == '#' || buf[i-2] == '?') &&
333 buf[i-3] == '$')
334 break;
335 { newword; }
336 break;
337
338 default:
339 { newword; }
340 }
341 }
342 }
343 }
344 done:
345 return (wlist);
346 }
347
348
349 static void
prompt()350 prompt()
351 {
352 char *s;
353
354 if (cp_interactive == false)
355 return;
356 if (cp_promptstring == NULL)
357 s = "-> ";
358 else
359 s = cp_promptstring;
360 if (cp_altprompt)
361 s = cp_altprompt;
362
363 while (*s) {
364 switch (strip(*s)) {
365 case '!':
366 fprintf(cp_out, "%d", cp_event);
367 break;
368 case '\\':
369 if (*(s + 1))
370 (void) putc(strip(*++s), cp_out);
371
372 /* SRW -p prints cwd */
373 case '-':
374 if (*(s+1) == 'p') {
375 char *c, *getcwd();
376 (void) fprintf(cp_out,"%s",c = getcwd(NULL,128));
377 tfree(c);
378 s++;
379 break;
380 }
381 default:
382 (void) putc(strip(*s), cp_out);
383 }
384 s++;
385 }
386 (void) fflush(cp_out);
387 return;
388 }
389