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