xref: /csrg-svn/old/dbx/scanner.c (revision 9679)
1*9679Slinton /* Copyright (c) 1982 Regents of the University of California */
2*9679Slinton 
3*9679Slinton static char sccsid[] = "@(#)@(#)scanner.c 1.1 12/15/82";
4*9679Slinton 
5*9679Slinton /*
6*9679Slinton  * Debugger scanner.
7*9679Slinton  */
8*9679Slinton 
9*9679Slinton #include "defs.h"
10*9679Slinton #include "scanner.h"
11*9679Slinton #include "main.h"
12*9679Slinton #include "keywords.h"
13*9679Slinton #include "tree.h"
14*9679Slinton #include "symbols.h"
15*9679Slinton #include "names.h"
16*9679Slinton #include "y.tab.h"
17*9679Slinton 
18*9679Slinton #ifndef public
19*9679Slinton typedef int Token;
20*9679Slinton #endif
21*9679Slinton 
22*9679Slinton public String initfile = ".dbxinit";
23*9679Slinton 
24*9679Slinton typedef enum { WHITE, ALPHA, NUM, OTHER } Charclass;
25*9679Slinton 
26*9679Slinton private Charclass class[256 + 1];
27*9679Slinton private Charclass *lexclass = class + 1;
28*9679Slinton 
29*9679Slinton #define isdigit(c) (lexclass[c] == NUM)
30*9679Slinton #define isalnum(c) (lexclass[c] == ALPHA or lexclass[c] == NUM)
31*9679Slinton #define ishexdigit(c) ( \
32*9679Slinton     isdigit(c) or (c >= 'a' and c <= 'f') or (c >= 'A' and c <= 'F') \
33*9679Slinton )
34*9679Slinton 
35*9679Slinton #define MAXLINESIZE 1024
36*9679Slinton 
37*9679Slinton private File in;
38*9679Slinton private Char linebuf[MAXLINESIZE];
39*9679Slinton private Char *curchar;
40*9679Slinton 
41*9679Slinton #define MAXINCLDEPTH 10
42*9679Slinton 
43*9679Slinton private struct {
44*9679Slinton     File savefile;
45*9679Slinton     Filename savefn;
46*9679Slinton     int savelineno;
47*9679Slinton } inclinfo[MAXINCLDEPTH];
48*9679Slinton 
49*9679Slinton private unsigned int curinclindex;
50*9679Slinton 
51*9679Slinton private Boolean firsttoken = true;
52*9679Slinton private Boolean firstinit = true;
53*9679Slinton 
54*9679Slinton private Token getident();
55*9679Slinton private Token getnum();
56*9679Slinton private Token getstring();
57*9679Slinton private Boolean eofinput();
58*9679Slinton private Char charcon();
59*9679Slinton private Char charlookup();
60*9679Slinton 
61*9679Slinton private enterlexclass(class, s)
62*9679Slinton Charclass class;
63*9679Slinton String s;
64*9679Slinton {
65*9679Slinton     register char *p;
66*9679Slinton 
67*9679Slinton     for (p = s; *p != '\0'; p++) {
68*9679Slinton 	lexclass[*p] = class;
69*9679Slinton     }
70*9679Slinton }
71*9679Slinton 
72*9679Slinton public scanner_init()
73*9679Slinton {
74*9679Slinton     register Integer i;
75*9679Slinton 
76*9679Slinton     for (i = 0; i < 257; i++) {
77*9679Slinton 	class[i] = OTHER;
78*9679Slinton     }
79*9679Slinton     enterlexclass(WHITE, " \t");
80*9679Slinton     enterlexclass(ALPHA, "abcdefghijklmnopqrstuvwxyz");
81*9679Slinton     enterlexclass(ALPHA, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_$");
82*9679Slinton     enterlexclass(NUM, "0123456789");
83*9679Slinton     in = stdin;
84*9679Slinton     errfilename = nil;
85*9679Slinton     errlineno = 0;
86*9679Slinton     curchar = linebuf;
87*9679Slinton     linebuf[0] = '\0';
88*9679Slinton     if (runfirst) {
89*9679Slinton 	firstinit = false;
90*9679Slinton 	firsttoken = false;
91*9679Slinton     } else if (firstinit and isterm(in)) {
92*9679Slinton 	firstinit = false;
93*9679Slinton 	printf("> ");
94*9679Slinton 	fflush(stdout);
95*9679Slinton     }
96*9679Slinton }
97*9679Slinton 
98*9679Slinton /*
99*9679Slinton  * Read a single token.
100*9679Slinton  *
101*9679Slinton  * Input is line buffered.
102*9679Slinton  *
103*9679Slinton  * There are two "modes" of operation:  one as in a compiler,
104*9679Slinton  * and one for reading shell-like syntax.
105*9679Slinton  */
106*9679Slinton 
107*9679Slinton private Boolean shellmode;
108*9679Slinton 
109*9679Slinton public Token yylex()
110*9679Slinton {
111*9679Slinton     register int c;
112*9679Slinton     register char *p;
113*9679Slinton     register Token t;
114*9679Slinton     String line;
115*9679Slinton 
116*9679Slinton     p = curchar;
117*9679Slinton     if (*p == '\0') {
118*9679Slinton 	do {
119*9679Slinton 	    if (isterm(in)) {
120*9679Slinton 		if (firsttoken) {
121*9679Slinton 		    firsttoken = false;
122*9679Slinton 		} else {
123*9679Slinton 		    printf("> ");
124*9679Slinton 		    fflush(stdout);
125*9679Slinton 		}
126*9679Slinton 	    }
127*9679Slinton 	    line = fgets(linebuf, MAXLINESIZE, in);
128*9679Slinton 	} while (line == nil and not eofinput());
129*9679Slinton 	if (line == nil) {
130*9679Slinton 	    c = EOF;
131*9679Slinton 	} else {
132*9679Slinton 	    p = linebuf;
133*9679Slinton 	    while (lexclass[*p] == WHITE) {
134*9679Slinton 		p++;
135*9679Slinton 	    }
136*9679Slinton 	    shellmode = false;
137*9679Slinton 	}
138*9679Slinton     } else {
139*9679Slinton 	while (lexclass[*p] == WHITE) {
140*9679Slinton 	    p++;
141*9679Slinton 	}
142*9679Slinton     }
143*9679Slinton     curchar = p;
144*9679Slinton     c = *p;
145*9679Slinton     if (lexclass[c] == ALPHA) {
146*9679Slinton 	t = getident();
147*9679Slinton     } else if (lexclass[c] == NUM) {
148*9679Slinton 	t = getnum();
149*9679Slinton     } else {
150*9679Slinton 	++curchar;
151*9679Slinton 	switch (c) {
152*9679Slinton 	    case '\n':
153*9679Slinton 		t = '\n';
154*9679Slinton 		if (errlineno != 0) {
155*9679Slinton 		    errlineno++;
156*9679Slinton 		}
157*9679Slinton 		break;
158*9679Slinton 
159*9679Slinton 	    case '"':
160*9679Slinton 	    case '\'':
161*9679Slinton 		t = getstring();
162*9679Slinton 		break;
163*9679Slinton 
164*9679Slinton 	    case '.':
165*9679Slinton 		if (shellmode) {
166*9679Slinton 		    --curchar;
167*9679Slinton 		    t = getident();
168*9679Slinton 		} else if (isdigit(*curchar)) {
169*9679Slinton 		    --curchar;
170*9679Slinton 		    t = getnum();
171*9679Slinton 		} else {
172*9679Slinton 		    t = '.';
173*9679Slinton 		}
174*9679Slinton 		break;
175*9679Slinton 
176*9679Slinton 	    case '<':
177*9679Slinton 		if (not shellmode and *curchar == '<') {
178*9679Slinton 		    ++curchar;
179*9679Slinton 		    t = LFORMER;
180*9679Slinton 		} else {
181*9679Slinton 		    t = '<';
182*9679Slinton 		}
183*9679Slinton 		break;
184*9679Slinton 
185*9679Slinton 	    case '>':
186*9679Slinton 		if (not shellmode and *curchar == '>') {
187*9679Slinton 		    ++curchar;
188*9679Slinton 		    t = RFORMER;
189*9679Slinton 		} else {
190*9679Slinton 		    t = '>';
191*9679Slinton 		}
192*9679Slinton 		break;
193*9679Slinton 
194*9679Slinton 	    case '#':
195*9679Slinton 		if (*curchar == '^') {
196*9679Slinton 		    ++curchar;
197*9679Slinton 		    t = ABSTRACTION;
198*9679Slinton 		} else {
199*9679Slinton 		    t = '#';
200*9679Slinton 		}
201*9679Slinton 		break;
202*9679Slinton 
203*9679Slinton 	    case '-':
204*9679Slinton 		if (shellmode) {
205*9679Slinton 		    --curchar;
206*9679Slinton 		    t = getident();
207*9679Slinton 		} else if (*curchar == '>') {
208*9679Slinton 		    ++curchar;
209*9679Slinton 		    t = ARROW;
210*9679Slinton 		} else {
211*9679Slinton 		    t = '-';
212*9679Slinton 		}
213*9679Slinton 		break;
214*9679Slinton 
215*9679Slinton 	    case EOF:
216*9679Slinton 		t = 0;
217*9679Slinton 		break;
218*9679Slinton 
219*9679Slinton 	    default:
220*9679Slinton 		if (shellmode and index("!&*()[]", c) == nil) {
221*9679Slinton 		    --curchar;
222*9679Slinton 		    t = getident();
223*9679Slinton 		} else {
224*9679Slinton 		    t = c;
225*9679Slinton 		}
226*9679Slinton 		break;
227*9679Slinton 	}
228*9679Slinton     }
229*9679Slinton #   ifdef LEXDEBUG
230*9679Slinton 	if (lexdebug) {
231*9679Slinton 	    fprintf(stderr, "yylex returns ");
232*9679Slinton 	    print_token(stderr, t);
233*9679Slinton 	    fprintf(stderr, "\n");
234*9679Slinton 	}
235*9679Slinton #   endif
236*9679Slinton     return t;
237*9679Slinton }
238*9679Slinton 
239*9679Slinton /*
240*9679Slinton  * Parser error handling.
241*9679Slinton  */
242*9679Slinton 
243*9679Slinton public yyerror(s)
244*9679Slinton String s;
245*9679Slinton {
246*9679Slinton     register Char *p, *tokenbegin, *tokenend;
247*9679Slinton     register Integer len;
248*9679Slinton 
249*9679Slinton     if (streq(s, "syntax error")) {
250*9679Slinton 	beginerrmsg();
251*9679Slinton 	tokenend = curchar - 1;
252*9679Slinton 	tokenbegin = tokenend;
253*9679Slinton 	while (lexclass[*tokenbegin] != WHITE and tokenbegin > &linebuf[0]) {
254*9679Slinton 	    --tokenbegin;
255*9679Slinton 	}
256*9679Slinton 	len = tokenend - tokenbegin + 1;
257*9679Slinton 	p = tokenbegin;
258*9679Slinton 	if (p > &linebuf[0]) {
259*9679Slinton 	    while (lexclass[*p] == WHITE and p > &linebuf[0]) {
260*9679Slinton 		--p;
261*9679Slinton 	    }
262*9679Slinton 	}
263*9679Slinton 	if (p == &linebuf[0]) {
264*9679Slinton 	    fprintf(stderr, "unrecognized command \"%.*s\"", len, tokenbegin);
265*9679Slinton 	} else {
266*9679Slinton 	    fprintf(stderr, "syntax error");
267*9679Slinton 	    if (len != 0) {
268*9679Slinton 		fprintf(stderr, " on \"%.*s\"", len, tokenbegin);
269*9679Slinton 	    }
270*9679Slinton 	}
271*9679Slinton 	enderrmsg();
272*9679Slinton     } else {
273*9679Slinton 	error(s);
274*9679Slinton     }
275*9679Slinton }
276*9679Slinton 
277*9679Slinton /*
278*9679Slinton  * Eat the current line.
279*9679Slinton  */
280*9679Slinton 
281*9679Slinton public gobble()
282*9679Slinton {
283*9679Slinton     curchar = linebuf;
284*9679Slinton     linebuf[0] = '\0';
285*9679Slinton }
286*9679Slinton 
287*9679Slinton /*
288*9679Slinton  * Scan an identifier and check to see if it's a keyword.
289*9679Slinton  */
290*9679Slinton 
291*9679Slinton private Token getident()
292*9679Slinton {
293*9679Slinton     char buf[256];
294*9679Slinton     register Char *p, *q;
295*9679Slinton     register Token t;
296*9679Slinton 
297*9679Slinton     p = curchar;
298*9679Slinton     q = buf;
299*9679Slinton     if (shellmode) {
300*9679Slinton 	do {
301*9679Slinton 	    *q++ = *p++;
302*9679Slinton 	} while (index(" \t\n!&<>*[]()", *p) == nil);
303*9679Slinton     } else {
304*9679Slinton 	do {
305*9679Slinton 	    *q++ = *p++;
306*9679Slinton 	} while (isalnum(*p));
307*9679Slinton     }
308*9679Slinton     curchar = p;
309*9679Slinton     *q = '\0';
310*9679Slinton     yylval.y_name = identname(buf, false);
311*9679Slinton     if (not shellmode) {
312*9679Slinton 	t = findkeyword(yylval.y_name);
313*9679Slinton 	if (t == nil) {
314*9679Slinton 	    t = NAME;
315*9679Slinton 	}
316*9679Slinton     } else {
317*9679Slinton 	t = NAME;
318*9679Slinton     }
319*9679Slinton     return t;
320*9679Slinton }
321*9679Slinton 
322*9679Slinton /*
323*9679Slinton  * Scan a number.
324*9679Slinton  */
325*9679Slinton 
326*9679Slinton private Token getnum()
327*9679Slinton {
328*9679Slinton     char buf[256];
329*9679Slinton     register Char *p, *q;
330*9679Slinton     register Token t;
331*9679Slinton     Integer base;
332*9679Slinton 
333*9679Slinton     p = curchar;
334*9679Slinton     q = buf;
335*9679Slinton     if (*p == '0') {
336*9679Slinton 	if (*(p+1) == 'x') {
337*9679Slinton 	    p += 2;
338*9679Slinton 	    base = 16;
339*9679Slinton 	} else {
340*9679Slinton 	    base = 8;
341*9679Slinton 	}
342*9679Slinton     } else {
343*9679Slinton 	base = 10;
344*9679Slinton     }
345*9679Slinton     if (base == 16) {
346*9679Slinton 	do {
347*9679Slinton 	    *q++ = *p++;
348*9679Slinton 	} while (ishexdigit(*p));
349*9679Slinton     } else {
350*9679Slinton 	do {
351*9679Slinton 	    *q++ = *p++;
352*9679Slinton 	} while (isdigit(*p));
353*9679Slinton     }
354*9679Slinton     if (*p == '.') {
355*9679Slinton 	do {
356*9679Slinton 	    *q++ = *p++;
357*9679Slinton 	} while (isdigit(*p));
358*9679Slinton 	if (*p == 'e' or *p == 'E') {
359*9679Slinton 	    p++;
360*9679Slinton 	    if (*p == '+' or *p == '-' or isdigit(*p)) {
361*9679Slinton 		*q++ = 'e';
362*9679Slinton 		do {
363*9679Slinton 		    *q++ = *p++;
364*9679Slinton 		} while (isdigit(*p));
365*9679Slinton 	    }
366*9679Slinton 	}
367*9679Slinton 	*q = '\0';
368*9679Slinton 	yylval.y_real = atof(buf);
369*9679Slinton 	t = REAL;
370*9679Slinton     } else {
371*9679Slinton 	*q = '\0';
372*9679Slinton 	switch (base) {
373*9679Slinton 	    case 10:
374*9679Slinton 		yylval.y_int = atol(buf);
375*9679Slinton 		break;
376*9679Slinton 
377*9679Slinton 	    case 8:
378*9679Slinton 		yylval.y_int = octal(buf);
379*9679Slinton 		break;
380*9679Slinton 
381*9679Slinton 	    case 16:
382*9679Slinton 		yylval.y_int = hex(buf);
383*9679Slinton 		break;
384*9679Slinton 
385*9679Slinton 	    default:
386*9679Slinton 		badcaseval(base);
387*9679Slinton 	}
388*9679Slinton 	t = INT;
389*9679Slinton     }
390*9679Slinton     curchar = p;
391*9679Slinton     return t;
392*9679Slinton }
393*9679Slinton 
394*9679Slinton /*
395*9679Slinton  * Convert a string of octal digits to an integer.
396*9679Slinton  */
397*9679Slinton 
398*9679Slinton private int octal(s)
399*9679Slinton String s;
400*9679Slinton {
401*9679Slinton     register Char *p;
402*9679Slinton     register Integer n;
403*9679Slinton 
404*9679Slinton     n = 0;
405*9679Slinton     for (p = s; *p != '\0'; p++) {
406*9679Slinton 	n = 8*n + (*p - '0');
407*9679Slinton     }
408*9679Slinton     return n;
409*9679Slinton }
410*9679Slinton 
411*9679Slinton /*
412*9679Slinton  * Convert a string of hexadecimal digits to an integer.
413*9679Slinton  */
414*9679Slinton 
415*9679Slinton private int hex(s)
416*9679Slinton String s;
417*9679Slinton {
418*9679Slinton     register Char *p;
419*9679Slinton     register Integer n;
420*9679Slinton 
421*9679Slinton     n = 0;
422*9679Slinton     for (p = s; *p != '\0'; p++) {
423*9679Slinton 	n *= 16;
424*9679Slinton 	if (*p >= 'a' and *p <= 'f') {
425*9679Slinton 	    n += (*p - 'a' + 10);
426*9679Slinton 	} else if (*p >= 'A' and *p <= 'F') {
427*9679Slinton 	    n += (*p - 'A' + 10);
428*9679Slinton 	} else {
429*9679Slinton 	    n += (*p - '0');
430*9679Slinton 	}
431*9679Slinton     }
432*9679Slinton     return n;
433*9679Slinton }
434*9679Slinton 
435*9679Slinton /*
436*9679Slinton  * Scan a string.
437*9679Slinton  */
438*9679Slinton 
439*9679Slinton private Token getstring()
440*9679Slinton {
441*9679Slinton     char buf[256];
442*9679Slinton     register Char *p, *q;
443*9679Slinton     Boolean endofstring;
444*9679Slinton 
445*9679Slinton     p = curchar;
446*9679Slinton     q = buf;
447*9679Slinton     endofstring = false;
448*9679Slinton     while (not endofstring) {
449*9679Slinton 	if (*p == '\n' or *p == '\0') {
450*9679Slinton 	    error("non-terminated string");
451*9679Slinton 	    endofstring = true;
452*9679Slinton 	} else if (*p == '"') {
453*9679Slinton 	    if (*(p+1) != '"') {
454*9679Slinton 		endofstring = true;
455*9679Slinton 	    } else {
456*9679Slinton 		*q++ = *p;
457*9679Slinton 	    }
458*9679Slinton 	} else {
459*9679Slinton 	    *q++ = charcon(*p);
460*9679Slinton 	}
461*9679Slinton 	p++;
462*9679Slinton     }
463*9679Slinton     curchar = p;
464*9679Slinton     *q = '\0';
465*9679Slinton     yylval.y_string = strdup(buf);
466*9679Slinton     return STRING;
467*9679Slinton }
468*9679Slinton 
469*9679Slinton /*
470*9679Slinton  * Process a character constant.
471*9679Slinton  * Watch out for backslashes.
472*9679Slinton  */
473*9679Slinton 
474*9679Slinton private Char charcon(ch)
475*9679Slinton Char ch;
476*9679Slinton {
477*9679Slinton     Char c, buf[10], *p, *q;
478*9679Slinton 
479*9679Slinton     p = curchar;
480*9679Slinton     if (ch == '\\') {
481*9679Slinton 	if (*p != '\\') {
482*9679Slinton 	    q = buf;
483*9679Slinton 	    do {
484*9679Slinton 		*q++ = *p++;
485*9679Slinton 	    } while (*p != '\\' and *p != '\n' and *p != '\0');
486*9679Slinton 	    if (*p != '\\') {
487*9679Slinton 		ungetc(*p, in);
488*9679Slinton 		error("non-terminated character constant");
489*9679Slinton 	    }
490*9679Slinton 	    *q = '\0';
491*9679Slinton 	    if (isdigit(buf[0])) {
492*9679Slinton 		c = (Char) octal(buf);
493*9679Slinton 	    } else {
494*9679Slinton 		c = charlookup(buf);
495*9679Slinton 	    }
496*9679Slinton 	    curchar = p;
497*9679Slinton 	} else {
498*9679Slinton 	    c = '\\';
499*9679Slinton 	}
500*9679Slinton     } else {
501*9679Slinton 	c = ch;
502*9679Slinton     }
503*9679Slinton     return c;
504*9679Slinton }
505*9679Slinton 
506*9679Slinton /*
507*9679Slinton  * Do a lookup for a ASCII character name.
508*9679Slinton  */
509*9679Slinton 
510*9679Slinton private String ascii[] = {
511*9679Slinton     "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
512*9679Slinton     "BS",  "HT",  "NL",  "VT",  "NP",  "CR",  "SO",  "SI",
513*9679Slinton     "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
514*9679Slinton     "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
515*9679Slinton     "SP", nil
516*9679Slinton };
517*9679Slinton 
518*9679Slinton private char charlookup(s)
519*9679Slinton String s;
520*9679Slinton {
521*9679Slinton     register int i;
522*9679Slinton 
523*9679Slinton     for (i = 0; ascii[i] != NULL; i++) {
524*9679Slinton 	if (streq(s, ascii[i])) {
525*9679Slinton 	    return i;
526*9679Slinton 	}
527*9679Slinton     }
528*9679Slinton     if (streq(s, "DEL")) {
529*9679Slinton 	return 0177;
530*9679Slinton     }
531*9679Slinton     error("unknown ascii name \"%s\"", s);
532*9679Slinton     return '?';
533*9679Slinton }
534*9679Slinton 
535*9679Slinton /*
536*9679Slinton  * Input file management routines.
537*9679Slinton  */
538*9679Slinton 
539*9679Slinton public setinput(filename)
540*9679Slinton Filename filename;
541*9679Slinton {
542*9679Slinton     File f;
543*9679Slinton 
544*9679Slinton     f = fopen(filename, "r");
545*9679Slinton     if (f == nil) {
546*9679Slinton 	error("can't open %s", filename);
547*9679Slinton     } else {
548*9679Slinton 	if (curinclindex >= MAXINCLDEPTH) {
549*9679Slinton 	    error("unreasonable input nesting on \"%s\"", filename);
550*9679Slinton 	}
551*9679Slinton 	inclinfo[curinclindex].savefile = in;
552*9679Slinton 	inclinfo[curinclindex].savefn = errfilename;
553*9679Slinton 	inclinfo[curinclindex].savelineno = errlineno;
554*9679Slinton 	curinclindex++;
555*9679Slinton 	in = f;
556*9679Slinton 	errfilename = filename;
557*9679Slinton 	errlineno = 1;
558*9679Slinton     }
559*9679Slinton }
560*9679Slinton 
561*9679Slinton private Boolean eofinput()
562*9679Slinton {
563*9679Slinton     register Boolean b;
564*9679Slinton 
565*9679Slinton     if (curinclindex == 0) {
566*9679Slinton 	if (isterm(in)) {
567*9679Slinton 	    putchar('\n');
568*9679Slinton 	    b = false;
569*9679Slinton 	} else {
570*9679Slinton 	    b = true;
571*9679Slinton 	}
572*9679Slinton     } else {
573*9679Slinton 	fclose(in);
574*9679Slinton 	--curinclindex;
575*9679Slinton 	in = inclinfo[curinclindex].savefile;
576*9679Slinton 	errfilename = inclinfo[curinclindex].savefn;
577*9679Slinton 	errlineno = inclinfo[curinclindex].savelineno;
578*9679Slinton 	b = false;
579*9679Slinton     }
580*9679Slinton     return b;
581*9679Slinton }
582*9679Slinton 
583*9679Slinton /*
584*9679Slinton  * Pop the current input.  Return whether successful.
585*9679Slinton  */
586*9679Slinton 
587*9679Slinton public Boolean popinput()
588*9679Slinton {
589*9679Slinton     Boolean b;
590*9679Slinton 
591*9679Slinton     if (curinclindex == 0) {
592*9679Slinton 	b = false;
593*9679Slinton     } else {
594*9679Slinton 	b = (Boolean) (not eofinput());
595*9679Slinton     }
596*9679Slinton     return b;
597*9679Slinton }
598*9679Slinton 
599*9679Slinton /*
600*9679Slinton  * Return whether we are currently reading from standard input.
601*9679Slinton  */
602*9679Slinton 
603*9679Slinton public Boolean isstdin()
604*9679Slinton {
605*9679Slinton     return (Boolean) (in == stdin);
606*9679Slinton }
607*9679Slinton 
608*9679Slinton /*
609*9679Slinton  * Send the current line to the shell.
610*9679Slinton  */
611*9679Slinton 
612*9679Slinton public shellline()
613*9679Slinton {
614*9679Slinton     register char *p;
615*9679Slinton 
616*9679Slinton     p = curchar;
617*9679Slinton     while (*p != '\0' and (*p == '\n' or lexclass[*p] == WHITE)) {
618*9679Slinton 	++p;
619*9679Slinton     }
620*9679Slinton     shell(p);
621*9679Slinton     if (*p == '\0' and isterm(in)) {
622*9679Slinton 	putchar('\n');
623*9679Slinton     }
624*9679Slinton     erecover();
625*9679Slinton }
626*9679Slinton 
627*9679Slinton /*
628*9679Slinton  * Read the rest of the current line in "shell mode".
629*9679Slinton  */
630*9679Slinton 
631*9679Slinton public beginshellmode()
632*9679Slinton {
633*9679Slinton     shellmode = true;
634*9679Slinton }
635*9679Slinton 
636*9679Slinton /*
637*9679Slinton  * Print out a token for debugging.
638*9679Slinton  */
639*9679Slinton 
640*9679Slinton public print_token(f, t)
641*9679Slinton File f;
642*9679Slinton Token t;
643*9679Slinton {
644*9679Slinton     if (t == '\n') {
645*9679Slinton 	fprintf(f, "char '\\n'");
646*9679Slinton     } else if (t == EOF) {
647*9679Slinton 	fprintf(f, "EOF");
648*9679Slinton     } else if (t < 256) {
649*9679Slinton 	fprintf(f, "char '%c'", t);
650*9679Slinton     } else {
651*9679Slinton 	fprintf(f, "\"%s\"", keywdstring(t));
652*9679Slinton     }
653*9679Slinton }
654