1 %{ 2 /* Copyright (c) 1982 Regents of the University of California */ 3 4 static char sccsid[] = "@(#)token.l 1.3 01/25/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 "main.h" 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)); } 61 <file>{filenm} { yylval.y_string = strdup(yytext); return(FILENAME); } 62 {qfilenm} { yylval.y_string = strdup(yytext); return(FILENAME); } 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); } 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; 253 LOCAL BOOLEAN firsttime; 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 265 firsttime = FALSE; 266 fp = fopen(initfile, "r"); 267 if (fp != NIL) { 268 fclose(fp); 269 setinput(initfile); 270 if (!option('r')) { 271 firsttime = TRUE; 272 } 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) { 318 if (firsttime) { 319 firsttime = FALSE; 320 } else { 321 prompt(); 322 } 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 } 368