1*5476Slinton %{
2*5476Slinton /* Copyright (c) 1982 Regents of the University of California */
3*5476Slinton 
4*5476Slinton static char sccsid[] = "@(#)token.l 1.1 01/18/82";
5*5476Slinton 
6*5476Slinton /*
7*5476Slinton  * Token definitions for pdx scanner.
8*5476Slinton  */
9*5476Slinton 
10*5476Slinton #include "defs.h"
11*5476Slinton #include "command.h"
12*5476Slinton #include "y.tab.h"
13*5476Slinton #include "symtab.h"
14*5476Slinton #include "sym.h"
15*5476Slinton #include "process.h"
16*5476Slinton #include "process/pxinfo.h"
17*5476Slinton 
18*5476Slinton char *initfile = ".pdxinit";
19*5476Slinton 
20*5476Slinton /*
21*5476Slinton  * This is a silly "lex" thing.
22*5476Slinton  */
23*5476Slinton 
24*5476Slinton #define yywrap()	(1)
25*5476Slinton 
26*5476Slinton /*
27*5476Slinton  * Override Lex default input macros.
28*5476Slinton  */
29*5476Slinton 
30*5476Slinton #undef  input
31*5476Slinton #undef  unput
32*5476Slinton 
33*5476Slinton #define unput(c)	ungetc(c, yyin)
34*5476Slinton 
35*5476Slinton %}
36*5476Slinton 
37*5476Slinton blank		[ \t]
38*5476Slinton white		{blank}+
39*5476Slinton alpha		[a-zA-Z]
40*5476Slinton digit		[0-9]
41*5476Slinton n		{digit}+
42*5476Slinton h		[0-9a-fA-F]+
43*5476Slinton e		(("e"|"E")("+"|"-")?{n})
44*5476Slinton alphanum	[a-zA-Z0-9]
45*5476Slinton ident		{alpha}{alphanum}*
46*5476Slinton filenm		[^ \t\n"<>!*"]+
47*5476Slinton qfilenm		{filenm}/":"
48*5476Slinton string		'[^']+'('[^']*')*
49*5476Slinton newline		"\n"
50*5476Slinton char		.
51*5476Slinton 
52*5476Slinton %Start file sh
53*5476Slinton 
54*5476Slinton %%
55*5476Slinton 
56*5476Slinton {white}		;
57*5476Slinton ^sh{white}.*$	{ BEGIN 0; yylval.y_string = &yytext[3]; return(SH); }
58*5476Slinton ^sh		{ BEGIN 0; yylval.y_string = NIL; return(SH); }
59*5476Slinton ^{ident}	{ return(findcmd(yytext)); }
60*5476Slinton {n}?\.{n}{e}?	{ yylval.y_real = atof(yytext); return(REAL); }
61*5476Slinton 0{n}		{ yylval.y_long = octal(yytext); return(INT); }
62*5476Slinton 0x{h}		{ yylval.y_long = hex(yytext); return(INT); }
63*5476Slinton {n}		{ yylval.y_long = atol(yytext); return(INT); }
64*5476Slinton <file>{filenm}	{ yylval.y_string = strdup(yytext); return(FILENAME); }
65*5476Slinton {qfilenm}	{ yylval.y_string = strdup(yytext); return(FILENAME); }
66*5476Slinton at		{ return(AT); }
67*5476Slinton {ident}		{ return(ident(yytext)); }
68*5476Slinton {string}	{ yylval.y_string = yytext; return(STRING); }
69*5476Slinton "%dp"		{ yylval.y_long = (long) DP; return(INT); }
70*5476Slinton {newline}	{ BEGIN 0; nlflag = TRUE; return('\n'); }
71*5476Slinton {char}		{ return(yylval.y_int = yytext[0]); }
72*5476Slinton 
73*5476Slinton %%
74*5476Slinton 
75*5476Slinton LOCAL SYMTAB *dbtab, *specialtab;
76*5476Slinton 
77*5476Slinton /*
78*5476Slinton  * Look for the given string in the debugger keyword table.
79*5476Slinton  * If it's there, return the associated token, otherwise report an error.
80*5476Slinton  */
81*5476Slinton 
82*5476Slinton LOCAL int findcmd(s)
83*5476Slinton char *s;
84*5476Slinton {
85*5476Slinton 	register SYM *p;
86*5476Slinton 
87*5476Slinton 	if ((p = st_lookup(dbtab, s)) == NIL) {
88*5476Slinton 		error("\"%s\" is not a command", s);
89*5476Slinton 	}
90*5476Slinton 	yylval.y_int = tokval(p);
91*5476Slinton 	switch (toknum(p)) {
92*5476Slinton 		case ALIAS:
93*5476Slinton 		case DUMP:
94*5476Slinton 		case EDIT:
95*5476Slinton 		case CHFILE:
96*5476Slinton 		case RUN:
97*5476Slinton 		case SOURCE:
98*5476Slinton 		case STATUS:
99*5476Slinton 			BEGIN file;
100*5476Slinton 			break;
101*5476Slinton 
102*5476Slinton 		default:
103*5476Slinton 			/* do nothing */;
104*5476Slinton 	}
105*5476Slinton 	return(toknum(p));
106*5476Slinton }
107*5476Slinton 
108*5476Slinton /*
109*5476Slinton  * Look for a symbol, first in the special table (if, in, etc.)
110*5476Slinton  * then in the symbol table.  If it's there, return the SYM pointer,
111*5476Slinton  * otherwise it's an error.
112*5476Slinton  */
113*5476Slinton 
114*5476Slinton LOCAL int ident(s)
115*5476Slinton char *s;
116*5476Slinton {
117*5476Slinton 	register SYM *p;
118*5476Slinton 
119*5476Slinton 	if ((p = st_lookup(specialtab, s)) != NIL) {
120*5476Slinton 		yylval.y_sym = p;
121*5476Slinton 		return(toknum(p));
122*5476Slinton 	}
123*5476Slinton 	p = st_lookup(symtab, s);
124*5476Slinton 	if (p == NIL) {
125*5476Slinton 		if (strcmp(s, "nil") == 0) {
126*5476Slinton 			yylval.y_long = 0L;
127*5476Slinton 			return(INT);
128*5476Slinton 		} else {
129*5476Slinton 			error("\"%s\" is not defined", s);
130*5476Slinton 		}
131*5476Slinton 	}
132*5476Slinton 	yylval.y_sym = p;
133*5476Slinton 	return(NAME);
134*5476Slinton }
135*5476Slinton 
136*5476Slinton /*
137*5476Slinton  * Convert a string to octal.  No check that digits are less than 8.
138*5476Slinton  */
139*5476Slinton 
140*5476Slinton LOCAL int octal(s)
141*5476Slinton char *s;
142*5476Slinton {
143*5476Slinton 	register char *p;
144*5476Slinton 	register int n;
145*5476Slinton 
146*5476Slinton 	n = 0;
147*5476Slinton 	for (p = s; *p != '\0'; p++) {
148*5476Slinton 		n = 8*n + (*p - '0');
149*5476Slinton 	}
150*5476Slinton 	return(n);
151*5476Slinton }
152*5476Slinton 
153*5476Slinton /*
154*5476Slinton  * Convert a string to hex.
155*5476Slinton  */
156*5476Slinton 
157*5476Slinton LOCAL int hex(s)
158*5476Slinton char *s;
159*5476Slinton {
160*5476Slinton 	register char *p;
161*5476Slinton 	register int n;
162*5476Slinton 
163*5476Slinton 	n = 0;
164*5476Slinton 	for (p = s+2; *p != '\0'; p++) {
165*5476Slinton 		n *= 16;
166*5476Slinton 		if (*p >= 'a' && *p <= 'f') {
167*5476Slinton 			n += (*p - 'a' + 10);
168*5476Slinton 		} else if (*p >= 'A' && *p <= 'F') {
169*5476Slinton 			n += (*p - 'A' + 10);
170*5476Slinton 		} else {
171*5476Slinton 			n += (*p - '0');
172*5476Slinton 		}
173*5476Slinton 	}
174*5476Slinton 	return(n);
175*5476Slinton }
176*5476Slinton 
177*5476Slinton /*
178*5476Slinton  * Initialize the debugger keyword table (dbtab) and special symbol
179*5476Slinton  * table (specialtab).
180*5476Slinton  */
181*5476Slinton 
182*5476Slinton #define db_keyword(nm, n)	make_keyword(dbtab, nm, n)
183*5476Slinton #define sp_keyword(nm, n)	make_keyword(specialtab, nm, n)
184*5476Slinton 
185*5476Slinton lexinit()
186*5476Slinton {
187*5476Slinton 	dbtab = st_creat(150);
188*5476Slinton 	db_keyword("alias", ALIAS);
189*5476Slinton 	db_keyword("assign", ASSIGN);
190*5476Slinton 	db_keyword("call", CALL);
191*5476Slinton 	db_keyword("cont", CONT);
192*5476Slinton 	db_keyword("delete", DELETE);
193*5476Slinton 	db_keyword("dump", DUMP);
194*5476Slinton 	db_keyword("edit", EDIT);
195*5476Slinton 	db_keyword("file", CHFILE);
196*5476Slinton 	db_keyword("gripe", GRIPE);
197*5476Slinton 	db_keyword("help", HELP);
198*5476Slinton 	db_keyword("list", LIST);
199*5476Slinton 	db_keyword("next", NEXT);
200*5476Slinton 	db_keyword("pi", REMAKE);
201*5476Slinton 	db_keyword("print", PRINT);
202*5476Slinton 	db_keyword("quit", QUIT);
203*5476Slinton 	db_keyword("run", RUN);
204*5476Slinton 	db_keyword("sh", SH);
205*5476Slinton 	db_keyword("source", SOURCE);
206*5476Slinton 	db_keyword("status", STATUS);
207*5476Slinton 	db_keyword("step", STEP);
208*5476Slinton 	db_keyword("stop", STOP);
209*5476Slinton 	db_keyword("stopi", STOPI);
210*5476Slinton 	db_keyword("trace", TRACE);
211*5476Slinton 	db_keyword("tracei", TRACEI);
212*5476Slinton 	db_keyword("whatis", WHATIS);
213*5476Slinton 	db_keyword("where", WHERE);
214*5476Slinton 	db_keyword("which", WHICH);
215*5476Slinton 	db_keyword("xd", XD);
216*5476Slinton 	db_keyword("xi", XI);
217*5476Slinton 
218*5476Slinton 	specialtab = st_creat(10);
219*5476Slinton 	sp_keyword("div", DIV);
220*5476Slinton 	sp_keyword("mod", MOD);
221*5476Slinton 	sp_keyword("in", IN);
222*5476Slinton 	sp_keyword("if", IF);
223*5476Slinton 	sp_keyword("and", AND);
224*5476Slinton 	sp_keyword("or", OR);
225*5476Slinton }
226*5476Slinton 
227*5476Slinton /*
228*5476Slinton  * Send an alias directive over to the symbol table manager.
229*5476Slinton  */
230*5476Slinton 
231*5476Slinton alias(new, old)
232*5476Slinton char *new, *old;
233*5476Slinton {
234*5476Slinton 	if (old == NIL) {
235*5476Slinton 		print_alias(dbtab, new);
236*5476Slinton 	} else {
237*5476Slinton 		enter_alias(dbtab, new, old);
238*5476Slinton 	}
239*5476Slinton }
240*5476Slinton 
241*5476Slinton /*
242*5476Slinton  * Input file management routines, "yyin" is Lex's idea of
243*5476Slinton  * where the input comes from.
244*5476Slinton  */
245*5476Slinton 
246*5476Slinton #define MAXINPUT 10
247*5476Slinton 
248*5476Slinton LOCAL FILE *infp[MAXINPUT];
249*5476Slinton LOCAL FILE **curfp = &infp[0];
250*5476Slinton 
251*5476Slinton LOCAL BOOLEAN isnewfile;
252*5476Slinton 
253*5476Slinton /*
254*5476Slinton  * Initially, we set the input to the initfile if it exists.
255*5476Slinton  * If it does exist, we play a game or two to avoid generating
256*5476Slinton  * multiple prompts.
257*5476Slinton  */
258*5476Slinton 
259*5476Slinton initinput()
260*5476Slinton {
261*5476Slinton 	FILE *fp;
262*5476Slinton 
263*5476Slinton 	fp = fopen(initfile, "r");
264*5476Slinton 	if (fp != NIL) {
265*5476Slinton 		fclose(fp);
266*5476Slinton 		setinput(initfile);
267*5476Slinton 	}
268*5476Slinton 	nlflag = TRUE;
269*5476Slinton }
270*5476Slinton 
271*5476Slinton /*
272*5476Slinton  * Set the input to the named file.  It is expected that the file exists
273*5476Slinton  * and is readable.
274*5476Slinton  */
275*5476Slinton 
276*5476Slinton setinput(filename)
277*5476Slinton char *filename;
278*5476Slinton {
279*5476Slinton 	register FILE *fp;
280*5476Slinton 
281*5476Slinton 	if ((fp = fopen(filename, "r")) == NIL) {
282*5476Slinton 		error("can't open %s", filename);
283*5476Slinton 	}
284*5476Slinton 	if (curfp >= &infp[MAXINPUT]) {
285*5476Slinton 		error("unreasonable input nesting on %s", filename);
286*5476Slinton 	}
287*5476Slinton 	*curfp++ = yyin;
288*5476Slinton 	yyin = fp;
289*5476Slinton 	isnewfile = TRUE;
290*5476Slinton }
291*5476Slinton 
292*5476Slinton BOOLEAN isstdin()
293*5476Slinton {
294*5476Slinton 	return((BOOLEAN) (yyin == stdin));
295*5476Slinton }
296*5476Slinton 
297*5476Slinton LOCAL int input()
298*5476Slinton {
299*5476Slinton 	register int c;
300*5476Slinton 
301*5476Slinton 	if (isnewfile) {
302*5476Slinton 		isnewfile = FALSE;
303*5476Slinton 		return('\n');
304*5476Slinton 	}
305*5476Slinton 	while ((c = getc(yyin)) == EOF) {
306*5476Slinton 		if (curfp == &infp[0]) {
307*5476Slinton 			return(0);
308*5476Slinton 		} else {
309*5476Slinton 			fclose(yyin);
310*5476Slinton 			yyin = *--curfp;
311*5476Slinton 			if (yyin == stdin) {
312*5476Slinton 				prompt();
313*5476Slinton 			}
314*5476Slinton 		}
315*5476Slinton 	}
316*5476Slinton 	return(c);
317*5476Slinton }
318*5476Slinton 
319*5476Slinton /*
320*5476Slinton  * Handle an input string by stripping the quotes and converting
321*5476Slinton  * two interior quotes to one.  Copy to newly allocated space and
322*5476Slinton  * return a pointer to it.
323*5476Slinton  *
324*5476Slinton  * The handling of strings here is not particularly efficient,
325*5476Slinton  * nor need it be.
326*5476Slinton  */
327*5476Slinton 
328*5476Slinton LOCAL char *pstring(p)
329*5476Slinton char *p;
330*5476Slinton {
331*5476Slinton 	int i, len;
332*5476Slinton 	char *r, *newp;
333*5476Slinton 
334*5476Slinton 	len = strlen(p);
335*5476Slinton 	r = newp = alloc(len - 2 + 1, char);
336*5476Slinton 	for (i = 1; i < len - 1; i++) {
337*5476Slinton 		if (p[i] == '\'' && p[i+1] == '\'') {
338*5476Slinton 			i++;
339*5476Slinton 		}
340*5476Slinton 		*newp++ = p[i];
341*5476Slinton 	}
342*5476Slinton 	*newp = '\0';
343*5476Slinton 	return(r);
344*5476Slinton }
345*5476Slinton 
346*5476Slinton /*
347*5476Slinton  * prompt for a command
348*5476Slinton  */
349*5476Slinton 
350*5476Slinton prompt()
351*5476Slinton {
352*5476Slinton 	nlflag = FALSE;
353*5476Slinton 	if (yyin == stdin) {
354*5476Slinton 		printf("> ");
355*5476Slinton 		fflush(stdout);
356*5476Slinton 	}
357*5476Slinton }
358