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