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