|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: static char sccsid[] = "@(#)asscan.c 4.6 9/8/80"; ! 3: #include <stdio.h> ! 4: #include "as.h" ! 5: #include "asscan.h" ! 6: ! 7: /* ! 8: * NOTE: ! 9: * This version of the assembler does not use fread and fwrite ! 10: * for the token buffering. The token buffers are integrals of BUFSIZ ! 11: * at all times, so we use direct read and write. fread and fwrite ! 12: * as supplied from BTL in stdio are HORRENDOUSLY inefficient, ! 13: * as they use putchar for each character, nested two deep in loops. ! 14: */ ! 15: #define writeTEST(pointer, size, nelements, ioptr) \ ! 16: write(ioptr->_file, pointer, nelements * size) != nelements * size ! 17: ! 18: #define readTEST(pointer, size, nelements, ioptr) \ ! 19: read(ioptr->_file, pointer, nelements * size) != nelements * size ! 20: /* ! 21: * Variables to manage the token buffering. ! 22: * We scan (lexically analyze) a large number of tokens, and ! 23: * then parse all of the tokens in the scan buffer. ! 24: * This reduces procedure call overhead when the parser ! 25: * demands a token, allows for an efficient reread during ! 26: * the second pass, and confuses the line number reporting ! 27: * for errors encountered in the scanner and in the parser. ! 28: */ ! 29: #define TOKDALLOP 8 ! 30: struct tokbufdesc *bufstart; /*where the buffer list begins*/ ! 31: struct tokbufdesc *buftail; /*last one on the list*/ ! 32: struct tokbufdesc *emptybuf; /*the one being filled*/ ! 33: /* ! 34: * If we are using VM, during the second pass we reclaim the used ! 35: * token buffers for saving the relocation information ! 36: */ ! 37: struct tokbufdesc *tok_free; /* free pool */ ! 38: struct tokbufdesc *tok_temp; /* temporary for doing list manipulation */ ! 39: /* ! 40: * Other token buffer managers ! 41: */ ! 42: int bufno; /*which buffer number: 0,1 for tmp file*/ ! 43: struct tokbufdesc tokbuf[2]; /*our initial increment of buffers*/ ! 44: ptrall tokptr; /*where the current token comes from*/ ! 45: ptrall tokub; /*the last token in the current token buffer*/ ! 46: ! 47: /* ! 48: * Variables to manage the string buffering ! 49: * declared in asscan.h. ! 50: */ ! 51: int strno; /*the current string being filled*/ ! 52: struct strdesc strbuf[3]; /*the string buffers; the first for nulls*/ ! 53: struct strdesc *strptr; /*current string buffer being filled*/ ! 54: ! 55: inittmpfile() ! 56: { ! 57: if (passno == 1){ ! 58: if (useVM){ ! 59: bufstart = &tokbuf[0]; ! 60: buftail = &tokbuf[1]; ! 61: bufstart->tok_next = buftail; ! 62: buftail->tok_next = 0; ! 63: } ! 64: tokbuf[0].tok_count = -1; ! 65: tokbuf[1].tok_count = -1; ! 66: } ! 67: tok_temp = 0; ! 68: tok_free = 0; ! 69: bufno = 0; ! 70: emptybuf = &tokbuf[bufno]; ! 71: tokptr = 0; ! 72: tokub = 0; ! 73: } ! 74: ! 75: closetmpfile() ! 76: { ! 77: if (passno == 1){ ! 78: if (useVM){ ! 79: emptybuf->toks[emptybuf->tok_count++] = PARSEEOF; ! 80: } else { ! 81: /* ! 82: * Clean up the buffers that haven't been ! 83: * written out yet ! 84: */ ! 85: if (tokbuf[bufno ^ 1].tok_count >= 0){ ! 86: if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){ ! 87: badwrite: ! 88: yyerror("Unexpected end of file writing the interpass tmp file"); ! 89: exit(2); ! 90: } ! 91: } ! 92: /* ! 93: * Ensure that we will read an End of file, ! 94: * if there are more than one file names ! 95: * in the argument list ! 96: */ ! 97: tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF; ! 98: if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil)) ! 99: goto badwrite; ! 100: } ! 101: } /*end of being pass 1*/ ! 102: } ! 103: ! 104: #define bstrlg(from, length) \ ! 105: *(lgtype *)from = length; \ ! 106: (char *)from += sizeof(lgtype) + length ! 107: ! 108: #define bstrfromto(from,to) \ ! 109: *(lgtype *)from = (char *)to - (char *)from - sizeof(lgtype); \ ! 110: (char *)from += sizeof(lgtype) + (char *)to - (char *)from ! 111: ! 112: #define eatstrlg(from) \ ! 113: (char *)from += sizeof(lgtype) + *(lgtype *)from ! 114: ! 115: #define bskiplg(from, length) \ ! 116: *(lgtype *)from = length; \ ! 117: (char *)from += sizeof(lgtype) + length ! 118: ! 119: #define bskipfromto(from, to) \ ! 120: *(lgtype *)from = (toktype *)to - (toktype *)from - sizeof(lgtype); \ ! 121: (char *)from += sizeof (lgtype) + (toktype *)to - (toktype *)from ! 122: ! 123: #define eatskiplg(from) \ ! 124: (toktype *)from += sizeof(lgtype) + *(lgtype *)from ! 125: ! 126: #ifdef DEBUG ! 127: ptrall firsttoken; ! 128: #endif DEBUG ! 129: ! 130: extern int yylval; /*global communication with parser*/ ! 131: static int Lastjxxx; /*this ONLY shuts up cc; see below*/ ! 132: ! 133: toktype yylex() ! 134: { ! 135: register ptrall bufptr; ! 136: register toktype val; ! 137: register struct exp *locxp; ! 138: ! 139: bufptr = tokptr; /*copy in the global value*/ ! 140: top: ! 141: if (bufptr < tokub){ ! 142: gtoken(val, bufptr); ! 143: switch(yylval = val){ ! 144: case PARSEEOF : ! 145: yylval = val = PARSEEOF; ! 146: break; ! 147: case BFINT: ! 148: case INT: ! 149: if (xp >= &explist[NEXP]) ! 150: yyerror("Too many expressions; try simplyfing"); ! 151: else ! 152: locxp = xp++; ! 153: glong(locxp->e_xvalue, bufptr); ! 154: locxp->e_yvalue = 0; ! 155: makevalue: ! 156: locxp->e_xtype = XABS; ! 157: locxp->e_xloc = 0; ! 158: locxp->e_xname = NULL; ! 159: yylval = (int)locxp; ! 160: break; ! 161: case FLTNUM: ! 162: if (xp >= &explist[NEXP]) ! 163: yyerror("Too many expressions; try simplyfing"); ! 164: else ! 165: locxp = xp++; ! 166: gdouble( ( (union Double *)locxp)->dvalue, bufptr); ! 167: goto makevalue; ! 168: case QUAD: ! 169: if (xp >= &explist[NEXP]) ! 170: yyerror("Too many expressions; try simplyfing"); ! 171: else ! 172: locxp = xp++; ! 173: glong(locxp->e_xvalue, bufptr); ! 174: glong(locxp->e_yvalue, bufptr); ! 175: yylval = val = INT; ! 176: goto makevalue; ! 177: case NAME: ! 178: gptr(yylval, bufptr); ! 179: lastnam = (struct symtab *)yylval; ! 180: break; ! 181: case SIZESPEC: ! 182: case REG: ! 183: case INSTn: ! 184: case INST0: ! 185: gchar(yylval, bufptr); ! 186: break; ! 187: case IJXXX: ! 188: gchar(yylval, bufptr); ! 189: /* We can't cast Lastjxxx into (int *) here.. */ ! 190: gptr(Lastjxxx, bufptr); ! 191: lastjxxx = (struct symtab *)Lastjxxx; ! 192: break; ! 193: case ILINESKIP: ! 194: gint(yylval, bufptr); ! 195: lineno += yylval; ! 196: goto top; ! 197: case SKIP: ! 198: eatskiplg(bufptr); ! 199: goto top; ! 200: case VOID: ! 201: goto top; ! 202: case STRING: ! 203: strptr = &strbuf[strno ^= 1]; ! 204: strptr->str_lg = *((lgtype *)bufptr); ! 205: movestr(&strptr->str[0], ! 206: (char *)bufptr + sizeof(lgtype), ! 207: strptr->str_lg); ! 208: eatstrlg(bufptr); ! 209: yylval = (int)strptr; ! 210: break; ! 211: case ISTAB: ! 212: case ISTABSTR: ! 213: case ISTABNONE: ! 214: case ISTABDOT: ! 215: case IALIGN: ! 216: gptr(yylval, bufptr); ! 217: break; ! 218: } ! 219: #ifdef DEBUG ! 220: if (toktrace){ ! 221: char *tok_to_name(); ! 222: printf("P: %d T#: %4d, %s ", ! 223: passno, bufptr - firsttoken, tok_to_name(val)); ! 224: switch(val){ ! 225: case INT: printf("val %d", ! 226: ((struct exp *)yylval)->e_xvalue); ! 227: break; ! 228: case BFINT: printf("val %d", ! 229: ((struct exp *)yylval)->e_xvalue); ! 230: break; ! 231: case QUAD: printf("val[msd] = 0x%x, val[lsd] = 0x%x.", ! 232: ((struct exp *)yylval)->e_xvalue, ! 233: ((struct exp *)yylval)->e_yvalue); ! 234: break; ! 235: case FLTNUM: printf("value %20.17f", ! 236: ((union Double *)yylval)->dvalue); ! 237: break; ! 238: case NAME: printf("\"%.8s\"", ! 239: ((struct symtab *)yylval)->s_name); ! 240: break; ! 241: case REG: printf(" r%d", ! 242: yylval); ! 243: break; ! 244: case IJXXX: ! 245: case INST0: ! 246: case INSTn: printf("%.8s", ! 247: itab[0xFF &yylval]->s_name); ! 248: break; ! 249: case STRING: printf("length %d ", ! 250: ((struct strdesc *)yylval)->str_lg); ! 251: printf("value\"%s\"", ! 252: ((struct strdesc *)yylval)->str); ! 253: break; ! 254: } /*end of the debug switch*/ ! 255: printf("\n"); ! 256: } ! 257: #endif DEBUG ! 258: ! 259: } else { /* start a new buffer */ ! 260: if (useVM){ ! 261: if (passno == 2){ ! 262: tok_temp = emptybuf->tok_next; ! 263: emptybuf->tok_next = tok_free; ! 264: tok_free = emptybuf; ! 265: emptybuf = tok_temp; ! 266: } else { ! 267: emptybuf = emptybuf->tok_next; ! 268: } ! 269: bufno += 1; ! 270: if (emptybuf == 0){ ! 271: struct tokbufdesc *newdallop; ! 272: int i; ! 273: if (passno == 2) ! 274: goto badread; ! 275: emptybuf = newdallop = (struct tokbufdesc *) ! 276: Calloc(TOKDALLOP, sizeof (struct tokbufdesc)); ! 277: for (i=0; i < TOKDALLOP; i++){ ! 278: buftail->tok_next = newdallop; ! 279: buftail = newdallop; ! 280: newdallop += 1; ! 281: } ! 282: buftail->tok_next = 0; ! 283: } /*end of need to get more buffers*/ ! 284: (toktype *)bufptr = &(emptybuf->toks[0]); ! 285: if (passno == 1) ! 286: scan_dot_s(emptybuf); ! 287: } else { /*don't use VM*/ ! 288: bufno ^= 1; ! 289: emptybuf = &tokbuf[bufno]; ! 290: ((toktype *)bufptr) = &(emptybuf->toks[0]); ! 291: if (passno == 1){ ! 292: /* ! 293: * First check if there are things to write ! 294: * out at all ! 295: */ ! 296: if (emptybuf->tok_count >= 0){ ! 297: if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ ! 298: badwrite: ! 299: yyerror("Unexpected end of file writing the interpass tmp file"); ! 300: exit(2); ! 301: } ! 302: } ! 303: scan_dot_s(emptybuf); ! 304: } else { /*pass 2*/ ! 305: if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ ! 306: badread: ! 307: yyerror("Unexpected end of file while reading the interpass tmp file"); ! 308: exit(1); ! 309: } ! 310: } ! 311: } /*end of using a real live file*/ ! 312: (char *)tokub = (char *)bufptr + emptybuf->tok_count; ! 313: #ifdef DEBUG ! 314: firsttoken = bufptr; ! 315: if (debug) ! 316: printf("created buffernumber %d with %d tokens\n", ! 317: bufno, emptybuf->tok_count); ! 318: #endif DEBUG ! 319: goto top; ! 320: } /*end of reading/creating a new buffer*/ ! 321: tokptr = bufptr; /*copy back the global value*/ ! 322: return(val); ! 323: } /*end of yylex*/ ! 324: ! 325: ! 326: buildskip(from, to) ! 327: register ptrall from, to; ! 328: { ! 329: int diff; ! 330: register int frombufno; ! 331: register struct tokbufdesc *middlebuf; ! 332: /* ! 333: * check if from and to are in the same buffer ! 334: * from and to DIFFER BY AT MOST 1 buffer and to is ! 335: * always ahead of from, with to being in the buffer emptybuf ! 336: * points to. ! 337: * The hard part here is accounting for the case where the ! 338: * skip is to cross a buffer boundary; we must construct ! 339: * two skips. ! 340: * ! 341: * Figure out where the buffer boundary between from and to is ! 342: * It's easy in VM, as buffers increase to high memory, but ! 343: * w/o VM, we alternate between two buffers, and want ! 344: * to look at the exact middle of the contiguous buffer region. ! 345: */ ! 346: middlebuf = useVM ? emptybuf : &tokbuf[1]; ! 347: if ( ( (toktype *)from > (toktype *)middlebuf) ! 348: ^ ( (toktype *)to > (toktype *)middlebuf) ! 349: ){ /*split across a buffer boundary*/ ! 350: ptoken(from, SKIP); ! 351: /* ! 352: * Set the skip so it lands someplace beyond ! 353: * the end of this buffer. ! 354: * When we pull this skip out in the second pass, ! 355: * we will temporarily move the current pointer ! 356: * out beyond the end of the buffer, but immediately ! 357: * do a compare and fail the compare, and then reset ! 358: * all the pointers correctly to point into the next buffer. ! 359: */ ! 360: bskiplg(from, TOKBUFLG + 1); ! 361: /* ! 362: * Now, force from to be in the same buffer as to ! 363: */ ! 364: (toktype *)from = (toktype *)&(emptybuf->toks[0]); ! 365: } ! 366: /* ! 367: * Now, to and from are in the same buffer ! 368: */ ! 369: if (from > to) ! 370: yyerror("Internal error: bad skip construction"); ! 371: else { ! 372: if ( (diff = (toktype *)to - (toktype *)from) >= ! 373: (sizeof(toktype) + sizeof(lgtype) + 1)) { ! 374: ptoken(from, SKIP); ! 375: bskipfromto(from, to); ! 376: } else { ! 377: for ( ; diff > 0; --diff) ! 378: ptoken(from, VOID); ! 379: } ! 380: } ! 381: } ! 382: ! 383: movestr(to, from, lg) ! 384: register char *to, *from; ! 385: register int lg; ! 386: { ! 387: if (lg <= 0) return; ! 388: do ! 389: *to++ = *from++; ! 390: while (--lg); ! 391: } ! 392: static int newfflag = 0; ! 393: static char *newfname; ! 394: int scanlineno; /*the scanner's linenumber*/ ! 395: ! 396: new_dot_s(namep) ! 397: char *namep; ! 398: { ! 399: newfflag = 1; ! 400: newfname = namep; ! 401: dotsname = namep; ! 402: lineno = 1; ! 403: scanlineno = 1; ! 404: } ! 405: ! 406: /* ! 407: * Maps characters to their use in assembly language ! 408: */ ! 409: #define EOFCHAR (-1) ! 410: #define NEEDCHAR (-2) ! 411: ! 412: readonly short type[] = { ! 413: NEEDSBUF, /*fill up the input buffer*/ ! 414: SCANEOF, /*hit the hard end of file*/ ! 415: SP, BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*\0..^G*/ ! 416: BADCHAR,SP, NL, BADCHAR,BADCHAR,SP, BADCHAR,BADCHAR, /*BS..SI*/ ! 417: BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*DLE..ETB*/ ! 418: BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*CAN..US*/ ! 419: SP, ORNOT, DQ, SH, LITOP, REGOP, AND, SQ, /*sp .. '*/ ! 420: LP, RP, MUL, PLUS, CM, MINUS, ALPH, DIV, /*( .. /*/ ! 421: DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /*0 .. 7*/ ! 422: DIG, DIG, COLON, SEMI, LSH, BADCHAR,RSH, BADCHAR, /*8 .. ?*/ ! 423: BADCHAR,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*@ .. G*/ ! 424: ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*H .. BADCHAR*/ ! 425: ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*P .. V*/ ! 426: ALPH, ALPH, ALPH, LB, BADCHAR,RB, XOR, ALPH,/*W .. _*/ ! 427: SIZEQUOTE,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*` .. g*/ ! 428: ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*h .. o*/ ! 429: ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*p .. v*/ ! 430: ALPH, ALPH, ALPH, BADCHAR,IOR, BADCHAR,TILDE, BADCHAR,/*x .. del*/ ! 431: }; ! 432: ! 433: /* ! 434: * The table of possible uses for each character to test set inclusion. ! 435: * Different than the above table, which knows about tokens yylex ! 436: * is to return. ! 437: */ ! 438: #define HEXFLAG 01 /* 'x' or 'X' */ ! 439: #define HEXLDIGIT 02 /* 'a' .. 'f' */ ! 440: #define HEXUDIGIT 04 /* 'A' .. 'F' */ ! 441: #define ALPHA 010 /* 'A' .. 'Z', 'a' .. 'z', '_'*/ ! 442: #define DIGIT 020 /* '0' .. '9' */ ! 443: #define FLOATEXP 040 /* 'd' 'e' 'D' 'E' */ ! 444: #define SIGN 0100 /* '+' .. '-'*/ ! 445: #define REGDIGIT 0200 /* '0' .. '5' */ ! 446: #define SZSPECBEGIN 0400 /* 'b', 'B', 'l', 'L', 'w', 'W' */ ! 447: #define POINT 01000 /* '.' */ ! 448: #define SPACE 02000 /* '\t' or ' ' */ ! 449: #define BSESCAPE 04000 /* bnrtf */ ! 450: #define STRESCAPE 010000 /* '"', '\\', '\n' */ ! 451: #define OCTDIGIT 020000 /* '0' .. '7' */ ! 452: #define FLOATFLAG 040000 /* 'd', 'D', 'f', 'F' */ ! 453: /*after leading 0*/ ! 454: ! 455: readonly short charsets[] = { ! 456: 0, 0, 0, 0, 0, 0, 0, 0, /*\0..^G*/ ! 457: 0, SPACE, STRESCAPE,0, 0, 0, 0, 0, /*BS..SI*/ ! 458: 0, 0, 0, 0, 0, 0, 0, 0, /*DLE..ETB*/ ! 459: 0, 0, 0, 0, 0, 0, 0, 0, /*CAN..US*/ ! 460: /* dollar is an alpha character */ ! 461: SPACE, 0, STRESCAPE,0, ALPHA, 0, 0, 0, /*sp.. '*/ ! 462: 0, 0, 0, SIGN, 0, SIGN, POINT+ALPHA,0, /*( .. /*/ ! 463: DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*0..1*/ ! 464: DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*2..3*/ ! 465: DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*4..5*/ ! 466: DIGIT+OCTDIGIT, DIGIT+OCTDIGIT, /*6..7*/ ! 467: DIGIT, DIGIT, 0, 0, 0, 0, 0, 0, /*8..?*/ ! 468: 0, /*@*/ ! 469: ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+SZSPECBEGIN, /*A..B*/ ! 470: ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+FLOATEXP+FLOATFLAG, /*C..D*/ ! 471: ALPHA+HEXUDIGIT+FLOATEXP,ALPHA+HEXUDIGIT+FLOATFLAG, /*E..F*/ ! 472: ALPHA, /*G*/ ! 473: ALPHA, ALPHA, ALPHA, ALPHA, /*H..K*/ ! 474: ALPHA+SZSPECBEGIN, ALPHA, ALPHA, ALPHA, /*L..O*/ ! 475: ALPHA, ALPHA, ALPHA, ALPHA, /*P..S*/ ! 476: ALPHA, ALPHA, ALPHA, ALPHA+SZSPECBEGIN, /*T..W*/ ! 477: ALPHA+HEXFLAG, ALPHA, ALPHA, 0,STRESCAPE,0, 0, ALPHA,/*X.._*/ ! 478: ! 479: 0, ! 480: ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+BSESCAPE+SZSPECBEGIN, /*a..b*/ ! 481: ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+FLOATEXP+FLOATFLAG, /*c..d*/ ! 482: ALPHA+HEXLDIGIT+FLOATEXP,ALPHA+HEXLDIGIT+BSESCAPE+FLOATFLAG, /*e..f*/ ! 483: ALPHA, /*g*/ ! 484: ALPHA, ALPHA, ALPHA, ALPHA, /*h..k*/ ! 485: ALPHA+SZSPECBEGIN, ALPHA, ALPHA+BSESCAPE, ALPHA, /*l..o*/ ! 486: ALPHA, ALPHA, ALPHA+BSESCAPE, ALPHA, /*p..s*/ ! 487: ALPHA+BSESCAPE, ALPHA, ALPHA, ALPHA+SZSPECBEGIN,/*t..w*/ ! 488: ALPHA+HEXFLAG, ALPHA, ALPHA, 0,0, 0, 0, 0, /*x..del*/ ! 489: 0}; ! 490: ! 491: #define INCHARSET(val, kind) (charsets[val] & (kind) ) ! 492: static toktype oval = NL; ! 493: ! 494: #define NINBUFFERS 2 ! 495: #define INBUFLG NINBUFFERS*BUFSIZ + 2 ! 496: /* ! 497: * We have two input buffers; the first one is reserved ! 498: * for catching the tail of a line split across a buffer ! 499: * boundary; the other one are used for snarfing a buffer ! 500: * worth of .s source. ! 501: */ ! 502: static char inbuffer[INBUFLG]; ! 503: static char *InBufPtr = 0; ! 504: ! 505: #ifdef getchar ! 506: #undef getchar ! 507: #endif ! 508: #define getchar() *inbufptr++ ! 509: ! 510: #ifdef ungetc ! 511: #undef ungetc ! 512: #endif ! 513: #define ungetc(char) *--inbufptr = char ! 514: ! 515: /* ! 516: * fill the inbuffer from the standard input. ! 517: * Assert: there are always n COMPLETE! lines in the buffer area. ! 518: * Assert: there is always a \n terminating the last line ! 519: * in the buffer area. ! 520: * Assert: after the \n, there is an EOFCHAR (hard end of file) ! 521: * or a NEEDCHAR (end of buffer) ! 522: * Assert: fgets always null pads the string it reads. ! 523: * Assert: no ungetc's are done at the end of a line or at the ! 524: * beginning of a line. ! 525: * ! 526: * We read a complete buffer of characters in one single read. ! 527: * We then back scan within this buffer to find the end of the ! 528: * last complete line, and force the assertions, and save a pointer ! 529: * to the incomplete line. ! 530: * The next call to fillinbuffer will move the unread characters ! 531: * to the end of the first buffer, and then read another two buffers, ! 532: * completing the cycle. ! 533: */ ! 534: ! 535: static char p_swapped = '\0'; ! 536: static char *p_start = &inbuffer[NINBUFFERS * BUFSIZ]; ! 537: static char *p_stop = &inbuffer[NINBUFFERS * BUFSIZ]; ! 538: char *fillinbuffer() ! 539: { ! 540: register char *to; ! 541: register char *from; ! 542: char *inbufptr; ! 543: int nread; ! 544: ! 545: *p_start = p_swapped; ! 546: inbufptr = &inbuffer[1*BUFSIZ] - (p_stop - p_start); ! 547: ! 548: for (to = inbufptr, from = p_start; from < p_stop;) ! 549: *to++ = *from++; ! 550: /* ! 551: * Now, go read two full buffers (hopefully) ! 552: */ ! 553: nread = read(stdin->_file, &inbuffer[1*BUFSIZ], (NINBUFFERS - 1)*BUFSIZ); ! 554: if (nread == 0) ! 555: return(0); ! 556: p_stop = from = &inbuffer[1*BUFSIZ + nread]; ! 557: *from = '\0'; ! 558: while (*--from != '\n') /* back over the partial line */ ! 559: continue; ! 560: from++; /* first char of partial line */ ! 561: p_start = from; ! 562: p_swapped = *p_start; ! 563: *p_start = NEEDCHAR; /* force assertion */ ! 564: return(inbufptr); ! 565: } ! 566: ! 567: scan_dot_s(bufferbox) ! 568: struct tokbufdesc *bufferbox; ! 569: { ! 570: register int yylval;/*lexical value*/ ! 571: register toktype val; /*the value returned; the character read*/ ! 572: register int base; /*the base of the number also counter*/ ! 573: register char *cp; ! 574: register char *inbufptr; ! 575: register struct symtab *op; ! 576: register unsigned char tag; ! 577: int forb; ! 578: ! 579: register ptrall bufptr; /*where to stuff tokens*/ ! 580: ptrall lgbackpatch; /*where to stuff a string length*/ ! 581: ptrall bufub; /*where not to stuff tokens*/ ! 582: register int maxstrlg; /*how long a string can be*/ ! 583: long intval; /*value of int*/ ! 584: char fltchr[64]; /*buffer for floating values*/ ! 585: union Double fltval; /*floating value returned*/ ! 586: struct Quad quadval; /*quad returned from immediate constant */ ! 587: int linescrossed; /*when doing strings and comments*/ ! 588: ! 589: (toktype *)bufptr = (toktype *) & (bufferbox->toks[0]); ! 590: (toktype *)bufub = &(bufferbox->toks[AVAILTOKS]); ! 591: ! 592: inbufptr = InBufPtr; ! 593: if (inbufptr == 0){ ! 594: inbufptr = fillinbuffer(); ! 595: if (inbufptr == 0){ /*end of file*/ ! 596: endoffile: ! 597: inbufptr = 0; ! 598: ptoken(bufptr, PARSEEOF); ! 599: goto done; ! 600: } ! 601: } ! 602: ! 603: if (newfflag){ ! 604: ptoken(bufptr, IFILE); ! 605: ptoken(bufptr, STRING); ! 606: val = strlen(newfname) + 1; ! 607: movestr( (char *)&( ( (lgtype *)bufptr)[1]), newfname, val); ! 608: bstrlg(bufptr, val); ! 609: ! 610: ptoken(bufptr, ILINENO); ! 611: ptoken(bufptr, INT); ! 612: pint(bufptr, 1); ! 613: newfflag = 0; ! 614: } ! 615: ! 616: while (bufptr < bufub){ ! 617: loop: ! 618: switch(yylval = (type+2)[val = getchar()]) { ! 619: case SCANEOF: ! 620: inbufptr = 0; ! 621: goto endoffile; ! 622: ! 623: case NEEDSBUF: ! 624: inbufptr = fillinbuffer(); ! 625: if (inbufptr == 0) ! 626: goto endoffile; ! 627: goto loop; ! 628: ! 629: case DIV: /*process C style comments*/ ! 630: if ( (val = getchar()) == '*') { /*comment prelude*/ ! 631: int incomment; ! 632: linescrossed = 0; ! 633: incomment = 1; ! 634: val = getchar(); /*skip over the * */ ! 635: do{ ! 636: while ( (val != '*') && ! 637: (val != '\n') && ! 638: (val != EOFCHAR) && ! 639: (val != NEEDCHAR)) ! 640: val = getchar(); ! 641: if (val == '\n'){ ! 642: scanlineno++; ! 643: linescrossed++; ! 644: } else ! 645: if (val == EOFCHAR) ! 646: goto endoffile; ! 647: if (val == NEEDCHAR){ ! 648: inbufptr = fillinbuffer(); ! 649: if (inbufptr == 0) ! 650: goto endoffile; ! 651: lineno++; ! 652: incomment = 1; ! 653: val = getchar(); /*pull in the new char*/ ! 654: } else { /*its a star */ ! 655: val = getchar(); ! 656: incomment = val != '/'; ! 657: } ! 658: } while (incomment); ! 659: val = ILINESKIP; ! 660: yylval = linescrossed; ! 661: goto ret; ! 662: } else { /*just an ordinary DIV*/ ! 663: ungetc(val); ! 664: val = yylval = DIV; ! 665: goto ret; ! 666: } ! 667: case SH: ! 668: if (oval == NL){ ! 669: /* ! 670: * Attempt to recognize a C preprocessor ! 671: * style comment '^#[ \t]*[0-9]*[ \t]*".*" ! 672: */ ! 673: val = getchar(); /*bump the #*/ ! 674: while (INCHARSET(val, SPACE)) ! 675: val = getchar();/*bump white */ ! 676: if (INCHARSET(val, DIGIT)){ ! 677: intval = 0; ! 678: while(INCHARSET(val, DIGIT)){ ! 679: intval = intval *10 + val - '0'; ! 680: val = getchar(); ! 681: } ! 682: while (INCHARSET(val, SPACE)) ! 683: val = getchar(); ! 684: if (val == '"'){ ! 685: ptoken(bufptr, ILINENO); ! 686: ptoken(bufptr, INT); ! 687: pint(bufptr, intval - 1); ! 688: ptoken(bufptr, IFILE); ! 689: /* ! 690: * The '"' has already been ! 691: * munched ! 692: * ! 693: * eatstr will not eat ! 694: * the trailing \n, so ! 695: * it is given to the parser ! 696: * and counted. ! 697: */ ! 698: goto eatstr; ! 699: } ! 700: } ! 701: } ! 702: /* ! 703: * Well, its just an ordinary decadent comment ! 704: */ ! 705: while ((val != '\n') && (val != EOFCHAR)) ! 706: val = getchar(); ! 707: if (val == EOFCHAR) ! 708: goto endoffile; ! 709: val = yylval = oval = NL; ! 710: scanlineno++; ! 711: goto ret; ! 712: ! 713: case NL: ! 714: scanlineno++; ! 715: val = yylval; ! 716: goto ret; ! 717: ! 718: case SP: ! 719: oval = SP; /*invalidate ^# meta comments*/ ! 720: goto loop; ! 721: ! 722: case REGOP: /* % , could be used as modulo, or register*/ ! 723: val = getchar(); ! 724: if (INCHARSET(val, DIGIT)){ ! 725: yylval = val-'0'; ! 726: if (val=='1') { ! 727: if (INCHARSET( (val = getchar()), REGDIGIT)) ! 728: yylval = 10+val-'0'; ! 729: else ! 730: ungetc(val); ! 731: } ! 732: /* ! 733: * God only knows what the original author ! 734: * wanted this undocumented feature to ! 735: * do. ! 736: * %5++ is really r7 ! 737: */ ! 738: while(INCHARSET( (val = getchar()), SIGN)) { ! 739: if (val=='+') ! 740: yylval++; ! 741: else ! 742: yylval--; ! 743: } ! 744: ungetc(val); ! 745: val = REG; ! 746: } else { ! 747: ungetc(val); ! 748: val = REGOP; ! 749: } ! 750: goto ret; ! 751: ! 752: case ALPH: ! 753: yylval = val; ! 754: if (INCHARSET(val, SZSPECBEGIN)){ ! 755: if( (val = getchar()) == '`' || val == '^'){ ! 756: yylval |= 0100; /*convert to lower*/ ! 757: if (yylval == 'b') yylval = 1; ! 758: else if (yylval == 'w') yylval = 2; ! 759: else if (yylval == 'l') yylval = 4; ! 760: else yylval = d124; ! 761: val = SIZESPEC; ! 762: goto ret; ! 763: } else { ! 764: ungetc(val); ! 765: val = yylval; /*restore first character*/ ! 766: } ! 767: } ! 768: cp = yytext; ! 769: do { ! 770: if (cp < &yytext[NCPS]) ! 771: *cp++ = val; ! 772: } while (INCHARSET ( (val = getchar()), ALPHA | DIGIT)); ! 773: *cp = '\0'; ! 774: while (INCHARSET(val, SPACE)) ! 775: val = getchar(); ! 776: ungetc(val); ! 777: doit: ! 778: tag = (op = *lookup(1))->s_tag; ! 779: if (tag && tag != LABELID){ ! 780: yylval = ( (struct instab *)op)->i_opcode; ! 781: val = op->s_tag ; ! 782: goto ret; ! 783: } else { ! 784: /* ! 785: * Its a name... (Labels are subsets ofname) ! 786: */ ! 787: yylval = (int)op; ! 788: val = NAME; ! 789: goto ret; ! 790: } ! 791: ! 792: case DIG: ! 793: base = 10; ! 794: cp = fltchr; ! 795: intval = 0; ! 796: if (val=='0') { ! 797: val = getchar(); ! 798: if (val == 'b') { ! 799: yylval = -1; ! 800: val = BFINT; ! 801: goto ret; ! 802: } ! 803: if (val == 'f') { ! 804: /* ! 805: * Well, it appears to be a local label ! 806: * reference, but check to see if ! 807: * the next character makes it a floating ! 808: * point constant. ! 809: */ ! 810: forb = getchar(); ! 811: ungetc(forb); ! 812: if (!(INCHARSET(forb,(DIGIT|SIGN|FLOATEXP|POINT)))){ ! 813: yylval = 1; ! 814: val = BFINT; ! 815: goto ret; ! 816: } ! 817: } ! 818: if (INCHARSET(val, HEXFLAG)){ ! 819: base = 16; ! 820: } else ! 821: if (INCHARSET(val, FLOATFLAG)){ ! 822: double atof(); ! 823: while ( (cp < &fltchr[63]) && ! 824: INCHARSET( ! 825: (val=getchar()), ! 826: (DIGIT|SIGN|FLOATEXP|POINT) ! 827: ) ! 828: ) *cp++ = val; ! 829: if (cp == fltchr) { ! 830: yylval = 1; ! 831: val = BFINT; ! 832: goto ret; ! 833: } ! 834: ungetc(val); ! 835: *cp++ = '\0'; ! 836: fltval.dvalue = atof(fltchr); ! 837: val = FLTNUM; ! 838: goto ret; ! 839: } else { ! 840: ungetc(val); ! 841: base = 8; ! 842: } ! 843: } else { ! 844: forb = getchar(); ! 845: if (forb == 'f' || forb == 'b') { ! 846: yylval = val - '0' + 1; ! 847: if (forb == 'b') ! 848: yylval = -yylval; ! 849: val = BFINT; ! 850: goto ret; ! 851: } ! 852: ungetc(forb); /* put back non zero */ ! 853: goto middle; ! 854: } ! 855: while ( (val = getchar()) == '0') ! 856: continue; ! 857: ungetc(val); ! 858: while ( INCHARSET( (val = getchar()), DIGIT) || ! 859: (base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) ) ! 860: ) ! 861: ){ ! 862: if (base==8) ! 863: intval <<= 3; ! 864: else if (base==10) ! 865: intval *= 10; ! 866: else { ! 867: intval <<= 4; ! 868: if (INCHARSET(val, HEXLDIGIT)) ! 869: val -= 'a' - 10 - '0'; ! 870: else if (INCHARSET(val, HEXUDIGIT)) ! 871: val -= 'A' - 10 - '0'; ! 872: } ! 873: middle: ! 874: *cp++ = (val -= '0'); ! 875: intval += val; ! 876: } ! 877: ungetc(val); ! 878: *cp = 0; ! 879: maxstrlg = cp - fltchr; ! 880: if ( (maxstrlg > 8) ! 881: && ( ( (base == 8) ! 882: && ( (maxstrlg>11) ! 883: || ( (maxstrlg == 11) ! 884: && (*fltchr > 3) ! 885: ) ! 886: ) ! 887: ) ! 888: || ( (base == 16) ! 889: && (maxstrlg > 8) ! 890: ) ! 891: || ( (base == 10) ! 892: && (maxstrlg >= 10) ! 893: ) ! 894: ) ! 895: ) { ! 896: val = QUAD; ! 897: get_quad(base, fltchr, cp, &quadval); ! 898: } else ! 899: val = INT; ! 900: goto ret; ! 901: ! 902: case LSH: ! 903: case RSH: ! 904: /* ! 905: * We allow the C style operators ! 906: * << and >>, as well as < and > ! 907: */ ! 908: if ( (base = getchar()) != val) ! 909: ungetc(base); ! 910: val = yylval; ! 911: goto ret; ! 912: ! 913: case MINUS: ! 914: if ( (val = getchar()) =='(') ! 915: yylval=val=MP; ! 916: else { ! 917: ungetc(val); ! 918: val=MINUS; ! 919: } ! 920: goto ret; ! 921: ! 922: case SQ: ! 923: if ((yylval = getchar()) == '\n') ! 924: scanlineno++; /*not entirely correct*/ ! 925: intval = yylval; ! 926: val = INT; ! 927: goto ret; ! 928: ! 929: case DQ: ! 930: eatstr: ! 931: linescrossed = 0; ! 932: maxstrlg = (char *)bufub - (char *)bufptr; ! 933: ! 934: if (maxstrlg < MAXSTRLG) { ! 935: ungetc('"'); ! 936: *(toktype *)bufptr = VOID ; ! 937: bufub = bufptr; ! 938: goto done; ! 939: } ! 940: if (maxstrlg > MAXSTRLG) ! 941: maxstrlg = MAXSTRLG; ! 942: ! 943: ptoken(bufptr, STRING); ! 944: lgbackpatch = bufptr; /*this is where the size goes*/ ! 945: bufptr += sizeof(lgtype); ! 946: /* ! 947: * bufptr is now set to ! 948: * be stuffed with characters from ! 949: * the input ! 950: */ ! 951: ! 952: while ( (maxstrlg > 0) ! 953: && !(INCHARSET( (val = getchar()), STRESCAPE)) ! 954: ){ ! 955: stuff: ! 956: maxstrlg-= 1; ! 957: pchar(bufptr, val); ! 958: } ! 959: if (maxstrlg <= 0){ /*enough characters to fill a string buffer*/ ! 960: ungetc('"'); /*will read it next*/ ! 961: } ! 962: else if (val == '"'); /*done*/ ! 963: else if (val == '\n'){ ! 964: yywarning("New line embedded in a string constant."); ! 965: scanlineno++; ! 966: linescrossed++; ! 967: val = getchar(); ! 968: if (val == EOFCHAR){ ! 969: do_eof: ! 970: pchar(bufptr, '\n'); ! 971: ungetc(EOFCHAR); ! 972: } else ! 973: if (val == NEEDCHAR){ ! 974: if ( (inbufptr = fillinbuffer()) == 0) ! 975: goto do_eof; ! 976: val = '\n'; ! 977: goto stuff; ! 978: } else { /* simple case */ ! 979: ungetc(val); ! 980: val = '\n'; ! 981: goto stuff; ! 982: } ! 983: } else { ! 984: val = getchar(); /*skip the '\\'*/ ! 985: if ( INCHARSET(val, BSESCAPE)){ ! 986: switch (val){ ! 987: case 'b': val = '\b'; goto stuff; ! 988: case 'f': val = '\f'; goto stuff; ! 989: case 'n': val = '\n'; goto stuff; ! 990: case 'r': val = '\r'; goto stuff; ! 991: case 't': val = '\t'; goto stuff; ! 992: } ! 993: } ! 994: if ( !(INCHARSET(val,OCTDIGIT)) ) goto stuff; ! 995: base = 0; ! 996: intval = 0; ! 997: while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){ ! 998: base++;intval <<= 3;intval += val - '0'; ! 999: val = getchar(); ! 1000: } ! 1001: ungetc(val); ! 1002: val = (char)intval; ! 1003: goto stuff; ! 1004: } ! 1005: /* ! 1006: * bufptr now points at the next free slot ! 1007: */ ! 1008: bstrfromto(lgbackpatch, bufptr); ! 1009: if (linescrossed){ ! 1010: val = ILINESKIP; ! 1011: yylval = linescrossed; ! 1012: goto ret; ! 1013: } else ! 1014: goto builtval; ! 1015: ! 1016: case BADCHAR: ! 1017: linescrossed = lineno; ! 1018: lineno = scanlineno; ! 1019: yyerror("Illegal character mapped: %d, char read:(octal) %o", ! 1020: yylval, val); ! 1021: lineno = linescrossed; ! 1022: val = BADCHAR; ! 1023: goto ret; ! 1024: ! 1025: default: ! 1026: val = yylval; ! 1027: goto ret; ! 1028: } /*end of the switch*/ ! 1029: /* ! 1030: * here with one token, so stuff it ! 1031: */ ! 1032: ret: ! 1033: oval = val; ! 1034: ptoken(bufptr, val); ! 1035: switch(val){ ! 1036: case ILINESKIP: ! 1037: pint(bufptr, yylval); ! 1038: break; ! 1039: case SIZESPEC: ! 1040: pchar(bufptr, yylval); ! 1041: break; ! 1042: case BFINT: plong(bufptr, yylval); ! 1043: break; ! 1044: case INT: plong(bufptr, intval); ! 1045: break; ! 1046: case QUAD: plong(bufptr, quadval.quad_low_long); ! 1047: plong(bufptr, quadval.quad_high_long); ! 1048: break; ! 1049: case FLTNUM: pdouble(bufptr, fltval.dvalue); ! 1050: break; ! 1051: case NAME: pptr(bufptr, (int)(struct symtab *)yylval); ! 1052: break; ! 1053: case REG: pchar(bufptr, yylval); ! 1054: break; ! 1055: case INST0: ! 1056: case INSTn: ! 1057: pchar(bufptr, yylval); ! 1058: break; ! 1059: case IJXXX: ! 1060: pchar(bufptr, yylval); ! 1061: pptr(bufptr, (int)(struct symtab *)symalloc()); ! 1062: break; ! 1063: case ISTAB: ! 1064: case ISTABSTR: ! 1065: case ISTABNONE: ! 1066: case ISTABDOT: ! 1067: case IALIGN: ! 1068: pptr(bufptr, (int)(struct symtab *)symalloc()); ! 1069: break; ! 1070: /* ! 1071: * default: ! 1072: */ ! 1073: } ! 1074: builtval: ; ! 1075: } /*end of the while to stuff the buffer*/ ! 1076: done: ! 1077: bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]); ! 1078: ! 1079: /* ! 1080: * This is a real kludge: ! 1081: * ! 1082: * We put the last token in the buffer to be a MINUS ! 1083: * symbol. This last token will never be picked up ! 1084: * in the normal way, but can be looked at during ! 1085: * a peekahead look that the short circuit expression ! 1086: * evaluator uses to see if an expression is complicated. ! 1087: * ! 1088: * Consider the following situation: ! 1089: * ! 1090: * .word 45 + 47 ! 1091: * buffer 1 | buffer 0 ! 1092: * the peekahead would want to look across the buffer, ! 1093: * but will look in the buffer end zone, see the minus, and ! 1094: * fail. ! 1095: */ ! 1096: ptoken(bufptr, MINUS); ! 1097: InBufPtr = inbufptr; /*copy this back*/ ! 1098: } ! 1099: ! 1100: struct Quad _quadtemp; ! 1101: get_quad(radix, cp_start, cp_end, quadptr) ! 1102: int radix; ! 1103: char *cp_start, *cp_end; ! 1104: struct Quad *quadptr; ! 1105: { ! 1106: register char *cp = cp_start; /* r11 */ ! 1107: register struct Quad *qp = quadptr; /* r10 */ ! 1108: register long temp; /* r9 */ ! 1109: ! 1110: asm("clrq (r10)"); ! 1111: for (; cp < cp_end; cp++){ ! 1112: switch (radix) { ! 1113: case 8: ! 1114: asm ("ashq $3, (r10), (r10)"); ! 1115: break; ! 1116: case 16: ! 1117: asm ("ashq $4, (r10), (r10)"); ! 1118: break; ! 1119: case 10: ! 1120: asm ("ashq $1, (r10), __quadtemp"); ! 1121: asm ("ashq $3, (r10), (r10)"); ! 1122: asm ("addl2 __quadtemp, (r10)"); ! 1123: asm ("adwc __quadtemp+4, 4(r10)"); ! 1124: break; ! 1125: } ! 1126: asm ("cvtbl (r11), r9"); ! 1127: asm ("addl2 r9, (r10)"); ! 1128: asm ("adwc $0, 4(r10)"); ! 1129: } ! 1130: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.