1 /* 2 * Copyright (c) 1982 Regents of the University of California 3 */ 4 #ifndef lint 5 static char sccsid[] = "@(#)asscan2.c 4.10 06/30/83"; 6 #endif not lint 7 8 #include "asscanl.h" 9 10 static inttoktype oval = NL; 11 12 char inbufunget[8]; 13 char inbuffer[ASINBUFSIZ]; 14 char *Ginbufptr = inbuffer; 15 int Ginbufcnt = 0; 16 17 fillinbuffer() 18 { 19 int nread; 20 static int hadeof; 21 int goal; 22 int got; 23 24 nread = 0; 25 if (hadeof == 0){ 26 goal = sizeof(inbuffer); 27 do { 28 got = read(stdin->_file, inbuffer + nread, goal); 29 if (got == 0) 30 hadeof = 1; 31 if (got <= 0) 32 break; 33 nread += got; 34 goal -= got; 35 } while (goal); 36 } 37 /* 38 * getchar assumes that Ginbufcnt and Ginbufptr 39 * are adjusted as if one character has been removed 40 * from the input. 41 */ 42 if (nread == 0){ 43 inbuffer[0] = EOFCHAR; 44 nread = 1; 45 } 46 Ginbufcnt = nread - 1; 47 Ginbufptr = inbuffer + 1; 48 } 49 50 #ifndef FLEXNAMES 51 char strtext[NCPString + 1]; 52 #else FLEXNAMES 53 # if NCPName < NCPString 54 char strtext[NCPString + 1]; 55 # else 56 #define strtext yytext 57 # endif 58 #endif FLEXNAMES 59 60 scan_dot_s(bufferbox) 61 struct tokbufdesc *bufferbox; 62 { 63 reg char *inbufptr; 64 reg int inbufcnt; 65 reg int ryylval; /* local copy of lexical value */ 66 extern int yylval; /* global copy of lexical value */ 67 reg int val; /* the value returned */ 68 int i; /* simple counter */ 69 reg char *rcp; 70 int ch; /* treated as a character */ 71 int ch1; /* shadow value */ 72 struct symtab *op; 73 ptrall lgbackpatch; /* where to stuff a string length */ 74 reg ptrall bufptr; /* where to stuff tokens */ 75 ptrall bufub; /* where not to stuff tokens */ 76 reg int strlg; /* the length of a string */ 77 long intval; /* value of int */ 78 int linescrossed; /* when doing strings and comments */ 79 struct Opcode opstruct; 80 struct strdesc strd; /* for building DQ strings */ 81 82 (bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]); 83 (bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]); 84 85 MEMTOREGBUF; 86 if (newfflag){ 87 newfflag = 0; 88 strd.sd_stroff = strfilepos; 89 strd.sd_place = STR_BOTH; 90 strd.sd_strlen = strlen(newfname) + 1; 91 fputs(newfname, strfile); 92 putc(0, strfile); 93 strfilepos += strd.sd_strlen; 94 ryylval = (int)savestr(newfname, &strd); 95 96 ptoken(bufptr, IFILE); 97 ptoken(bufptr, STRING); 98 pptr(bufptr, ryylval); 99 100 ptoken(bufptr, ILINENO); 101 ptoken(bufptr, INT); 102 pint(bufptr, 1); 103 } 104 105 while (bufptr < bufub){ 106 loop: 107 switch(ryylval = (type+1)[ch = getchar()]) { 108 case SCANEOF: 109 endoffile: ; 110 inbufptr = 0; 111 ptoken(bufptr, PARSEEOF); 112 goto done; 113 114 case DIV: /*process C style comments*/ 115 if ( (ch = getchar()) == '*') { /*comment prelude*/ 116 int incomment; 117 linescrossed = 0; 118 incomment = 1; 119 ch = getchar(); /*skip over the * */ 120 while(incomment){ 121 switch(ch){ 122 case '*': 123 ch = getchar(); 124 incomment = (ch != '/'); 125 break; 126 case '\n': 127 scanlineno++; 128 linescrossed++; 129 ch = getchar(); 130 break; 131 case EOFCHAR: 132 goto endoffile; 133 default: 134 ch = getchar(); 135 break; 136 } 137 } 138 val = ILINESKIP; 139 ryylval = linescrossed; 140 goto ret; 141 } else { /*just an ordinary DIV*/ 142 ungetc(ch); 143 val = ryylval = DIV; 144 goto ret; 145 } 146 case SH: 147 if (oval == NL){ 148 /* 149 * Attempt to recognize a C preprocessor 150 * style comment '^#[ \t]*[0-9]*[ \t]*".*" 151 */ 152 ch = getchar(); /*bump the #*/ 153 while (INCHARSET(ch, SPACE)) 154 ch = getchar();/*bump white */ 155 if (INCHARSET(ch, DIGIT)){ 156 intval = 0; 157 while(INCHARSET(ch, DIGIT)){ 158 intval = intval*10 + ch - '0'; 159 ch = getchar(); 160 } 161 while (INCHARSET(ch, SPACE)) 162 ch = getchar(); 163 if (ch == '"'){ 164 ptoken(bufptr, ILINENO); 165 ptoken(bufptr, INT); 166 pint(bufptr, intval - 1); 167 ptoken(bufptr, IFILE); 168 /* 169 * The '"' has already been 170 * munched 171 * 172 * eatstr will not eat 173 * the trailing \n, so 174 * it is given to the parser 175 * and counted. 176 */ 177 goto eatstr; 178 } 179 } 180 } 181 /* 182 * Well, its just an ordinary decadent comment 183 */ 184 while ((ch != '\n') && (ch != EOFCHAR)) 185 ch = getchar(); 186 if (ch == EOFCHAR) 187 goto endoffile; 188 val = ryylval = oval = NL; 189 scanlineno++; 190 goto ret; 191 192 case NL: 193 scanlineno++; 194 val = ryylval; 195 goto ret; 196 197 case SP: 198 oval = SP; /*invalidate ^# meta comments*/ 199 goto loop; 200 201 case REGOP: /* % , could be used as modulo, or register*/ 202 ch = getchar(); 203 if (INCHARSET(ch, DIGIT)){ 204 ryylval = ch-'0'; 205 if (ch=='1') { 206 if (INCHARSET( (ch = getchar()), REGDIGIT)) 207 ryylval = 10+ch-'0'; 208 else 209 ungetc(ch); 210 } 211 /* 212 * God only knows what the original author 213 * wanted this undocumented feature to 214 * do. 215 * %5++ is really r7 216 */ 217 while(INCHARSET( (ch = getchar()), SIGN)) { 218 if (ch=='+') 219 ryylval++; 220 else 221 ryylval--; 222 } 223 ungetc(ch); 224 val = REG; 225 } else { 226 ungetc(ch); 227 val = REGOP; 228 } 229 goto ret; 230 231 case ALPH: 232 ch1 = ch; 233 if (INCHARSET(ch, SZSPECBEGIN)){ 234 if( (ch = getchar()) == '`' || ch == '^'){ 235 ch1 |= 0100; /*convert to lower*/ 236 switch(ch1){ 237 case 'b': ryylval = 1; break; 238 case 'w': ryylval = 2; break; 239 case 'l': ryylval = 4; break; 240 default: ryylval = d124; break; 241 } 242 val = SIZESPEC; 243 goto ret; 244 } else { 245 ungetc(ch); 246 ch = ch1; /*restore first character*/ 247 } 248 } 249 rcp = yytext; 250 do { 251 if (rcp < &yytext[NCPName]) 252 *rcp++ = ch; 253 } while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT)); 254 *rcp = '\0'; 255 while (INCHARSET(ch, SPACE)) 256 ch = getchar(); 257 ungetc(ch); 258 259 switch((op = *lookup(1))->s_tag){ 260 case 0: 261 case LABELID: 262 /* 263 * Its a name... (Labels are subsets of name) 264 */ 265 ryylval = (int)op; 266 val = NAME; 267 break; 268 case INST0: 269 case INSTn: 270 case IJXXX: 271 opstruct.Op_popcode = ( (struct instab *)op)->i_popcode; 272 opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode; 273 val = op->s_tag; 274 break; 275 default: 276 ryylval = ( (struct instab *)op)->i_popcode; 277 val = op->s_tag; 278 break; 279 } 280 goto ret; 281 282 case DIG: 283 /* 284 * restore local inbufptr and inbufcnt 285 */ 286 REGTOMEMBUF; 287 val = number(ch); 288 MEMTOREGBUF; 289 /* 290 * yylval or yybignum has been stuffed as a side 291 * effect to number(); get the global yylval 292 * into our fast local copy in case it was an INT. 293 */ 294 ryylval = yylval; 295 goto ret; 296 297 case LSH: 298 case RSH: 299 /* 300 * We allow the C style operators 301 * << and >>, as well as < and > 302 */ 303 if ( (ch1 = getchar()) != ch) 304 ungetc(ch1); 305 val = ryylval; 306 goto ret; 307 308 case MINUS: 309 if ( (ch = getchar()) =='(') 310 ryylval=val=MP; 311 else { 312 ungetc(ch); 313 val=MINUS; 314 } 315 goto ret; 316 317 case SQ: 318 if ((ryylval = getchar()) == '\n') 319 scanlineno++; /*not entirely correct*/ 320 val = INT; 321 goto ret; 322 323 case DQ: 324 eatstr: 325 linescrossed = 0; 326 strd.sd_stroff = strfilepos; 327 strd.sd_place = STR_FILE; 328 for (strd.sd_strlen = 0; /*VOID*/; strd.sd_strlen++){ 329 switch(ch = getchar()){ 330 case '"': 331 goto tailDQ; 332 default: 333 stuff: 334 putc(ch, strfile); 335 break; 336 case '\n': 337 yywarning("New line in a string constant"); 338 scanlineno++; 339 linescrossed++; 340 ch = getchar(); 341 switch(ch){ 342 case EOFCHAR: 343 putc('\n', strfile); 344 ungetc(EOFCHAR); 345 goto tailDQ; 346 default: 347 ungetc(ch); 348 ch = '\n'; 349 goto stuff; 350 } 351 break; 352 353 case '\\': 354 ch = getchar(); /*skip the '\\'*/ 355 if ( INCHARSET(ch, BSESCAPE)){ 356 switch (ch){ 357 case 'b': ch = '\b'; goto stuff; 358 case 'f': ch = '\f'; goto stuff; 359 case 'n': ch = '\n'; goto stuff; 360 case 'r': ch = '\r'; goto stuff; 361 case 't': ch = '\t'; goto stuff; 362 } 363 } 364 if ( !(INCHARSET(ch, OCTDIGIT)) ) 365 goto stuff; 366 i = 0; 367 intval = 0; 368 while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){ 369 i++; 370 intval <<= 3; 371 intval += ch - '0'; 372 ch = getchar(); 373 } 374 ungetc(ch); 375 ch = (char)intval; 376 goto stuff; 377 } 378 } 379 tailDQ: ; 380 /* 381 * account for any lines that were crossed 382 */ 383 if (linescrossed){ 384 ptoken(bufptr, ILINESKIP); 385 pint(bufptr, linescrossed); 386 } 387 /* 388 * put the string in strtext into the string pool 389 * 390 * Cheat: append a trailing null to the string 391 * and then adjust the string length to ignore 392 * the trailing null. If any STRING client requires 393 * the trailing null, the client can just change STRLEN 394 */ 395 val = STRING; 396 putc(0, strfile); 397 strd.sd_strlen += 1; 398 strfilepos += strd.sd_strlen; 399 ryylval = (int)savestr(strtext, &strd); 400 ((struct strdesc *)ryylval)->sd_strlen -= 1; 401 goto ret; 402 403 case BADCHAR: 404 linescrossed = lineno; 405 lineno = scanlineno; 406 yyerror("Illegal character mapped: %d, char read:(octal) %o", 407 ryylval, ch); 408 lineno = linescrossed; 409 val = BADCHAR; 410 goto ret; 411 412 default: 413 val = ryylval; 414 goto ret; 415 } /*end of the switch*/ 416 /* 417 * here with one token, so stuff it 418 */ 419 ret: 420 oval = val; 421 ptoken(bufptr, val); 422 switch(val){ 423 case ILINESKIP: 424 pint(bufptr, ryylval); 425 break; 426 case SIZESPEC: 427 pchar(bufptr, ryylval); 428 break; 429 case BFINT: plong(bufptr, ryylval); 430 break; 431 case INT: plong(bufptr, ryylval); 432 break; 433 case BIGNUM: pnumber(bufptr, yybignum); 434 break; 435 case STRING: pptr(bufptr, (int)(char *)ryylval); 436 break; 437 case NAME: pptr(bufptr, (int)(struct symtab *)ryylval); 438 break; 439 case REG: pchar(bufptr, ryylval); 440 break; 441 case INST0: 442 case INSTn: 443 popcode(bufptr, opstruct); 444 break; 445 case IJXXX: 446 popcode(bufptr, opstruct); 447 pptr(bufptr, (int)(struct symtab *)symalloc()); 448 break; 449 case ISTAB: 450 case ISTABSTR: 451 case ISTABNONE: 452 case ISTABDOT: 453 case IALIGN: 454 pptr(bufptr, (int)(struct symtab *)symalloc()); 455 break; 456 /* 457 * default: 458 */ 459 } 460 builtval: ; 461 } /*end of the while to stuff the buffer*/ 462 done: 463 bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]); 464 /* 465 * This is a real kludge: 466 * 467 * We put the last token in the buffer to be a MINUS 468 * symbol. This last token will never be picked up 469 * in the normal way, but can be looked at during 470 * a peekahead look that the short circuit expression 471 * evaluator uses to see if an expression is complicated. 472 * 473 * Consider the following situation: 474 * 475 * .word 45 + 47 476 * buffer 1 | buffer 0 477 * the peekahead would want to look across the buffer, 478 * but will look in the buffer end zone, see the minus, and 479 * fail. 480 */ 481 ptoken(bufptr, MINUS); 482 REGTOMEMBUF; 483 } 484