|
|
1.1 root 1: /* @(#) scan.c: 1.2 2/27/84 */
2:
3: # include "mfile1.h"
4: # include <ctype.h>
5: /* temporarily */
6:
7: /* character-set translation */
8: # ifndef CCTRANS
9: # define CCTRANS(x) (x)
10: # endif
11:
12: int flflag = 0, Oflag;
13: # ifndef FLOATCVT
14: double atof();
15: # define FLOATCVT(x) atof(x)
16: # endif
17:
18: # ifndef ASMBUF
19: # define ASMBUF 200
20: # endif
21: char asmbuf[ASMBUF];
22: char *asmp;
23: int asm_esc = 0; /* asm escaped used in file */
24: /* lexical actions */
25:
26: # define A_ERR 0 /* illegal character */
27: # define A_LET 1 /* saw a letter */
28: # define A_DIG 2 /* saw a digit */
29: # define A_1C 3 /* return a single character */
30: # define A_STR 4 /* string */
31: # define A_CC 5 /* character constant */
32: # define A_BCD 6 /* GCOS BCD constant */
33: # define A_SL 7 /* saw a / */
34: # define A_DOT 8 /* saw a . */
35: # define A_PL 9 /* + */
36: # define A_MI 10 /* - */
37: # define A_EQ 11 /* = */
38: # define A_NOT 12 /* ! */
39: # define A_LT 13 /* < */
40: # define A_GT 14 /* > */
41: # define A_AND 16 /* & */
42: # define A_OR 17 /* | */
43: # define A_WS 18 /* whitespace (not \n) */
44: # define A_NL 19 /* \n */
45:
46: /* character classes */
47:
48: # define LEXLET 01
49: # define LEXDIG 02
50: # define LEXOCT 04
51: # define LEXHEX 010
52: # define LEXWS 020
53: # define LEXDOT 040
54:
55: /* reserved word actions */
56:
57: # define AR_TY 0 /* type word */
58: # define AR_RW 1 /* simple reserved word */
59: # define AR_CL 2 /* storage class word */
60: # define AR_S 3 /* struct */
61: # define AR_U 4 /* union */
62: # define AR_E 5 /* enum */
63: # define AR_A 6 /* asm */
64:
65: /* text buffer */
66: # define LXTSZ BUFSIZ /* lots of room for FLEXNAMES */
67: char yytext[LXTSZ];
68: char * lxgcp;
69: /* If TRUNCATE is undefined, let -T determine whether symbols are truncated.
70: ** Otherwise, forcibly truncate all names.
71: */
72:
73: static int truncate_flag =
74: #ifndef TRUNCATE
75: 0; /* truncate based on -T (non-zero to truncate */
76: #else
77: 1; /* force all names <= NCHNAM chars */
78: #endif
79:
80: int zflag = 0;
81:
82:
83: /* ARGSUSED */
84: mainp1( argc, argv )
85: int argc;
86: char *argv[];
87: {
88: /* control multiple files */
89:
90: register i;
91: register char *cp;
92: extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, opdebug;
93: extern int asdebug, nowarn, proflag, bothdebug, syncstdio, Pflag;
94: extern int onlywarn;
95: extern unsigned int maxoffset;
96: int fdef = 0;
97:
98: unsigned int temp = 1;
99: i = 0;
100: do {
101: temp <<= 1;
102: ++i;
103: } while ( temp != 0 );
104: maxoffset = 1 << (i-1);
105:
106: for( i=1; i<argc; ++i ) {
107: if( *(cp=argv[i]) == '-' && *++cp == 'X' ) {
108: while( *++cp ) switch(++syncstdio, *cp) {
109: case 'P': ++Pflag; break;
110: case 'W': onlywarn=1; break; /* some fatal is not */
111: case 'B':
112: ++bothdebug; break;
113: case 'O':
114: Oflag++; break;
115: case 'd':
116: ++ddebug; break;
117: case 'i':
118: ++idebug; break;
119: case 'b':
120: ++bdebug; break;
121: case 't':
122: ++tdebug; break;
123: case 'e':
124: ++edebug; break;
125: case 'x':
126: ++xdebug; break;
127: case 'o':
128: ++opdebug; break;
129: case 'p':
130: ++proflag; break;
131: case 's':
132: ++asdebug; --syncstdio; break;
133: case 'w':
134: ++nowarn; --syncstdio; break;
135: case 'z': /* stin file debug info */
136: ++zflag; break;
137: case 'T': /* truncate names */
138: ++truncate_flag; break;
139: default:
140: cerror( "bad option: X%c", *cp );
141: }
142: } else {
143: if( *(argv[i]) != '-' ) switch( fdef++ ) {
144: case 0:
145: close(0);
146: if (open(argv[i], 0) == 0) break;
147: fprintf(stderr, "ccom: can't open %s\n", argv[i]);
148: exit(1);
149:
150: case 1:
151: if (freopen(argv[i], "w", stdout)) break;
152: fprintf(stderr, "ccom: can't open %s\n", argv[i]);
153: exit(1);
154:
155: default:
156: ;
157: }
158: }
159: }
160: if (isatty(1)) ++syncstdio;
161:
162: p2init( argc, argv );
163:
164: for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
165:
166: lxinit();
167: tinit();
168: mkdope();
169:
170: /* dimension table initialization */
171: allodimtab();
172: dimtab[NULL] = 0;
173: dimtab[VOID] = 0;
174: dimtab[CHAR] = SZCHAR;
175: dimtab[INT] = SZINT;
176: dimtab[FLOAT] = SZFLOAT;
177: dimtab[DOUBLE] = SZDOUBLE;
178: dimtab[LONG] = SZLONG;
179: dimtab[SHORT] = SZSHORT;
180: dimtab[UCHAR] = SZCHAR;
181: dimtab[USHORT] = SZSHORT;
182: dimtab[UNSIGNED] = SZINT;
183: dimtab[ULONG] = SZLONG;
184: /* starts past any of the above */
185: curdim = 16;
186: reached = 1;
187:
188: yyparse();
189: yyaccpt();
190:
191: # ifdef GDEBUG
192: ejsdb();
193: # endif
194: # ifdef ENDJOB
195: ENDJOB(nerrors?1:0);
196: # endif
197: return(nerrors?1:0);
198:
199: }
200:
201: # ifdef ibm
202:
203: # define CSMASK 0377
204: # define CSSZ 256
205:
206: # else
207:
208: # define CSMASK 0177
209: # define CSSZ 128
210:
211: # endif
212:
213: /*
214: * We buffer the input on a line by line basis
215: * so that we can output the ``C'' source as comments
216: * in the assembly language
217: */
218: int asdebug = 0;
219: static char linebuf[BUFSIZ+1];
220: static char *linecp = &linebuf[0], *endcp = &linebuf[0];
221: #undef ungetc
222: #undef getchar
223:
224: #define getchar() (*linecp ? *linecp++ : eatline() )
225: #define ungetchar() --linecp
226: #define ungetc(c) *--linecp=(c)
227:
228: eatline()
229: {
230: static int savechar; char *index(), *memcpy();
231: register n; register char *cp;
232: if (asdebug) for (*linecp = savechar, n = 0;;) {
233: if ((cp = index(linecp, '\n')) || (cp = endcp-1, n)) {
234: savechar = *++cp;
235: *cp = '\0';
236: spitline(linecp);
237: return *linecp++;
238: }
239: linecp = memcpy(linebuf, linecp, n = endcp - linecp);
240: if ((n = read(0, endcp = linebuf + n, BUFSIZ - n)) <= 0) {
241: *(endcp = linebuf) = '\0';
242: return EOF;
243: }
244: *(endcp += n) = '\0';
245: } else {
246: if ((n = read(0, linebuf, BUFSIZ)) <= 0) {
247: (linecp = linebuf)[0] = 0;
248: return EOF;
249: } else {
250: (linecp = linebuf)[n] = 0;
251: return *linecp++;
252: }
253: }
254: }
255:
256: /*
257: ** add the original C line to the assembler output as comment,
258: ** unless it is empty.
259: */
260: #define MARKERCNT 20 /* how often to spit out line markers */
261: spitline(l)
262: register char *l;
263: {
264: extern int lineno;
265:
266: if( !(lineno%MARKERCNT) )
267: printx( "%s -- line %d %s\n", COMMENTSTR, lineno, ftitle );
268: /* line marker */
269: while( isspace( *l ) )
270: l++;
271: if( *l )
272: printx( "%s %s", COMMENTSTR, l );
273: }
274:
275: short lxmask[CSSZ+1];
276:
277: lxenter( s, m )
278: register char *s;
279: register short m;
280: {
281: /* enter a mask into lxmask */
282: register c;
283:
284: while( c= *s++ ) lxmask[c+1] |= m;
285:
286: }
287:
288:
289: # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
290:
291: lxmore( c, m )
292: register c, m;
293: {
294: register char *cp;
295:
296: *(cp = lxgcp) = c;
297: while ((c = getchar()), lxmask[c+1]&m) {
298: if( cp < &yytext[LXTSZ-1])
299: *++cp = c;
300: }
301: ungetchar();
302: *(lxgcp = cp+1) = '\0';
303: }
304:
305: struct lxdope
306: {
307: short lxch; /* the character */
308: short lxact; /* the action to be performed */
309: short lxtok; /* the token number to be returned */
310: short lxval; /* the value to be returned */
311: } lxdope[] =
312: {
313: '$', A_ERR, 0, 0, /* illegal characters go here... */
314: '_', A_LET, 0, 0, /* letters point here */
315: '0', A_DIG, 0, 0, /* digits point here */
316: ' ', A_WS, 0, 0, /* whitespace goes here */
317: '\n', A_NL, 0, 0,
318: '"', A_STR, 0, 0, /* character string */
319: '\'', A_CC, 0, 0, /* character constant */
320: '`', A_BCD, 0, 0, /* GCOS BCD constant */
321: '(', A_1C, LP, 0,
322: ')', A_1C, RP, 0,
323: '{', A_1C, LC, 0,
324: '}', A_1C, RC, 0,
325: '[', A_1C, LB, 0,
326: ']', A_1C, RB, 0,
327: '*', A_1C, MUL, MUL,
328: '?', A_1C, QUEST, 0,
329: ':', A_1C, COLON, 0,
330: '+', A_PL, PLUS, PLUS,
331: '-', A_MI, MINUS, MINUS,
332: '/', A_SL, DIVOP, DIV,
333: '%', A_1C, DIVOP, MOD,
334: '&', A_AND, AND, AND,
335: '|', A_OR, OR, OR,
336: '^', A_1C, ER, ER,
337: '!', A_NOT, UNOP, NOT,
338: '~', A_1C, UNOP, COMPL,
339: ',', A_1C, CM, CM,
340: ';', A_1C, SM, 0,
341: '.', A_DOT, STROP, DOT,
342: '<', A_LT, RELOP, LT,
343: '>', A_GT, RELOP, GT,
344: '=', A_EQ, ASSIGN, ASSIGN,
345: -1, A_1C, 0, 0,
346: };
347:
348: struct lxdope *lxcp[CSSZ+1];
349:
350: lxinit()
351: {
352: register struct lxdope *p;
353: register i;
354: register char *cp;
355: /* set up character classes */
356:
357: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
358: lxenter( "0123456789", LEXDIG );
359: lxenter( "0123456789abcdefABCDEF", LEXHEX );
360: /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
361: lxenter( " \t\r\b\f\013", LEXWS );
362: lxenter( "01234567", LEXOCT );
363: lxmask['.'+1] |= LEXDOT;
364: lxhinit();
365:
366: /* make lxcp point to appropriate lxdope entry for each character */
367:
368: /* initialize error entries */
369:
370: for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
371:
372: /* make unique entries */
373:
374: for( p=lxdope; ; ++p )
375: {
376: lxcp[p->lxch+1] = p;
377: if( p->lxch < 0 ) break;
378: }
379:
380: /* handle letters, digits, and whitespace */
381: /* by convention, first, second, and third places */
382:
383: cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
384: while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
385: cp = "123456789";
386: while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
387: cp = "\t\b\r\f\013";
388: while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
389:
390: /* first line might have title */
391: lineno = 1;
392: lxtitle();
393:
394: }
395:
396: int lxmatch; /* character to be matched in char or string constant */
397:
398: lxstr(ct)
399: register ct;
400: {
401: /* match a string or character constant, up to lxmatch */
402:
403: register c, val, i = 0;
404:
405: while ((c = getchar()) != lxmatch) {
406: switch( c ) {
407:
408: case EOF:
409: uerror( "lxstr() unexpected EOF" );
410: break;
411:
412: case '\n':
413: uerror( "newline in string or char constant" );
414: ++lineno;
415: break;
416:
417: case '\\':
418: switch (c = getchar()) {
419: case '\n':
420: ++lineno; continue;
421: default:
422: val = c; goto mkcc;
423: case 'n':
424: val = '\n'; goto mkcc;
425: case 'r':
426: val = '\r'; goto mkcc;
427: case 'b':
428: val = '\b'; goto mkcc;
429: case 't':
430: val = '\t'; goto mkcc;
431: case 'f':
432: val = '\f'; goto mkcc;
433: case 'v':
434: val = '\013'; goto mkcc;
435: case '0': case '1': case '2': case '3':
436: case '4': case '5': case '6': case '7':
437: val = c-'0';
438: c = getchar(); /* try for 2 */
439: if (lxmask[c+1] & LEXOCT) {
440: val = (val<<3) | (c-'0');
441: c = getchar(); /* try for 3 */
442: if (lxmask[c+1] & LEXOCT)
443: val = (val<<3) | (c-'0');
444: else
445: ungetchar();
446: } else
447: ungetchar();
448: goto mkcc1;
449: }
450: default:
451: val =c;
452: mkcc:
453: val = CCTRANS(val);
454: mkcc1:
455: if (lxmatch == '\'') {
456: /* it is, after all, a "character" constant */
457: val = ccast((CONSZ)val,CHAR);
458: if (i == 0)
459: lastcon = val;
460: else {
461: # ifdef MAKECC
462: MAKECC( val, i );
463: # else
464: # ifdef RTOLBYTES
465: lastcon <<= SZCHAR;
466: lastcon |= (val&BITMASK(SZCHAR));
467: # else
468: lastcon &= BITMASK(SZCHAR*i);
469: lastcon |= val << (SZCHAR*i);
470: # endif
471: # endif
472: }
473: } else {
474: /* stash the byte into the string */
475: if (strflg) {
476: if (ct==0 || i<ct)
477: putbyte( val );
478: else
479: if( i == ct )
480: werror(
481: "non-null byte ignored in string initializer" );
482: } else
483: bycode( val, i );
484: }
485: ++i;
486: continue;
487: }
488: break;
489: }
490: /* end of string or char constant */
491:
492: if (lxmatch == '"') {
493: if (strflg) { /* end the string */
494: if (ct==0 || i<ct)
495: putbyte( 0 ); /* the null at the end */
496: } else { /* the initializer gets a null byte */
497: bycode( 0, i++ );
498: bycode( -1, i );
499: dimtab[curdim] = i; /* in case of later sizeof ... */
500: }
501: } else { /* end the character constant */
502: if (i == 0)
503: uerror( "empty character constant" );
504: if (i>(SZINT/SZCHAR) || ((pflag||hflag)&&i>1))
505: uerror( "too many characters in character constant" );
506: }
507: }
508:
509: lxcom()
510: {
511: register c;
512: /* saw a /*: process a comment */
513:
514: for (;;) {
515: switch (c = getchar()) {
516:
517: case EOF:
518: uerror( "lxcom() unexpected EOF" );
519: return;
520:
521: case '\n':
522: ++lineno;
523:
524: default:
525: continue;
526:
527: case '*':
528: if( (c = getchar()) == '/' ) return;
529: else ungetchar();
530: continue;
531:
532: }
533: }
534: }
535:
536: #define Return(e) return(yylval.lineno = lineno, (e))
537:
538: yylex()
539: {
540: for(;;)
541: {
542:
543: register lxchar;
544: register struct lxdope *p;
545: register struct symtab *sp;
546: register char *cp;
547: register id;
548:
549: switch( (p = lxcp[(lxchar = getchar())+1])->lxact )
550: {
551:
552: onechar:
553: ungetc( lxchar );
554:
555: case A_1C:
556: /* eat up a single character, and return an opcode */
557:
558: yylval.intval = p->lxval;
559: Return( p->lxtok );
560:
561: case A_ERR:
562: uerror( "illegal character: %03o (octal)", lxchar );
563: break;
564:
565: case A_LET:
566: /* collect an identifier, and check for reserved word */
567: lxget( lxchar, LEXLET|LEXDIG );
568:
569: /* 0 means some kind of low level error, >0 reserved,
570: ** <0 means id
571: */
572: if( (lxchar=lxres()) > 0 ) Return( lxchar );
573: if( lxchar== 0 ) continue;
574:
575: if (truncate_flag )
576: yytext[NCHNAM] = '\0'; /* truncate name */
577: id = lookup( hash(yytext),
578: /* tag name for struct/union/enum */
579: (stwart&TAGNAME)? STAG:
580: /* member name for struct/union */
581: (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
582: sp = &stab[id];
583: if( sp->sclass == TYPEDEF && !stwart )
584: {
585: stwart = instruct;
586: yylval.nodep = mkty( sp->stype, sp->dimoff,
587: sp->sizoff );
588: Return( TYPE );
589: }
590: stwart = (stwart&SEENAME) ? instruct : 0;
591: yylval.intval = id;
592: Return( NAME );
593:
594: case A_DIG:
595: /* collect a digit string, then look at last one... */
596: lastcon = 0;
597: lxget( lxchar, LEXDIG );
598: switch( lxchar = getchar() )
599: {
600:
601: case 'x':
602: case 'X':
603: if( yytext[0] != '0' && !yytext[1] )
604: uerror( "illegal hex constant" );
605: lxmore( lxchar, LEXHEX );
606: /* convert the value */
607: {
608: for( cp = yytext+2; *cp; ++cp )
609: {
610: /* this code won't work for all character sets,
611: ** but seems ok for ascii and ebcdic
612: */
613: lastcon <<= 4;
614: if( isdigit( *cp ) )
615: lastcon += *cp-'0';
616: else if( isupper( *cp ) )
617: lastcon += *cp - 'A'+ 10;
618: else
619: lastcon += *cp - 'a'+ 10;
620: }
621: }
622:
623: hexlong:
624: /* hex and octal constants are long if they
625: ** fit within 0177777
626: */
627: if( lastcon & ~0177777L ) yylval.intval = 1;
628: else yylval.intval = 0;
629:
630: goto islong;
631:
632: case '.':
633: lxmore( lxchar, LEXDIG );
634:
635: getfp:
636: if( (lxchar = getchar()) == 'e' || lxchar == 'E' )
637: {
638: /* exponent */
639: case 'e':
640: case 'E':
641: if( (lxchar = getchar()) == '+' ||
642: lxchar == '-' )
643: {
644: *lxgcp++ = 'e';
645: }
646: else
647: {
648: ungetc(lxchar);
649: lxchar = 'e';
650: }
651: lxmore( lxchar, LEXDIG );
652: /* now have the whole thing... */
653: }
654: else
655: {
656: /* no exponent */
657: ungetc( lxchar );
658: }
659: # ifdef NOFLOAT
660: if( !flflag )
661: {
662: flflag = 1;
663: werror( "sorry, no floating point" );
664: }
665: for( cp = yytext; *cp; ++cp )
666: {
667: if( *cp == 'e' || *cp == 'E' ||
668: *cp == '.' )
669: {
670: *cp = '\0';
671: break;
672: }
673: }
674: goto conv10;
675: # else
676: flflag = 1;
677: dcon = FLOATCVT(yytext);
678: Return( FCON );
679: # endif
680:
681: default:
682: ungetc( lxchar );
683: if( yytext[0] == '0' )
684: {
685: /* convert in octal */
686: for( cp = yytext+1; *cp; ++cp )
687: {
688: lastcon <<= 3;
689: lastcon += *cp - '0';
690: }
691: goto hexlong;
692: }
693: else
694: {
695: /* convert in decimal */
696: # ifdef NOFLOAT
697: conv10:
698: # endif
699: for( cp = yytext; *cp; ++cp )
700: {
701: lastcon = lastcon*10 + *cp - '0';
702: }
703: }
704:
705: /* decide if it is long or not (decimal case) */
706:
707: /* if it is positive and fits in 15 bits,
708: ** or negative and and fits in 15 bits
709: ** with an extended sign, it is int;
710: ** otherwise long
711: */
712: /* if there is an l or L following,
713: ** all bets are off...
714: */
715:
716: {
717: register CONSZ v;
718: v = lastcon & ~077777L;
719: if( v == 0 || v == ~077777L )
720: yylval.intval = 0;
721: else yylval.intval = 1;
722: }
723:
724: islong:
725: /* finally, look for trailing L or l */
726: if( (lxchar=getchar()) == 'L' || lxchar == 'l' )
727: yylval.intval = 1;
728: else ungetc( lxchar );
729: Return( ICON );
730: }
731:
732: case A_DOT:
733: /* a dot: if followed by a digit, floating point */
734: lxchar = getchar();
735: if( lxmask[lxchar+1] & LEXDIG )
736: {
737: ungetc(lxchar);
738: lxget( '.', LEXDIG );
739: goto getfp;
740: }
741: stwart = FUNNYNAME;
742: goto onechar;
743:
744: case A_STR:
745: /* string constant */
746: lxmatch = '"';
747: Return( STRING );
748:
749: case A_CC:
750: /* character constant */
751: lxmatch = '\'';
752: lastcon = 0;
753: lxstr(0);
754: yylval.intval = 0;
755: Return( ICON );
756:
757: case A_SL:
758: /* / */
759: if( (lxchar = getchar()) != '*' ) goto onechar;
760: lxcom();
761: case A_WS:
762: continue;
763:
764: case A_NL:
765: ++lineno;
766: lxtitle();
767: continue;
768:
769: case A_NOT:
770: /* ! */
771: if( (lxchar = getchar()) != '=' ) goto onechar;
772: yylval.intval = NE;
773: Return( EQUOP );
774:
775: case A_MI:
776: /* - */
777: if( (lxchar = getchar()) == '-' )
778: {
779: yylval.intval = DECR;
780: Return( INCOP );
781: }
782: if( lxchar != '>' ) goto onechar;
783: stwart = FUNNYNAME;
784: yylval.intval=STREF;
785: Return( STROP );
786:
787: case A_PL:
788: /* + */
789: if( (lxchar = getchar()) != '+' ) goto onechar;
790: yylval.intval = INCR;
791: Return( INCOP );
792:
793: case A_AND:
794: /* & */
795: if( (lxchar = getchar()) != '&' ) goto onechar;
796: Return( yylval.intval = ANDAND );
797:
798: case A_OR:
799: /* | */
800: if( (lxchar = getchar()) != '|' ) goto onechar;
801: Return( yylval.intval = OROR );
802:
803: case A_LT:
804: /* < */
805: if( (lxchar = getchar()) == '<' )
806: {
807: yylval.intval = LS;
808: Return( SHIFTOP );
809: }
810: if( lxchar != '=' ) goto onechar;
811: yylval.intval = LE;
812: Return( RELOP );
813:
814: case A_GT:
815: /* > */
816: if( (lxchar = getchar()) == '>' )
817: {
818: yylval.intval = RS;
819: Return(SHIFTOP );
820: }
821: if( lxchar != '=' ) goto onechar;
822: yylval.intval = GE;
823: Return( RELOP );
824:
825: case A_EQ:
826: /* = */
827: switch( lxchar = getchar() )
828: {
829:
830: case '=':
831: yylval.intval = EQ;
832: Return( EQUOP );
833:
834: default:
835: goto onechar;
836:
837: }
838:
839:
840: default:
841: cerror( "yylex error, character %03o (octal)", lxchar );
842:
843: }
844:
845: /* ordinarily, repeat here... */
846: cerror( "out of switch in yylex" );
847:
848: }
849:
850: }
851:
852: struct lxrdope
853: {
854: /* dope for reserved, in alphabetical order */
855:
856: char *lxrch; /* name of reserved word */
857: short lxhash;
858: short lxract; /* reserved word action */
859: short lxrval; /* value to be returned */
860: } lxrdope[] =
861: {
862: "asm", 0, AR_A, 0,
863: "auto", 0, AR_CL, AUTO,
864: "break", 0, AR_RW, BREAK,
865: "case", 0, AR_RW, CASE,
866: "char", 0, AR_TY, CHAR,
867: "continue", 0, AR_RW, CONTINUE,
868: "default", 0, AR_RW, DEFAULT,
869: "do", 0, AR_RW, DO,
870: "double", 0, AR_TY, DOUBLE,
871: "else", 0, AR_RW, ELSE,
872: "enum", 0, AR_E, ENUM,
873: "extern", 0, AR_CL, EXTERN,
874: #ifdef ONEFLOAT
875: "float", 0, AR_TY, DOUBLE,
876: #else
877: "float", 0, AR_TY, FLOAT,
878: #endif
879: "for", 0, AR_RW, FOR,
880: "fortran", 0, AR_CL, FORTRAN,
881: "goto", 0, AR_RW, GOTO,
882: "if", 0, AR_RW, IF,
883: "int", 0, AR_TY, INT,
884: "long", 0, AR_TY, LONG,
885: "register", 0, AR_CL, REGISTER,
886: "return", 0, AR_RW, RETURN,
887: "short", 0, AR_TY, SHORT,
888: "sizeof", 0, AR_RW, SIZEOF,
889: "static", 0, AR_CL, STATIC,
890: "struct", 0, AR_S, 0,
891: "switch", 0, AR_RW, SWITCH,
892: "typedef", 0, AR_CL, TYPEDEF,
893: "union", 0, AR_U, 0,
894: "unsigned", 0, AR_TY, UNSIGNED,
895: "void", 0, AR_TY, VOID,
896: "while", 0, AR_RW, WHILE,
897: 0, 0, 0, 0,
898: };
899:
900: #define HASH(s) (((lxrch0[(s)[0]&037]<<4) | lxrch2[(s)[2]&037]) & 0377)
901:
902: unsigned char lxrch0[040], lxrch2[040], lxrindx[0400];
903:
904: lxhinit()
905: {
906: register struct lxrdope *lp; struct lxrdope dptemp;
907: register char *s; register j;
908: int k0, k2;
909: for (lp = lxrdope; s = lp->lxrch; ++lp) {
910: ++lxrch0[s[0] & 037];
911: ++lxrch2[s[2] & 037];
912: }
913: for (k0=k2=j=0; j<040; j++) {
914: if (lxrch0[j]) lxrch0[j] = ++k0;
915: if (lxrch2[j]) lxrch2[j] = ++k2;
916: }
917: for (lp = lxrdope; s = lp->lxrch; ++lp)
918: lp->lxhash = HASH(s);
919: do {
920: j = 0;
921: for (lp = lxrdope+1; lp->lxrch; ++lp)
922: if (lp->lxhash < (lp-1)->lxhash) {
923: dptemp = *lp;
924: *lp = *(lp-1);
925: *(lp-1) = dptemp;
926: ++j;
927: }
928: } while (j);
929: for (k0 = 1, lp = lxrdope; s = lp->lxrch; ++lp, ++k0)
930: if (lxrindx[j = lp->lxhash] == 0)
931: lxrindx[j] = k0;
932: /*
933: for (lp = lxrdope; lp->lxrch; ++lp)
934: printf("%d %d %s\n", lxrindx[lp->lxhash], lp->lxhash, lp->lxrch);
935: */
936: }
937:
938: lxres()
939: {
940: /*
941: ** check to see of yytext is reserved; if so,
942: ** do the appropriate action and return
943: ** otherwise, return -1
944: */
945: register c;
946: register struct lxrdope *p;
947:
948: if (yytext[1] == 0) return -1;
949:
950: if ((c = HASH(yytext)) == 0 || (c = lxrindx[c]) == 0) return -1;
951:
952: p = lxrdope + c - 1;
953: do if (strcmp(yytext, p->lxrch) == 0) switch (p->lxract) {
954:
955: case AR_TY: /* type word */
956: stwart = instruct;
957: yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
958: if (p->lxrval==FLOAT || p->lxrval==DOUBLE) {
959: # ifdef NOFLOAT
960: if (!flflag)
961: werror( "sorry, no floating point" );
962: yylval.nodep->tn.type = LONG;
963: # endif
964: flflag = 1;
965: }
966: return( TYPE );
967:
968: case AR_RW: /* ordinary reserved word */
969: return( yylval.intval = p->lxrval );
970:
971: case AR_CL: /* class word */
972: yylval.intval = p->lxrval;
973: return( CLASS );
974:
975: case AR_S: /* struct */
976: stwart = INSTRUCT|SEENAME|TAGNAME;
977: yylval.intval = INSTRUCT;
978: return( STRUCT );
979:
980: case AR_U: /* union */
981: stwart = INUNION|SEENAME|TAGNAME;
982: yylval.intval = INUNION;
983: return( STRUCT );
984:
985: case AR_E: /* enums */
986: stwart = SEENAME|TAGNAME;
987: return( yylval.intval = ENUM );
988:
989: case AR_A: /* asm */
990: asm_esc = 1; /* warn the world! */
991: lxget(' ', LEXWS);
992: if (getchar() != '(') goto badasm;
993: lxget(' ', LEXWS);
994: if (getchar() != '"') goto badasm;
995: asmp = asmbuf;
996: while ((c = getchar()) != '"') {
997: if (c=='\n' || c==EOF) goto badasm;
998: *asmp++ = c;
999: if (asmp >= &asmbuf[ASMBUF-1])
1000: uerror( "asm > %d chars", ASMBUF);
1001: }
1002: lxget(' ', LEXWS);
1003: if( getchar() != ')' ) goto badasm;
1004: *asmp++ = '\0';
1005: return( ASM );
1006: badasm:
1007: uerror( "bad asm construction" );
1008: return( 0 );
1009:
1010: default:
1011: cerror("bad AR_?? action");
1012: } while ((++p)->lxhash == c);
1013: return -1;
1014: }
1015:
1016: lxtitle()
1017: {
1018: /* called after a newline; set linenumber and file name */
1019:
1020: register c, val; register char *cp;
1021:
1022: /*for(;;)*/ { /* might be several such lines in a row */
1023: /* but we really want the very first one */
1024: if ((c = getchar()) != '#') {
1025: if (c != EOF) ungetchar();
1026: return;
1027: }
1028: lxget( ' ', LEXWS);
1029: val = 0;
1030: for (c = getchar(); isdigit(c); c = getchar())
1031: val = val*10+ c - '0';
1032: ungetchar();
1033: lineno = val-1;
1034: lxget(' ', LEXWS);
1035: if ((c = getchar()) != '\n') {
1036: cp = ftitle; *cp++ = c;
1037: while ((c=getchar()) != '\n')
1038: *cp++ = c;
1039: *cp = '\0';
1040: if (c != EOF) ungetchar();
1041: }
1042: }
1043: }
1044:
1045: # ifndef MYASMOUT
1046: asmout()
1047: {
1048: #ifdef GDEBUG
1049: dbline();
1050: #endif
1051: printx("%s\n%s\n%s\n", ASM_COMMENT, asmbuf, ASM_END);
1052: }
1053: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.