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