|
|
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.