1 %{ 2 /* Copyright (c) 1982 Regents of the University of California */ 3 4 static char sccsid[] = "@(#)token.l 1.1 01/18/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 {n}?\.{n}{e}? { yylval.y_real = atof(yytext); return(REAL); } 61 0{n} { yylval.y_long = octal(yytext); return(INT); } 62 0x{h} { yylval.y_long = hex(yytext); return(INT); } 63 {n} { yylval.y_long = atol(yytext); return(INT); } 64 <file>{filenm} { yylval.y_string = strdup(yytext); return(FILENAME); } 65 {qfilenm} { yylval.y_string = strdup(yytext); return(FILENAME); } 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