Commit | Line | Data |
---|---|---|
6858bd7a ML |
1 | %{ |
2 | /* Copyright (c) 1982 Regents of the University of California */ | |
3 | ||
23cc830f | 4 | static char sccsid[] = "@(#)token.l 1.3 %G%"; |
6858bd7a ML |
5 | |
6 | /* | |
7 | * Token definitions for pdx scanner. | |
8 | */ | |
9 | ||
10 | #include "defs.h" | |
11 | #include "command.h" | |
12 | #include "y.tab.h" | |
23cc830f | 13 | #include "main.h" |
6858bd7a ML |
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)); } | |
f677c8e6 ML |
61 | <file>{filenm} { yylval.y_string = strdup(yytext); return(FILENAME); } |
62 | {qfilenm} { yylval.y_string = strdup(yytext); return(FILENAME); } | |
6858bd7a ML |
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); } | |
6858bd7a ML |
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; | |
23cc830f | 253 | LOCAL BOOLEAN firsttime; |
6858bd7a ML |
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 | ||
23cc830f | 265 | firsttime = FALSE; |
6858bd7a ML |
266 | fp = fopen(initfile, "r"); |
267 | if (fp != NIL) { | |
268 | fclose(fp); | |
269 | setinput(initfile); | |
23cc830f ML |
270 | if (!option('r')) { |
271 | firsttime = TRUE; | |
272 | } | |
6858bd7a ML |
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) { | |
23cc830f ML |
318 | if (firsttime) { |
319 | firsttime = FALSE; | |
320 | } else { | |
321 | prompt(); | |
322 | } | |
6858bd7a ML |
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 | } |