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