|
|
1.1 ! root 1: /* ! 2: * This is the controlling loop in the assembler. ! 3: * ! 4: */ ! 5: #include <utype.h> ! 6: #include <asm.h> ! 7: #include <asflags.h> ! 8: #include <y_tab.h> ! 9: #include <symtab.h> ! 10: ! 11: /* states */ ! 12: #define INITIAL 0 ! 13: #define INSYM 1 ! 14: #define INCHAR 2 /* in char constant */ ! 15: #define LTS 3 ! 16: #define GTS 4 ! 17: #define BSLP 5 /* back slash while reading parms */ ! 18: #define WHITE 6 /* in white space */ ! 19: #define ENDLINE 7 ! 20: #define CSTATE 8 /* Pick up parms in macro expansion */ ! 21: #define INTOKEN 9 ! 22: ! 23: #define OPONLY1 10 /* search for operator only */ ! 24: #define OPONLY2 11 ! 25: #define OPONLY3 12 ! 26: #define OPONLY4 13 ! 27: ! 28: #define INSTR 14 /* string detected */ ! 29: #define BSL 15 /* back slash */ ! 30: #define BSLDIG 16 /* digit after back slash */ ! 31: ! 32: #define CMSTATE 17 /* pick up names in macro definition */ ! 33: #define INNAME 18 ! 34: ! 35: #define LZERO 19 /* lead zero */ ! 36: #define XNUM 20 /* hex number */ ! 37: #define DNUM 21 /* decimal number */ ! 38: #define ONUM 22 /* octal number */ ! 39: #define BNUM 23 /* binary number */ ! 40: ! 41: #define BANGS 24 /* ! seen */ ! 42: #define EQUS 25 /* = seen */ ! 43: ! 44: #define DSTATE 26 /* eat whole line for S_EQUS */ ! 45: ! 46: /* positions */ ! 47: #define LABEL 0 ! 48: #define OPCODE 1 ! 49: #define OPERAND 2 ! 50: #define COMMENT 3 ! 51: ! 52: /* comparisons */ ! 53: #define LT 1 ! 54: #define GT 2 ! 55: #define EQ 4 ! 56: ! 57: #define RET(toYacc) return(lastToken = (toYacc)) ! 58: #define RSTATE(toYacc, newstate) { state = newstate; RET(toYacc); } ! 59: #define NEWS(newstate) { state = newstate; continue; } ! 60: ! 61: static unsigned short state = INITIAL; ! 62: static unsigned short pstate; /* previous state when \ detected */ ! 63: static unsigned short pos = LABEL; ! 64: ! 65: static unsigned short ctype; /* current logic type */ ! 66: ! 67: static char buf[1024], *bp = buf; ! 68: static char *backOff; /* start of decimal number */ ! 69: static char fromMac = ' '; /* ' ' or '+' */ ! 70: static short opIx; /* index of current opcode */ ! 71: static psw = 0; ! 72: static long number = 0; ! 73: static char token[1024], *tp; ! 74: ! 75: static int lastChar; /* last Character in */ ! 76: static short vctr, scnt, dcnt; ! 77: static symt *stype; ! 78: static short ytype; ! 79: ! 80: /* ! 81: * Invalid character message. ! 82: */ ! 83: static void ! 84: invChar(c, s) ! 85: register short c; ! 86: char *s; ! 87: { ! 88: unsigned short p; ! 89: ! 90: p = bp - lastL; ! 91: if (isprint(c)) ! 92: yyerror("Invalid character '%c' %s at position %d", c, s, p); ! 93: /**/ ! 94: else ! 95: yyerror("Invalid character 0x%02x %s at position %d", ! 96: c & 255, s, p); /**/ ! 97: } ! 98: ! 99: /* ! 100: * Expand parms in macro line. ! 101: * # as first char of line foils replacment. ! 102: */ ! 103: static char * ! 104: expand(s, recurs) ! 105: register char *s; ! 106: { ! 107: register char c; ! 108: char *tp, *rep, *newl, *start; ! 109: macro *mac; ! 110: short sav, pb; ! 111: unsigned short point; ! 112: ! 113: start = s; ! 114: pb = 0; ! 115: for(state = WHITE; ; ) { ! 116: switch(state) { ! 117: case WHITE: ! 118: if (isalpha(c = *s++)) { ! 119: state = INSYM; ! 120: tp = token; ! 121: *tp++ = c; ! 122: break; ! 123: } ! 124: pb = 0; ! 125: break; ! 126: case INSYM: ! 127: if (isalnum(c = *s++)) { ! 128: *tp++ = c; ! 129: break; ! 130: } ! 131: mac = NULL; ! 132: *tp = '\0'; ! 133: if ((!recurs && (NULL != trueMac) && ! 134: (NULL != (rep = lookList(token)))) || ! 135: (NULL != (mac = macLookUp(token, MACSTR)))) { ! 136: tp = --s - (strlen(token) + pb); ! 137: sav = *tp; /* stomp parm name */ ! 138: *tp = '\0'; ! 139: if (NULL == mac) /* parm match */ ! 140: rep = expand(rep, 1); ! 141: else { /* equs match */ ! 142: rep = mac->names->str; ! 143: mac->type = MACSCAN; ! 144: rep = expand(rep, 1); ! 145: mac->type = MACSTR; ! 146: } ! 147: point = strlen(start) + strlen(rep); ! 148: newl = galloc(point + strlen(s) + 1); ! 149: sprintf(newl, "%s%s%s", start, rep, s); ! 150: *tp = sav; /* Un stomp parm name */ ! 151: start = newl; ! 152: s = start + point; /* don't rescan */ ! 153: } ! 154: pb = (c == '\\'); ! 155: state = WHITE; ! 156: } ! 157: if (!c) ! 158: break; ! 159: } ! 160: return(start); ! 161: } ! 162: ! 163: /* ! 164: * Get next line from macro or while. ! 165: */ ! 166: static char * ! 167: nextMac() ! 168: { ! 169: macctl *tmp; ! 170: macline *l; ! 171: extern char *strcpy(); ! 172: ! 173: for(;;) { ! 174: if (NULL == macExp) { /* not in a macro */ ! 175: fromMac = ' '; ! 176: return(NULL); ! 177: } ! 178: if (NULL != (l = macExp->curr)) { ! 179: fromMac = '+'; ! 180: macExp->curr = l->next; ! 181: return(strcpy(buf, l->line)); ! 182: } ! 183: ! 184: if ((tmp = macExp) == trueMac) { /* popping macro */ ! 185: freeList(macExp->parms); ! 186: ! 187: while(logic->expno == trueMac->expno) { ! 188: if ((logic->type == INWDEF) || ! 189: (logic->type == INPWDEF)) ! 190: yyerror("End of macro building .while"); ! 191: /* A \fB.macro\fR ended while reading in a ! 192: * \fB.while\fR loop. */ ! 193: freeLevel(); ! 194: } ! 195: ! 196: do { ! 197: trueMac = trueMac->prev; ! 198: } while((NULL != trueMac) && ! 199: (trueMac->type != MACTYPE)); ! 200: } ! 201: ! 202: macExp = macExp->prev; /* pop a level */ ! 203: free((char *)tmp); ! 204: } ! 205: } ! 206: ! 207: /* ! 208: * Save a line in a macro. ! 209: */ ! 210: saveLine() ! 211: { ! 212: macline *newl; ! 213: ! 214: newl = (macline *)alloc((unsigned)(sizeof(*newl) + strlen(lastL))); ! 215: strcpy(newl->line, lastL); ! 216: if (NULL == inMacDef->first) ! 217: lastDef = inMacDef->first = newl; ! 218: else { ! 219: lastDef->next = newl; ! 220: lastDef = newl; ! 221: } ! 222: } ! 223: ! 224: /* ! 225: * Get a line off a file. ! 226: */ ! 227: static char * ! 228: getLine() ! 229: { ! 230: register char *line; ! 231: ! 232: ++statement; /* increment statement number */ ! 233: if (NULL != (line = nextMac())) ! 234: return(line); ! 235: ! 236: while(NULL == (fgets(line = buf, sizeof(buf), inpc->fp))) { ! 237: if (NULL != inpc->prev) { ! 238: inpctl *tmp; ! 239: ! 240: fclose(inpc->fp); ! 241: inpc = (tmp = inpc)->prev; ! 242: free((char *)tmp); ! 243: } ! 244: else { /* end of pass */ ! 245: for(;NORMAL != logic->type; freeLevel()) { ! 246: switch(logic->type) { ! 247: case INMACDEF: ! 248: case PMACDEF: ! 249: yyerror("Missing .endm"); ! 250: /* Input ended leaving \fB.macro\fR open. */ ! 251: break; ! 252: case INIF0: ! 253: case INIF1: ! 254: case INIFX: ! 255: yyerror("Missing .endi"); ! 256: /* Input ended leaving \fB.if\fR open. */ ! 257: break; ! 258: case INWDEF: ! 259: case INPWDEF: ! 260: yyerror("Missing .endw"); ! 261: /* Input ended leaving \fB.while\fR open. */ ! 262: } ! 263: } ! 264: if (2 == pass) { ! 265: cleanUp(); ! 266: ! 267: switch (errCt) { ! 268: case 0: ! 269: exit(0); ! 270: case 1: ! 271: fprintf(errdev, "1 Error\n"); ! 272: break; ! 273: default: ! 274: fprintf(errdev, "%d Errors\n", errCt); ! 275: } ! 276: unlink(outName); ! 277: exit(1); ! 278: } ! 279: else { /* avoid close & open */ ! 280: rewind(inpc->fp); ! 281: inpc->lineNo = 0; ! 282: statement = 1; ! 283: ! 284: newPass(outName); ! 285: ! 286: /* reset compiler switches to initial state */ ! 287: alignon = alignonX; ! 288: lswitch = lswitchX; ! 289: nswitch = nswitchX; ! 290: wswitch = wswitchX; ! 291: fswitch = fswitchX; ! 292: bswitch = bswitchX; ! 293: ! 294: dodefs(); ! 295: outLine((char *)NULL, 0); ! 296: continue; ! 297: } ! 298: } ! 299: } ! 300: inpc->lineNo++; ! 301: return(line); ! 302: } ! 303: ! 304: /* ! 305: * In OPONLY3 we found an op process it. ! 306: * separated to keep from crashing Coherent compiler in cc2. ! 307: */ ! 308: static unsigned short ! 309: procOp() ! 310: { ! 311: register opc *op; ! 312: ! 313: *tp = '\0'; ! 314: bp--; ! 315: if (-1 == (opIx = opLookUp(token))) ! 316: return(OPONLY4); ! 317: ! 318: if (INIF1 <= ctype) ! 319: fatal("Logic error in macro def '%s' %d", token, ctype); /* TECH */ ! 320: ! 321: op = prefTab + opIx; ! 322: switch(op->kind) { /* switch on function type */ ! 323: case S_MACRO: ! 324: if (ctype < INIF0) ! 325: newLevel(PMACDEF); ! 326: break; ! 327: case S_ENDM: ! 328: switch(ctype) { ! 329: case INMACDEF: ! 330: inMacDef = (macro *)NULL; ! 331: lastDef = (macline *)NULL; ! 332: freeLevel(); ! 333: return(INITIAL); ! 334: case PMACDEF: ! 335: freeLevel(); ! 336: } ! 337: break; ! 338: case S_WHILE: ! 339: switch(ctype) { ! 340: case INWDEF: ! 341: case INPWDEF: ! 342: newLevel(INPWDEF); ! 343: } ! 344: break; ! 345: case S_ENDW: ! 346: switch(ctype) { ! 347: case INWDEF: { ! 348: macctl *tmp; ! 349: saveLine(); ! 350: logic = (tmp = logic)->prev; ! 351: tmp->type = WHILETYPE; ! 352: tmp->curr = tmp->first = inMacDef->first; ! 353: tmp->parms = tmp->names = NULL; ! 354: tmp->prev = macExp; ! 355: macExp = tmp; ! 356: free((char *)inMacDef); ! 357: lastDef = (macline *)NULL; ! 358: inMacDef = (macro *)NULL; ! 359: return(INITIAL); ! 360: } ! 361: case INPWDEF: ! 362: freeLevel(); ! 363: break; ! 364: } ! 365: break; ! 366: case S_IF: ! 367: switch(ctype) { ! 368: case INIF0: ! 369: case INIFX: ! 370: newLevel(INIFX); ! 371: } ! 372: break; ! 373: case S_ELSE: ! 374: switch(ctype) { ! 375: case INIF0: ! 376: logic->type = INIF1; ! 377: return(INITIAL); ! 378: } ! 379: break; ! 380: case S_ENDI: ! 381: switch(ctype) { ! 382: case INIF0: ! 383: case INIFX: ! 384: freeLevel(); ! 385: } ! 386: break; ! 387: } ! 388: return(OPONLY4); ! 389: } ! 390: ! 391: /* ! 392: * Read line and start processing. ! 393: * separated from yylex() to keep from crashing compiler in cc2. ! 394: */ ! 395: static unsigned short ! 396: startLine() ! 397: { ! 398: register short c; ! 399: ! 400: do { /* GNU outputs # line numbers */ ! 401: if (';' != lastChar) { ! 402: outLine(lastL, fromMac); ! 403: bp = lastL = getLine(); ! 404: } ! 405: if (COMMA != lastToken) ! 406: freel(); /* trash free space from last line */ ! 407: } while ('#' == *bp); ! 408: ! 409: ctype = logic->type; ! 410: ! 411: if (('#' != *bp) && ! 412: (';' != lastChar) && ! 413: (defCt || (NULL != trueMac)) && ! 414: ((ctype > INPWDEF) || (ctype < INWDEF))) { ! 415: bp = lastL = expand(bp, 0); ! 416: ! 417: if ((lastL != buf) && (fromMac != '+')) { ! 418: outLine(buf, fromMac); ! 419: fromMac = '@'; ! 420: } ! 421: } ! 422: ! 423: if ('#' == *bp) /* don't lex noexpand */ ! 424: bp++; ! 425: ! 426: if (COMMA == lastToken) /* continuation line ? */ ! 427: return(psw); ! 428: ! 429: lastChar = c = *bp; /* get a char */ ! 430: if (ctype < INIF1) { ! 431: if ((' ' == c) || ('\t' == c)) ! 432: return(OPONLY1); ! 433: else if (isalpha(c)) ! 434: return(OPONLY2); ! 435: else ! 436: return(OPONLY4); ! 437: } ! 438: if ((' ' == c) || ('\t' == c)) { ! 439: pos = OPCODE; ! 440: return(WHITE); ! 441: } ! 442: if (isalpha(c)) { ! 443: pos = LABEL; ! 444: tp = token; ! 445: *tp++ = c; ! 446: return(INSYM); ! 447: } ! 448: switch(c) { ! 449: case '/': case '\n': case 0: case ';': ! 450: break; ! 451: default: ! 452: invChar(c, ""); ! 453: } ! 454: return(INITIAL); ! 455: } ! 456: ! 457: /* ! 458: * Got an opcode, set it up. ! 459: */ ! 460: static ! 461: doOp(opIx) ! 462: { ! 463: register opc *op; ! 464: ! 465: lflags = 0; ! 466: stype = typTab + (kind = (op = prefTab + opIx)->kind); ! 467: yylval.o = op; ! 468: pos = OPERAND; ! 469: /* op code determines operand syntax */ ! 470: switch(ytype = stype->type) { ! 471: case NCMD: ! 472: RSTATE(ytype, ENDLINE) ! 473: case OP: ! 474: if (stype->bldr & REP_INSTR) ! 475: pos = OPCODE; ! 476: case ICMD: ! 477: case DATA: ! 478: RSTATE(ytype, WHITE) ! 479: case ECMD: ! 480: case ECMDX: ! 481: case CMD: ! 482: if (S_EQUS == kind) { ! 483: tp = token; ! 484: scnt = dcnt = 0; ! 485: RSTATE(ytype, DSTATE) ! 486: } ! 487: RSTATE(ytype, CSTATE) ! 488: case DCMD: ! 489: RSTATE(ytype, CMSTATE) ! 490: default: ! 491: fatal("Optype %d in lex", ytype); /* TECH */ ! 492: } ! 493: } ! 494: ! 495: /* ! 496: * get tokens ! 497: */ ! 498: yylex() ! 499: { ! 500: register short c; ! 501: ! 502: for(;;) { ! 503: /* ! 504: * Allow Japaneese comments and strings, catch other non ascii ! 505: * and abort the line. ! 506: */ ! 507: if ((state != INITIAL) && ! 508: !isascii(lastChar = c = *bp++) && ! 509: (state != INSTR) && ! 510: (state != INCHAR)) { ! 511: invChar(c, ""); ! 512: RSTATE(NL, INITIAL) ! 513: } ! 514: ! 515: switch(state) { ! 516: case INITIAL: /* start of line */ ! 517: bcnt = pcnt = 0; ! 518: psw = startLine(); ! 519: lastChar = c = *bp++; ! 520: if (!isascii(c)) { ! 521: invChar(c, ""); ! 522: RSTATE(NL, INITIAL) ! 523: } ! 524: NEWS(psw); ! 525: ! 526: case OPONLY1: /* find start of opcode */ ! 527: switch(c) { ! 528: case ' ': ! 529: case '\t': ! 530: continue; ! 531: default: ! 532: if (!islower(c)) ! 533: NEWS(OPONLY4) ! 534: tp = token; ! 535: *tp++ = c; ! 536: NEWS(OPONLY3) ! 537: } ! 538: ! 539: case OPONLY2: /* bypass label */ ! 540: if (isalnum(c)) ! 541: continue; ! 542: --bp; ! 543: if ((' ' == c) || ('\t' == c)) ! 544: NEWS(OPONLY1) ! 545: NEWS(OPONLY4) ! 546: ! 547: case OPONLY3: ! 548: if (isalnum(c)) { /* accumulate opcode */ ! 549: *tp++ = c; ! 550: continue; ! 551: } ! 552: NEWS(procOp()); ! 553: ! 554: case OPONLY4: /* default processing */ ! 555: if (logic->type < INIF0) ! 556: saveLine(); ! 557: NEWS(INITIAL) ! 558: ! 559: case INSYM: ! 560: if (isalnum(c)) { ! 561: *tp++ = c; ! 562: continue; ! 563: } ! 564: *tp = '\0'; ! 565: --bp; ! 566: if (pos == OPERAND) { ! 567: sym *sp; ! 568: ! 569: sp = symLookUp(token, S_UNDEF, 0L, 0); ! 570: switch(sp->type) { ! 571: case IDENTIFIER: ! 572: case REG: ! 573: case LEN: ! 574: yylval.s = sp; ! 575: break; ! 576: case NUMBER: ! 577: yylval.val = sp->loc; ! 578: } ! 579: RSTATE(sp->type, WHITE) ! 580: } ! 581: ! 582: /* pos != OPERAND may be opcode or label */ ! 583: if (':' != c) { ! 584: if (-1 != (opIx = opLookUp(token))) ! 585: return(doOp(opIx)); ! 586: ! 587: if (NULL != (macFound = macLookUp(token, MACTYPE))) { ! 588: static opc smac = { /* fake opcode */ ! 589: 0, S_MAC ! 590: }; ! 591: ! 592: yylval.o = &smac; /* macro expansion */ ! 593: RSTATE(CMD, CSTATE) ! 594: } ! 595: ! 596: if (!strcmp(token, ".")) { ! 597: yylval.t = token; ! 598: pos = OPCODE; ! 599: RSTATE(TOKEN, WHITE) ! 600: } ! 601: } ! 602: ! 603: if ((pos == LABEL) || (':' == c)) { ! 604: yylval.t = token; ! 605: pos = OPCODE; ! 606: RSTATE(TOKEN, WHITE) ! 607: } ! 608: ! 609: yyerror("Invalid opcode: '%s'", token); ! 610: /* The string in the opcode position is ! 611: * not one of our opcodes or one of ! 612: * your macros. */ ! 613: RSTATE(NL, INITIAL) ! 614: ! 615: case DSTATE: /* eat whole line for define */ ! 616: switch(c) { ! 617: case '"': ! 618: if (dcnt) ! 619: dcnt = 0; ! 620: else if (!scnt) ! 621: dcnt = 1; ! 622: break; ! 623: case '\'': ! 624: if (scnt) ! 625: scnt = 0; ! 626: else if (!dcnt) ! 627: scnt = 1; ! 628: break; ! 629: case '\\': ! 630: *tp++ = c; ! 631: psw = state; ! 632: NEWS(BSLP) ! 633: case '/': ! 634: if (scnt | dcnt) ! 635: break; ! 636: case 0: /* let # define take semicolon */ ! 637: case '\n': ! 638: *tp = '\0'; ! 639: yylval.t = trim(token); ! 640: RSTATE(TOKEN, ENDLINE) ! 641: } ! 642: *tp++ = c; ! 643: continue; ! 644: ! 645: case CSTATE: /* pick up parms on macro expansion */ ! 646: state = psw = INTOKEN; ! 647: *(tp = token) = '\0'; ! 648: scnt = dcnt = pcnt = bcnt = 0; ! 649: vctr = 1; ! 650: switch(c) { ! 651: case 0: ! 652: case ';': ! 653: case '\n': ! 654: case '/': ! 655: if (COMMA == lastToken) ! 656: NEWS(INITIAL) ! 657: RSTATE(NL, INITIAL) ! 658: case ',': ! 659: switch(lastToken) { ! 660: case CMD: ! 661: case COMMA: ! 662: bp--; ! 663: yylval.t = token; ! 664: RSTATE(TOKEN, CSTATE) ! 665: } ! 666: RSTATE(COMMA, CSTATE) ! 667: } ! 668: ! 669: case INTOKEN: /* pick up parms on macro expansion */ ! 670: switch(c) { ! 671: case '(': ! 672: pcnt += vctr; break; ! 673: case ')': ! 674: if (pcnt) ! 675: pcnt -= vctr; ! 676: break; ! 677: case '[': ! 678: bcnt += vctr; break; ! 679: case ']': ! 680: if (bcnt) ! 681: bcnt -= vctr; ! 682: break; ! 683: case '"': ! 684: if (dcnt) ! 685: dcnt = 0; ! 686: else if (!scnt) ! 687: dcnt = 1; ! 688: vctr = (dcnt | scnt) ^ 1; ! 689: break; ! 690: case '\'': ! 691: if (scnt) ! 692: scnt = 0; ! 693: else if (!dcnt) ! 694: scnt = 1; ! 695: vctr = (dcnt | scnt) ^ 1; ! 696: break; ! 697: case '\\': ! 698: *tp++ = c; ! 699: psw = state; ! 700: NEWS(BSLP) ! 701: ! 702: case ';': ! 703: case '/': ! 704: if (!vctr) ! 705: break; ! 706: case 0: ! 707: case '\n': ! 708: if (pcnt | bcnt | scnt | dcnt) { ! 709: yyerror("Unmatched bracket in parmeter"); ! 710: /* Line ended leaving an open bracket or parenthesis. */ ! 711: RSTATE(NL, INITIAL) ! 712: } ! 713: --bp; ! 714: *tp = '\0'; ! 715: if (*(yylval.t = trim(token))) ! 716: RSTATE(TOKEN, CSTATE) ! 717: NEWS(CSTATE) ! 718: case ',': ! 719: if (pcnt | bcnt | scnt | dcnt) ! 720: break; ! 721: --bp; ! 722: *tp = '\0'; ! 723: yylval.t = trim(token); ! 724: switch(ytype) { ! 725: case ECMD: ! 726: case ECMDX: ! 727: RSTATE(TOKEN, WHITE) ! 728: } ! 729: RSTATE(TOKEN, CSTATE) ! 730: } ! 731: *tp++ = c; ! 732: continue; ! 733: ! 734: case BSLP: /* back slash while reading parm */ ! 735: switch(c) { ! 736: case 0: ! 737: case '\n': ! 738: --bp; ! 739: yyerror("End of line after backslash reading parm"); ! 740: /* Macro parmeters may not be broken up with backslash. */ ! 741: break; ! 742: } ! 743: *tp++ = c; ! 744: NEWS(psw) ! 745: ! 746: case CMSTATE: /* pick up names on macro definition */ ! 747: psw = state = INNAME; ! 748: tp = token; ! 749: switch(c) { ! 750: case ',': ! 751: RET(COMMA); ! 752: case 0: ! 753: case ';': ! 754: case '\n': ! 755: case '/': ! 756: if (COMMA == lastToken) ! 757: NEWS(INITIAL) ! 758: RSTATE(NL, INITIAL) ! 759: } ! 760: case INNAME: /* pick up parms on macro definition */ ! 761: switch(c) { ! 762: case 0: ! 763: case ';': ! 764: case '\n': ! 765: case '/': ! 766: case ',': ! 767: --bp; ! 768: *tp = '\0'; ! 769: if (*(yylval.t = trim(token))) ! 770: RSTATE(TOKEN, CMSTATE) ! 771: NEWS(CMSTATE) ! 772: default: ! 773: if (ispunct(c)) { ! 774: invChar(c, "in macro name"); ! 775: RSTATE(NL, INITIAL) ! 776: } ! 777: } ! 778: *tp++ = c; ! 779: continue; ! 780: ! 781: ! 782: case WHITE: ! 783: /* ! 784: * This piece of code is heavily trafficked. ! 785: * Force the fastest form of switch statement ! 786: * by covering many cases. ! 787: */ ! 788: switch(c) { ! 789: case '1': case '2': case '3': case '4': ! 790: case '5': case '6': case '7': case '8': ! 791: case '9': case '0': ! 792: backOff = bp - 1; ! 793: if (number = c - '0') ! 794: NEWS(DNUM) ! 795: NEWS(LZERO); ! 796: ! 797: /* % allowed as first char only */ ! 798: case 'a': case 'b': case 'c': case 'd': ! 799: case 'e': case 'f': case 'g': case 'h': ! 800: case 'i': case 'j': case 'k': case 'l': ! 801: case 'm': case 'n': case 'o': case 'p': ! 802: case 'q': case 'r': case 's': case 't': ! 803: case 'u': case 'v': case 'w': case 'x': ! 804: case 'y': case 'z': ! 805: case 'A': case 'B': case 'C': case 'D': ! 806: case 'E': case 'F': case 'G': case 'H': ! 807: case 'I': case 'J': case 'K': case 'L': ! 808: case 'M': case 'N': case 'O': case 'P': ! 809: case 'Q': case 'R': case 'S': case 'T': ! 810: case 'U': case 'V': case 'W': case 'X': ! 811: case 'Y': case 'Z': case '?': case '_': ! 812: case '%': case '.': ! 813: tp = token; ! 814: *tp++ = c; ! 815: NEWS(INSYM) ! 816: ! 817: case ' ': ! 818: case '\t': ! 819: continue; ! 820: case 0: ! 821: case ';': ! 822: case '\n': ! 823: case '/': ! 824: if (COMMA == lastToken) ! 825: NEWS(INITIAL) ! 826: RSTATE(NL, INITIAL) ! 827: case '<': ! 828: NEWS(LTS) ! 829: case '>': ! 830: NEWS(GTS) ! 831: case '!': ! 832: NEWS(BANGS) ! 833: case '=': ! 834: NEWS(EQUS) ! 835: case '+': ! 836: RET(PLUS); ! 837: case '-': ! 838: RET(MINUS); ! 839: case '*': ! 840: RET(TIMES); ! 841: case ':': ! 842: if (OPERAND == pos) ! 843: RET(COLON); ! 844: pos = OPCODE; ! 845: RSTATE(NL, WHITE) ! 846: ! 847: case '&': ! 848: RET(AND); ! 849: case '|': ! 850: RET(OR); ! 851: case '^': ! 852: RET(XOR); ! 853: case '#': ! 854: RET(P_SIGN); ! 855: case '$': ! 856: RET(D_SIGN); ! 857: case '~': ! 858: RET(NOT); ! 859: case ',': ! 860: psw = WHITE; ! 861: RET(COMMA); ! 862: /* ! 863: * This assembler may reverse the normal usage of ! 864: * brackets and parentheses. That is expressions ! 865: * are put in []. 5(%eax) is 5 past %eax. ! 866: * bswitch flips this back. Keeps counts to improve ! 867: * the syntax error message. ! 868: */ ! 869: case '[': ! 870: bcnt++; ! 871: RET(bswitch ? LBRACK : LPAREN); ! 872: case ']': ! 873: bcnt--; ! 874: RET(bswitch ? RBRACK : RPAREN); ! 875: case '(': ! 876: pcnt++; ! 877: RET(bswitch ? LPAREN : LBRACK); ! 878: case ')': ! 879: pcnt--; ! 880: RET(bswitch ? RPAREN : RBRACK); ! 881: case '@': ! 882: RET(AT); ! 883: case '"': ! 884: psw = WHITE; ! 885: tp = token; ! 886: NEWS(INSTR) ! 887: case '\'': ! 888: psw = WHITE; ! 889: tp = token; ! 890: NEWS(INCHAR) ! 891: default: ! 892: invChar(c, "as token start"); ! 893: RSTATE(NL, INITIAL) ! 894: } ! 895: ! 896: case ONUM: ! 897: if (isdigit(c)) { ! 898: if (c > '7') ! 899: yyerror("Error in octal number"); /**/ ! 900: number *= 8; ! 901: number += c - '0'; ! 902: continue; ! 903: } ! 904: bp--; ! 905: yylval.val = number; ! 906: RSTATE(NUMBER, WHITE) ! 907: ! 908: case BNUM: ! 909: if (isdigit(c)) { ! 910: if (c > '1') ! 911: yyerror("Error in binary number"); /**/ ! 912: number *= 2; ! 913: number += c - '0'; ! 914: continue; ! 915: } ! 916: bp--; ! 917: yylval.val = number; ! 918: RSTATE(NUMBER, WHITE) ! 919: ! 920: case XNUM: ! 921: if (isxdigit(c)) { ! 922: number *= 16; ! 923: if (isdigit(c)) ! 924: number += c - '0'; ! 925: else if (islower(c)) ! 926: number += c - ('a' - 10); ! 927: else ! 928: number += c - ('A' - 10); ! 929: continue; ! 930: } ! 931: bp--; ! 932: yylval.val = number; ! 933: RSTATE(NUMBER, WHITE) ! 934: ! 935: case DNUM: ! 936: if (isdigit(c)) { ! 937: number *= 10; ! 938: number += c - '0'; ! 939: continue; ! 940: } ! 941: if (('.' == c) || ('e' == c) || ('E' == c)) { ! 942: yylval.dbl = strtod(backOff, &bp); ! 943: RSTATE(FNUM, WHITE) ! 944: } ! 945: bp--; ! 946: yylval.val = number; ! 947: RSTATE(NUMBER, WHITE) ! 948: ! 949: case LZERO: ! 950: switch(c) { ! 951: case '.': ! 952: yylval.dbl = strtod(backOff, &bp); ! 953: RSTATE(FNUM, WHITE) ! 954: case 'x': ! 955: case 'X': ! 956: NEWS(XNUM) ! 957: case 'b': ! 958: case 'B': ! 959: NEWS(BNUM) ! 960: default: ! 961: bp--; ! 962: if (isdigit(c)) ! 963: NEWS(ONUM) ! 964: yylval.val = number; ! 965: RSTATE(NUMBER, WHITE) ! 966: } ! 967: ! 968: case LTS: /* < seen */ ! 969: switch(c) { ! 970: case '<': ! 971: RSTATE(LSHIFT, WHITE) ! 972: case '=': ! 973: yylval.val = (LT|EQ); ! 974: break; ! 975: default: ! 976: --bp; ! 977: yylval.val = LT; ! 978: } ! 979: RSTATE(COMPARISON, WHITE) ! 980: ! 981: case GTS: /* > seen */ ! 982: switch(c) { ! 983: case '=': ! 984: yylval.val = (GT|EQ); ! 985: break; ! 986: case '>': ! 987: RSTATE(RSHIFT, WHITE) ! 988: default: ! 989: --bp; ! 990: yylval.val = GT; ! 991: } ! 992: RSTATE(COMPARISON, WHITE) ! 993: ! 994: case EQUS: /* = seen take = or == */ ! 995: if (OPCODE == pos) { ! 996: --bp; ! 997: opIx = opLookUp(".equ"); ! 998: return(doOp(opIx)); ! 999: } ! 1000: if ('=' != c) ! 1001: --bp; ! 1002: yylval.val = EQ; ! 1003: RSTATE(COMPARISON, WHITE) ! 1004: ! 1005: case BANGS: /* ! seen */ ! 1006: if ('=' == c) { ! 1007: yylval.val = (GT|LT); ! 1008: RSTATE(COMPARISON, WHITE) ! 1009: } ! 1010: --bp; ! 1011: RSTATE(BANG, WHITE) ! 1012: ! 1013: case INSTR: ! 1014: case INCHAR: ! 1015: switch(c) { ! 1016: case 0: ! 1017: case '\n': ! 1018: --bp; ! 1019: if (state == INSTR) { ! 1020: yyerror("End of line detected in string"); /**/ ! 1021: *tp = '\0'; ! 1022: yylval.t = token; ! 1023: RSTATE(TOKEN, psw) ! 1024: } ! 1025: yyerror("End of line detected in character constant"); ! 1026: /**/ ! 1027: case '\'': ! 1028: if (state != INCHAR) ! 1029: break; ! 1030: *tp = '\0'; ! 1031: if (strlen(token) != 1) ! 1032: yyerror("Character constant %d long", ! 1033: strlen(token)); ! 1034: /* Character constants must be one byte long. */ ! 1035: yylval.val = token[0]; ! 1036: RSTATE(NUMBER, psw) ! 1037: case '"': ! 1038: if (state != INSTR) ! 1039: break; ! 1040: *tp = '\0'; ! 1041: yylval.t = token; ! 1042: RSTATE(TOKEN, psw) ! 1043: case '\\': ! 1044: pstate = state; ! 1045: NEWS(BSL) ! 1046: } ! 1047: *tp++ = c; ! 1048: continue; ! 1049: ! 1050: case BSL: /* back slash */ ! 1051: switch(c) { ! 1052: case 0: ! 1053: case '\n': ! 1054: --bp; ! 1055: yyerror("End of line after backslash"); ! 1056: /**/ ! 1057: break; ! 1058: case 'n': ! 1059: *tp++ = '\n'; break; ! 1060: case 'r': ! 1061: *tp++ = '\r'; break; ! 1062: case 't': ! 1063: *tp++ = '\t'; break; ! 1064: case 'b': ! 1065: *tp++ = '\b'; break; ! 1066: case 'f': ! 1067: *tp++ = '\f'; break; ! 1068: default: ! 1069: if ((c >= '0') && (c <= '7')) { ! 1070: number = 0; ! 1071: bp--; ! 1072: NEWS(BSLDIG) ! 1073: } ! 1074: *tp++ = c; ! 1075: } ! 1076: NEWS(pstate) ! 1077: ! 1078: case BSLDIG: /* accumulate octal number */ ! 1079: if ((c >= '0') && (c <= '7')) { ! 1080: number *= 8; ! 1081: number += c - '0'; ! 1082: continue; ! 1083: } ! 1084: if (number > 255) { ! 1085: yyerror("Octal number %ld truncated to char", number); ! 1086: /* An octal number in a string was too big. */ ! 1087: number &= 255; ! 1088: } ! 1089: if (!number) { ! 1090: yyerror("Cannot insert \\0 in string"); ! 1091: /* NUL (\e0) terminates strings. ! 1092: * Instead of ! 1093: * .DM ! 1094: * .byte "hello\en\e0" ! 1095: * .DE ! 1096: * use: ! 1097: * .DM ! 1098: * .byte "hello\en", 0 ! 1099: * .DE */ ! 1100: } ! 1101: *tp++ = number; ! 1102: bp--; ! 1103: NEWS(pstate) ! 1104: ! 1105: case ENDLINE: ! 1106: RSTATE(NL, INITIAL) ! 1107: } ! 1108: } ! 1109: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.