|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)scan.c 1.1 86/02/03 SMI"; /* from UCB X.X XX/XX/XX */
3: #endif
4:
5:
6: # include <ctype.h>
7: # include "cpass1.h"
8: # include <a.out.h>
9: # include <stab.h>
10: #ifdef STACKPROBE
11: int noprobe;
12: #endif
13:
14: int asm_esc = 0; /* asm escaped used in file */
15:
16: /*
17: * When we have a syntax error, we'd like to faithfully report
18: * the token near which the error occured. This can only be done
19: * if we squarrel away the token as we read it.
20: */
21: char tokebufr[200];
22: int tokebufptr = -1;
23: #define xreset() tokebufptr = -1;
24: #define xgetchar() ((++tokebufptr < sizeof tokebufr)?(tokebufr[tokebufptr] = getchar()): getchar())
25: #define xungetc(c,filedes) (((filedes==stdin)?tokebufptr--:0),ungetc(c,filedes))
26:
27: /*
28: * When we encounter a quoted string, we stash the characters therein in
29: * a buffer, which is then examined during processing of a semantic action.
30: * We have no idea whatsoever of the maximum size of strings, so must
31: * dynamically allocate the string space. The largest amount of space we'll
32: * need is no larger that the largest single string in the program.
33: */
34: char *stringval= NULL;
35: int stringmax= 0;
36: int stringsize;
37: char *newstring();
38: #define STRINGINIT 512
39: #define stashstring(c) {if(i<stringmax)*++nextstringchar=(c); else nextstringchar = newstring(c);}
40: #define mask(nbits) ((1 << (nbits)) - 1)
41:
42: /* lexical actions */
43:
44: # define A_ERR 0 /* illegal character */
45: # define A_LET 1 /* saw a letter */
46: # define A_DIG 2 /* saw a digit */
47: # define A_1C 3 /* return a single character */
48: # define A_STR 4 /* string */
49: # define A_CC 5 /* character constant */
50: # define A_BCD 6 /* GCOS BCD constant */
51: # define A_SL 7 /* saw a / */
52: # define A_DOT 8 /* saw a . */
53: # define A_PL 9 /* + */
54: # define A_MI 10 /* - */
55: # define A_EQ 11 /* = */
56: # define A_NOT 12 /* ! */
57: # define A_LT 13 /* < */
58: # define A_GT 14 /* > */
59: # define A_AND 16 /* & */
60: # define A_OR 17 /* | */
61: # define A_WS 18 /* whitespace (not \n) */
62: # define A_NL 19 /* \n */
63:
64: /* character classes */
65:
66: # define LEXLET 01
67: # define LEXDIG 02
68: # define LEXOCT 04
69: # define LEXHEX 010
70: # define LEXWS 020
71: # define LEXDOT 040
72:
73: /* reserved word actions */
74:
75: # define AR_TY 0 /* type word */
76: # define AR_RW 1 /* simple reserved word */
77: # define AR_CL 2 /* storage class word */
78: # define AR_S 3 /* struct */
79: # define AR_U 4 /* union */
80: # define AR_E 5 /* enum */
81: # define AR_A 6 /* asm */
82:
83: /* text buffer */
84: #ifndef FLEXNAMES
85: # define LXTSZ 100
86: #else
87: #define LXTSZ BUFSIZ
88: #endif
89: char yytext[LXTSZ];
90: char * lxgcp;
91:
92: extern int proflg;
93: extern int gdebug;
94: extern int optimize;
95: #ifndef LINT
96: extern int oldway;
97: extern int lastloc;
98: #endif
99:
100: unsigned caloff();
101: /* ARGSUSED */
102: mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */
103:
104: register i;
105: register char *cp;
106: extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, gdebug;
107: extern unsigned int offsz;
108: int fdef = 0;
109: char *release = "PCC/XXX SUN 4.1c bsd";
110:
111: offsz = caloff();
112: for( i=1; i<argc; ++i ){
113: if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
114: while( *++cp ){
115: switch( *cp ){
116:
117: case 'b':
118: ++bdebug;
119: break;
120: case 'd':
121: ++ddebug;
122: break;
123: case 'e':
124: ++edebug;
125: break;
126: #ifndef LINT
127: case 'G':
128: oldway = 1;
129: /* fall through */
130:
131: case 'g':
132: ++gdebug;
133: break;
134: #ifdef STACKPROBE
135: case 'K':
136: ++noprobe;
137: break;
138: #endif STACKPROBE
139: case 'P': /* profiling */
140: ++proflg;
141: break;
142: #endif !LINT
143: case 'i':
144: ++idebug;
145: break;
146: case 'r':
147: fprintf( stderr, "Release: %s\n",
148: release );
149: break;
150: case 't':
151: ++tdebug;
152: break;
153: case 'x':
154: ++xdebug;
155: break;
156: case 'O':
157: ++optimize;
158: break;
159: }
160: }
161: }
162: else {
163: if( *(argv[i]) != '-' ) switch( fdef++ ) {
164: case 0:
165: case 1:
166: if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
167: fprintf(stderr, "ccom:can't open %s\n", argv[i]);
168: exit(1);
169: }
170: break;
171:
172: default:
173: ;
174: }
175: }
176: }
177:
178: # ifdef ONEPASS
179: p2init( argc, argv );
180: # endif
181:
182: for( i=0; i<SYMTSZ; ++i ) stab[i] = NULL;
183:
184: lxinit();
185: tinit();
186: mkdope();
187:
188: lineno = 1;
189:
190: /* dimension table initialization */
191:
192: dimtab = (int*)malloc(DIMTABSZ*sizeof(dimtab[0]));
193: dimtab[NULL] = 0;
194: dimtab[CHAR] = SZCHAR;
195: dimtab[INT] = SZINT;
196: dimtab[FLOAT] = SZFLOAT;
197: dimtab[DOUBLE] = SZDOUBLE;
198: dimtab[LONG] = SZLONG;
199: dimtab[SHORT] = SZSHORT;
200: dimtab[UCHAR] = SZCHAR;
201: dimtab[USHORT] = SZSHORT;
202: dimtab[UNSIGNED] = SZINT;
203: dimtab[ULONG] = SZLONG;
204: dimtab[TERROR] = SZINT;
205: /* curdim starts past any of the above built-in types */
206: curdim = TERROR+1;
207: reached = 1;
208:
209: yyparse();
210: yyaccpt();
211:
212: ejobcode( nerrors ? 1 : 0 );
213: return(nerrors?1:0);
214:
215: }
216:
217: # ifdef ibm
218:
219: # define CSMASK 0377
220: # define CSSZ 256
221:
222: # else
223:
224: # define CSMASK 0177
225: # define CSSZ 128
226:
227: # endif
228:
229: short lxmask[CSSZ+1];
230:
231: lxenter( s, m ) register char *s; register short m; {
232: /* enter a mask into lxmask */
233: register c;
234:
235: while( c= *s++ ) lxmask[c+1] |= m;
236:
237: }
238:
239:
240: # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
241:
242: lxmore( c, m ) register c, m; {
243: register char *cp;
244:
245: *(cp = lxgcp) = c;
246: while( c=xgetchar(), lxmask[c+1]&m ){
247: if( cp < &yytext[LXTSZ-1] ){
248: *++cp = c;
249: }
250: }
251: xungetc(c,stdin);
252: *(lxgcp = cp+1) = '\0';
253: }
254:
255: struct lxdope {
256: short lxch; /* the character */
257: short lxact; /* the action to be performed */
258: short lxtok; /* the token number to be returned */
259: short lxval; /* the value to be returned */
260: } lxdope[] = {
261:
262: '@', A_ERR, 0, 0, /* illegal characters go here... */
263: '_', A_LET, 0, 0, /* letters point here */
264: '0', A_DIG, 0, 0, /* digits point here */
265: ' ', A_WS, 0, 0, /* whitespace goes here */
266: '\n', A_NL, 0, 0,
267: '"', A_STR, 0, 0, /* character string */
268: '\'', A_CC, 0, 0, /* character constant */
269: '`', A_BCD, 0, 0, /* GCOS BCD constant */
270: '(', A_1C, LP, 0,
271: ')', A_1C, RP, 0,
272: '{', A_1C, LC, 0,
273: '}', A_1C, RC, 0,
274: '[', A_1C, LB, 0,
275: ']', A_1C, RB, 0,
276: '*', A_1C, MUL, MUL,
277: '?', A_1C, QUEST, 0,
278: ':', A_1C, COLON, 0,
279: '+', A_PL, PLUS, PLUS,
280: '-', A_MI, MINUS, MINUS,
281: '/', A_SL, DIVOP, DIV,
282: '%', A_1C, DIVOP, MOD,
283: '&', A_AND, AND, AND,
284: '|', A_OR, OR, OR,
285: '^', A_1C, ER, ER,
286: '!', A_NOT, UNOP, NOT,
287: '~', A_1C, UNOP, COMPL,
288: ',', A_1C, CM, CM,
289: ';', A_1C, SM, 0,
290: '.', A_DOT, STROP, DOT,
291: '<', A_LT, RELOP, LT,
292: '>', A_GT, RELOP, GT,
293: '=', A_EQ, ASSIGN, ASSIGN,
294: -1, A_1C, 0, 0,
295: };
296:
297: struct lxdope *lxcp[CSSZ+1];
298:
299: lxinit(){
300: register struct lxdope *p;
301: register i;
302: register char *cp;
303: /* set up character classes */
304:
305: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
306: lxenter( "0123456789", LEXDIG );
307: lxenter( "0123456789abcdefABCDEF", LEXHEX );
308: /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
309: lxenter( " \t\r\b\f\013", LEXWS );
310: lxenter( "01234567", LEXOCT );
311: lxmask['.'+1] |= LEXDOT;
312:
313: /* make lxcp point to appropriate lxdope entry for each character */
314:
315: /* initialize error entries */
316:
317: for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
318:
319: /* make unique entries */
320:
321: for( p=lxdope; ; ++p ) {
322: lxcp[p->lxch+1] = p;
323: if( p->lxch < 0 ) break;
324: }
325:
326: /* handle letters, digits, and whitespace */
327: /* by convention, first, second, and third places */
328:
329: cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
330: while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
331: cp = "123456789";
332: while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
333: cp = "\t\b\r\f\013";
334: while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
335:
336: /* first line might have title */
337: lxtitle();
338:
339: }
340:
341: int lxmatch; /* character to be matched in char or string constant */
342:
343: lxstr(lxmatch)
344: register lxmatch;
345: {
346: /* match a string or character constant, up to lxmatch */
347:
348: register c;
349: register val;
350: register i;
351: register char *nextstringchar = stringval-1;
352:
353: i=0;
354: while( (c=xgetchar()) != lxmatch ){
355: switch( c ) {
356:
357: case EOF:
358: uerror( "unexpected EOF" );
359: break;
360:
361: case '\n':
362: uerror( "newline in string or char constant" );
363: ++lineno;
364: break;
365:
366: case '\\':
367: switch( c = xgetchar() ){
368:
369: case '\n':
370: ++lineno;
371: continue;
372:
373: default:
374: val = c;
375: goto mkcc;
376:
377: case 'n':
378: val = '\n';
379: goto mkcc;
380:
381: case 'r':
382: val = '\r';
383: goto mkcc;
384:
385: case 'b':
386: val = '\b';
387: goto mkcc;
388:
389: case 't':
390: val = '\t';
391: goto mkcc;
392:
393: case 'f':
394: val = '\f';
395: goto mkcc;
396:
397: case 'v':
398: val = '\013';
399: goto mkcc;
400:
401: case '0':
402: case '1':
403: case '2':
404: case '3':
405: case '4':
406: case '5':
407: case '6':
408: case '7':
409: val = c-'0';
410: c=xgetchar(); /* try for 2 */
411: if( lxmask[c+1] & LEXOCT ){
412: val = (val<<3) | (c-'0');
413: c = xgetchar(); /* try for 3 */
414: if( lxmask[c+1] & LEXOCT ){
415: val = (val<<3) | (c-'0');
416: }
417: else xungetc( c ,stdin);
418: }
419: else xungetc( c ,stdin);
420:
421: goto mkcc1;
422:
423: }
424: default:
425: val =c;
426: mkcc:
427: val = CCTRANS(val);
428: mkcc1:
429: if( lxmatch == '\'' ){
430: val = CHARCAST(val); /* it is, after all, a "character" constant */
431: makecc( val, i );
432: } else {
433: /* stash the byte into the string */
434: stashstring( val );
435: }
436: ++i;
437: continue;
438: }
439: break;
440: }
441: /* end of string or char constant */
442:
443: if( lxmatch == '"' ){
444: stringsize = i;
445: } else { /* end the character constant */
446: if( i == 0 ) uerror( "empty character constant" );
447: if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
448: uerror( "too many characters in character constant" );
449: }
450: }
451:
452: char
453: *newstring( c )
454: char c;
455: {
456: /*
457: * our string buffer has run out of room. Attempt to realloc it.
458: */
459: int oldstringmax = stringmax;
460: if (stringmax == 0 ){
461: /* initial allocation */
462: stringval = (char *)malloc( STRINGINIT );
463: stringmax = STRINGINIT;
464: } else {
465: stringmax *= 2;
466: stringval = (char *)realloc(stringval, stringmax);
467: }
468: if (stringval == NULL ){
469: cerror("Out of string space\n");
470: }
471: stringval[oldstringmax] = c;
472: return &stringval[oldstringmax];
473: }
474:
475: lxgetstr( ct )
476: register ct;
477: {
478: /*
479: * retrieve value of string constant stashed by lxstr()
480: */
481: register char *c = stringval;
482: register int i;
483: register int s;
484: if( strflg ) {
485: if( ct==0 || stringsize<=ct )
486: s = stringsize;
487: else {
488: werror( "non-null byte ignored in string initializer" );
489: s = ct-1;
490: }
491: for (i=0; i<s; i++)
492: putbyte( *c++ & 0377 );
493: if( ct==0 || s<ct ) putbyte( 0 ); /* the null at the end */
494: } else {
495: for (i=0, s=stringsize; i<s; i++)
496: bycode( *c++ & 0377, i );
497: /* the initializer gets a null byte */
498: bycode( 0, i++ );
499: bycode( -1, i );
500: dimtab[curdim] = i; /* in case of later sizeof ... */
501: }
502: }
503:
504: asmout()
505: {
506: /*
507: * dump the saved asm string directly into the assembly language stream
508: */
509: #ifndef LINT
510: printf("|#ASMOUT#\n%.*s\n|#ENDASM#\n", stringsize, stringval);
511: #endif
512: }
513:
514: lxcom(){
515: register c;
516: /* saw a /*: process a comment */
517:
518: for(;;){
519:
520: switch( c = xgetchar() ){
521:
522: case EOF:
523: uerror( "unexpected EOF" );
524: return;
525:
526: case '\n':
527: ++lineno;
528:
529: default:
530: continue;
531:
532: case '*':
533: if( (c = xgetchar()) == '/' ) return;
534: else xungetc( c ,stdin);
535: continue;
536:
537: # ifdef LINT
538: case 'V':
539: lxget( c, LEXLET|LEXDIG );
540: {
541: extern int vaflag;
542: int i;
543: i = yytext[7]?yytext[7]-'0':0;
544: yytext[7] = '\0';
545: if( strcmp( yytext, "VARARGS" ) ) continue;
546: vaflag = i;
547: continue;
548: }
549: case 'L':
550: lxget( c, LEXLET );
551: if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
552: {
553: extern int libflag;
554: libflag = 1;
555: }
556: continue;
557:
558: case 'A':
559: lxget( c, LEXLET );
560: if( strcmp( yytext, "ARGSUSED" ) ) continue;
561: {
562: extern int argflag, vflag;
563: argflag = 1;
564: vflag = 0;
565: }
566: continue;
567:
568: case 'N':
569: lxget( c, LEXLET );
570: if( strcmp( yytext, "NOTREACHED" ) ) continue;
571: reached = 0;
572: continue;
573: # endif
574: }
575: }
576: }
577:
578: yylex(){
579: for(;;){
580:
581: register lxchar;
582: register struct lxdope *p;
583: register struct symtab *sp;
584: int id;
585:
586: xreset();
587: switch( (p=lxcp[(lxchar=xgetchar())+1])->lxact ){
588:
589: onechar:
590: xungetc( lxchar ,stdin);
591:
592: case A_1C:
593: /* eat up a single character, and return an opcode */
594:
595: yylval.intval = p->lxval;
596: return( p->lxtok );
597:
598: case A_ERR:
599: uerror( "illegal character: %03o (octal)", lxchar );
600: break;
601:
602: case A_LET:
603: /* collect an identifier, check for reserved word, and return */
604: lxget( lxchar, LEXLET|LEXDIG );
605: if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
606: if( lxchar== 0 ) continue;
607: #ifdef FLEXNAMES
608: id = lookup( hash(yytext),
609: #else
610: id = lookup( yytext,
611: #endif
612: /* tag name for struct/union/enum */
613: (stwart&TAGNAME)? STAG:
614: /* member name for struct/union */
615: (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
616: sp = STP(id);
617: if( sp->sclass == TYPEDEF && !stwart ){
618: stwart = instruct;
619: yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
620: return( TYPE );
621: }
622: stwart = (stwart&SEENAME) ? instruct : 0;
623: yylval.intval = id;
624: return( NAME );
625:
626: case A_DIG:
627: /* collect a digit string, then look at last one... */
628: lastcon = 0;
629: lxget( lxchar, LEXDIG );
630: switch( lxchar=xgetchar() ){
631:
632: case 'x':
633: case 'X':
634: if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
635: lxmore( lxchar, LEXHEX );
636: /* convert the value */
637: {
638: register char *cp;
639: for( cp = yytext+2; *cp; ++cp ){
640: /* this code won't work for all wild character sets,
641: but seems ok for ascii and ebcdic */
642: lastcon <<= 4;
643: if( isdigit( *cp ) ) lastcon += *cp-'0';
644: else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
645: else lastcon += *cp - 'a'+ 10;
646: }
647: }
648:
649: hexlong:
650: yylval.intval = 0;
651: /*
652: * If the constant does not fit within an
653: * int, then consider it a long.
654: */
655: if( lastcon & ~((1 << SZINT) - 1))
656: yylval.intval = 1;
657: goto islong;
658:
659: case '.':
660: lxmore( lxchar, LEXDIG );
661:
662: getfp:
663: if( (lxchar=xgetchar()) == 'e' || lxchar == 'E' ){ /* exponent */
664:
665: case 'e':
666: case 'E':
667: if( (lxchar=xgetchar()) == '+' || lxchar == '-' ){
668: *lxgcp++ = 'e';
669: }
670: else {
671: xungetc(lxchar,stdin);
672: lxchar = 'e';
673: }
674: lxmore( lxchar, LEXDIG );
675: /* now have the whole thing... */
676: }
677: else { /* no exponent */
678: xungetc( lxchar ,stdin);
679: }
680: return( isitfloat( yytext ) );
681:
682: default:
683: xungetc( lxchar ,stdin);
684: if( yytext[0] == '0' ){
685: /* convert in octal */
686: register char *cp;
687: for( cp = yytext+1; *cp; ++cp ){
688: lastcon <<= 3;
689: lastcon += *cp - '0';
690: }
691: goto hexlong;
692: }
693: else {
694: /* convert in decimal */
695: register char *cp;
696: for( cp = yytext; *cp; ++cp ){
697: lastcon = lastcon * 10 + *cp - '0';
698: }
699: }
700:
701: /*
702: * Decide if it is long or not (decimal case).
703: * If it is positive, and fits in (SZINT - 1)
704: * bits, or negative and fits in (SZINT - 1)
705: * bits plus an extended sign, it is int;
706: * otherwise long. If there is an l or L
707: * following, then it is always a long.
708: */
709: { CONSZ v;
710: v = lastcon & ~mask(SZINT - 1);
711: if( v == 0 || v == ~mask(SZINT - 1) )
712: yylval.intval = 0;
713: else yylval.intval = 1;
714: }
715:
716: islong:
717: /* finally, look for trailing L or l */
718: if( (lxchar = xgetchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
719: else xungetc( lxchar ,stdin);
720: return( ICON );
721: }
722:
723: case A_DOT:
724: /* look for a dot: if followed by a digit, floating point */
725: lxchar = xgetchar();
726: if( lxmask[lxchar+1] & LEXDIG ){
727: xungetc(lxchar,stdin);
728: lxget( '.', LEXDIG );
729: goto getfp;
730: }
731: stwart = FUNNYNAME;
732: goto onechar;
733:
734: case A_STR:
735: /* string constant */
736: lxmatch = '"';
737: lxstr('"');
738: return( STRING );
739:
740: case A_CC:
741: /* character constant */
742: lxmatch = '\'';
743: lastcon = 0;
744: lxstr('\'');
745: yylval.intval = 0;
746: return( ICON );
747:
748: case A_BCD:
749: {
750: register i;
751: int j;
752: for( i=0; i<LXTSZ; ++i ){
753: if( ( j = xgetchar() ) == '`' ) break;
754: if( j == '\n' ){
755: uerror( "newline in BCD constant" );
756: break;
757: }
758: yytext[i] = j;
759: }
760: yytext[i] = '\0';
761: if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
762: # ifdef gcos
763: else strtob( yytext, &lastcon, i );
764: lastcon >>= 6*(6-i);
765: # else
766: uerror( "gcos BCD constant illegal" );
767: # endif
768: yylval.intval = 0; /* not long */
769: return( ICON );
770: }
771:
772: case A_SL:
773: /* / */
774: if( (lxchar=xgetchar()) != '*' ) goto onechar;
775: lxcom();
776: case A_WS:
777: continue;
778:
779: case A_NL:
780: ++lineno;
781: lxtitle();
782: continue;
783:
784: case A_NOT:
785: /* ! */
786: if( (lxchar=xgetchar()) != '=' ) goto onechar;
787: yylval.intval = NE;
788: return( EQUOP );
789:
790: case A_MI:
791: /* - */
792: if( (lxchar=xgetchar()) == '-' ){
793: yylval.intval = DECR;
794: return( INCOP );
795: }
796: if( lxchar != '>' ) goto onechar;
797: stwart = FUNNYNAME;
798: yylval.intval=STREF;
799: return( STROP );
800:
801: case A_PL:
802: /* + */
803: if( (lxchar=xgetchar()) != '+' ) goto onechar;
804: yylval.intval = INCR;
805: return( INCOP );
806:
807: case A_AND:
808: /* & */
809: if( (lxchar=xgetchar()) != '&' ) goto onechar;
810: return( yylval.intval = ANDAND );
811:
812: case A_OR:
813: /* | */
814: if( (lxchar=xgetchar()) != '|' ) goto onechar;
815: return( yylval.intval = OROR );
816:
817: case A_LT:
818: /* < */
819: if( (lxchar=xgetchar()) == '<' ){
820: yylval.intval = LS;
821: return( SHIFTOP );
822: }
823: if( lxchar != '=' ) goto onechar;
824: yylval.intval = LE;
825: return( RELOP );
826:
827: case A_GT:
828: /* > */
829: if( (lxchar=xgetchar()) == '>' ){
830: yylval.intval = RS;
831: return(SHIFTOP );
832: }
833: if( lxchar != '=' ) goto onechar;
834: yylval.intval = GE;
835: return( RELOP );
836:
837: case A_EQ:
838: /* = */
839: switch( lxchar = xgetchar() ){
840:
841: case '=':
842: yylval.intval = EQ;
843: return( EQUOP );
844:
845: case '+':
846: yylval.intval = ASG PLUS;
847: break;
848:
849: case '-':
850: yylval.intval = ASG MINUS;
851:
852: warn:
853: if( lxmask[ (lxchar=xgetchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
854: werror( "ambiguous assignment: assignment op taken" );
855: }
856: xungetc( lxchar ,stdin);
857: break;
858:
859: case '*':
860: yylval.intval = ASG MUL;
861: goto warn;
862:
863: case '/':
864: yylval.intval = ASG DIV;
865: break;
866:
867: case '%':
868: yylval.intval = ASG MOD;
869: break;
870:
871: case '&':
872: yylval.intval = ASG AND;
873: break;
874:
875: case '|':
876: yylval.intval = ASG OR;
877: break;
878:
879: case '^':
880: yylval.intval = ASG ER;
881: break;
882:
883: case '<':
884: if( (lxchar=xgetchar()) != '<' ){
885: uerror( "=<%c illegal", lxchar );
886: }
887: yylval.intval = ASG LS;
888: break;
889:
890: case '>':
891: if( (lxchar=xgetchar()) != '>' ){
892: uerror( "=>%c illegal", lxchar );
893: }
894: yylval.intval = ASG RS;
895: break;
896:
897: default:
898: goto onechar;
899:
900: }
901:
902: return( ASOP );
903:
904: default:
905: cerror( "yylex error, character %03o (octal)", lxchar );
906:
907: }
908:
909: /* ordinarily, repeat here... */
910: cerror( "out of switch in yylex" );
911:
912: }
913:
914: }
915:
916: struct lxrdope {
917: /* dope for reserved, in alphabetical order */
918:
919: char *lxrch; /* name of reserved word */
920: short lxract; /* reserved word action */
921: short lxrval; /* value to be returned */
922: } lxrdope[] = {
923:
924: "asm", AR_A, 0,
925: "auto", AR_CL, AUTO,
926: "break", AR_RW, BREAK,
927: "char", AR_TY, CHAR,
928: "case", AR_RW, CASE,
929: "continue", AR_RW, CONTINUE,
930: "double", AR_TY, DOUBLE,
931: "default", AR_RW, DEFAULT,
932: "do", AR_RW, DO,
933: "extern", AR_CL, EXTERN,
934: "else", AR_RW, ELSE,
935: "enum", AR_E, ENUM,
936: "for", AR_RW, FOR,
937: "float", AR_TY, FLOAT,
938: "fortran", AR_CL, FORTRAN,
939: "goto", AR_RW, GOTO,
940: "if", AR_RW, IF,
941: "int", AR_TY, INT,
942: "long", AR_TY, LONG,
943: "return", AR_RW, RETURN,
944: "register", AR_CL, REGISTER,
945: "switch", AR_RW, SWITCH,
946: "struct", AR_S, 0,
947: "sizeof", AR_RW, SIZEOF,
948: "short", AR_TY, SHORT,
949: "static", AR_CL, STATIC,
950: "typedef", AR_CL, TYPEDEF,
951: "unsigned", AR_TY, UNSIGNED,
952: "union", AR_U, 0,
953: "void", AR_TY, UNDEF, /* tymerge adds FTN */
954: "while", AR_RW, WHILE,
955: "", 0, 0, /* to stop the search */
956: };
957:
958: lxres() {
959: /* check to see of yytext is reserved; if so,
960: /* do the appropriate action and return */
961: /* otherwise, return -1 */
962:
963: register c, ch;
964: register struct lxrdope *p;
965:
966: ch = yytext[0];
967:
968: if( !islower(ch) ) return( -1 );
969:
970: switch( ch ){
971:
972: case 'a':
973: c=0; break;
974: case 'b':
975: c=2; break;
976: case 'c':
977: c=3; break;
978: case 'd':
979: c=6; break;
980: case 'e':
981: c=9; break;
982: case 'f':
983: c=12; break;
984: case 'g':
985: c=15; break;
986: case 'i':
987: c=16; break;
988: case 'l':
989: c=18; break;
990: case 'r':
991: c=19; break;
992: case 's':
993: c=21; break;
994: case 't':
995: c=26; break;
996: case 'u':
997: c=27; break;
998: case 'v':
999: c=29; break;
1000: case 'w':
1001: c=30; break;
1002:
1003: default:
1004: return( -1 );
1005: }
1006:
1007: for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
1008: if( !strcmp( yytext, p->lxrch ) ){ /* match */
1009: switch( p->lxract ){
1010:
1011: case AR_TY:
1012: /* type word */
1013: stwart = instruct;
1014: yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
1015: return( TYPE );
1016:
1017: case AR_RW:
1018: /* ordinary reserved word */
1019: return( yylval.intval = p->lxrval );
1020:
1021: case AR_CL:
1022: /* class word */
1023: yylval.intval = p->lxrval;
1024: return( CLASS );
1025:
1026: case AR_S:
1027: /* struct */
1028: stwart = INSTRUCT|SEENAME|TAGNAME;
1029: yylval.intval = INSTRUCT;
1030: return( STRUCT );
1031:
1032: case AR_U:
1033: /* union */
1034: stwart = INUNION|SEENAME|TAGNAME;
1035: yylval.intval = INUNION;
1036: return( STRUCT );
1037:
1038: case AR_E:
1039: /* enums */
1040: stwart = SEENAME|TAGNAME;
1041: return( yylval.intval = ENUM );
1042:
1043: case AR_A:
1044: /* asm */
1045: asm_esc = 1; /* warn the world! */
1046: return( ASM );
1047:
1048: default:
1049: cerror( "bad AR_?? action" );
1050: }
1051: }
1052: }
1053: return( -1 );
1054: }
1055:
1056: extern int labelno;
1057:
1058: #define PUSHINCL '1' /* Entering a header file */
1059: #define POPINCL '2' /* Exited a header file */
1060:
1061: lxtitle(){
1062: /* called after a newline; set linenumber and file name */
1063:
1064: register c, val;
1065: register char *cp, *cq;
1066:
1067: for(;;){ /* might be several such lines in a row */
1068: if( (c=xgetchar()) != '#' ){
1069: if( c != EOF ) xungetc(c,stdin);
1070: #ifndef LINT
1071: if ( lastloc != PROG) return;
1072: cp = ftitle;
1073: cq = ititle;
1074: while ( *cp ) if (*cp++ != *cq++) return;
1075: if ( *cq ) return;
1076: #endif
1077: return;
1078: }
1079:
1080: lxget( ' ', LEXWS );
1081: val = 0;
1082: for( c=xgetchar(); isdigit(c); c=xgetchar() ){
1083: val = val*10+ c - '0';
1084: }
1085: xungetc( c, stdin );
1086: lineno = val;
1087: lxget( ' ', LEXWS );
1088: if( (c=xgetchar()) != '\n' ){
1089: for( cp=ftitle; c!=' ' && c!='\n'; c=xgetchar(),++cp ){
1090: *cp = c;
1091: }
1092: *cp = '\0';
1093: if (c != '\n') {
1094: while ((c = xgetchar()) == ' ')
1095: ;
1096: if (c != '\n')
1097: xgetchar();
1098: }
1099: #ifndef LINT
1100: if (ititle[0] == '\0') {
1101: cp = ftitle;
1102: cq = ititle;
1103: while ( *cp )
1104: *cq++ = *cp++;
1105: *cq = '\0';
1106: *--cq = '\0';
1107: }
1108: #endif
1109: }
1110: }
1111: }
1112:
1113:
1114:
1115: #ifdef FLEXNAMES
1116: #define NSAVETAB 4096
1117: char *savetab;
1118: int saveleft;
1119:
1120: char *
1121: savestr(cp)
1122: register char *cp;
1123: {
1124: register int len;
1125:
1126: len = strlen(cp) + 1;
1127: if (len > saveleft) {
1128: saveleft = NSAVETAB;
1129: if (len > saveleft)
1130: saveleft = len;
1131: savetab = (char *)malloc(saveleft);
1132: if (savetab == 0)
1133: cerror("Ran out of memory (savestr)");
1134: }
1135: strncpy(savetab, cp, len);
1136: cp = savetab;
1137: savetab += len;
1138: saveleft -= len;
1139: return (cp);
1140: }
1141:
1142: /*
1143: * The definition for the segmented hash tables.
1144: */
1145: #define MAXHASH 20
1146: #define HASHINC 1013
1147: struct ht {
1148: char **ht_low;
1149: char **ht_high;
1150: int ht_used;
1151: } htab[MAXHASH];
1152:
1153: char *
1154: hash(s)
1155: char *s;
1156: {
1157: register char **h;
1158: register i;
1159: register char *cp;
1160: struct ht *htp;
1161: int sh;
1162:
1163: /*
1164: * The hash function is a modular hash of
1165: * the sum of the characters with the sum
1166: * doubled before each successive character
1167: * is added.
1168: */
1169: cp = s;
1170: i = 0;
1171: while (*cp)
1172: i = i*2 + *cp++;
1173: sh = (i&077777) % HASHINC;
1174: cp = s;
1175: /*
1176: * There are as many as MAXHASH active
1177: * hash tables at any given point in time.
1178: * The search starts with the first table
1179: * and continues through the active tables
1180: * as necessary.
1181: */
1182: for (htp = htab; htp < &htab[MAXHASH]; htp++) {
1183: if (htp->ht_low == 0) {
1184: register char **hp =
1185: (char **) calloc(sizeof (char **), HASHINC);
1186: if (hp == 0)
1187: cerror("ran out of memory (hash)");
1188: htp->ht_low = hp;
1189: htp->ht_high = htp->ht_low + HASHINC;
1190: }
1191: h = htp->ht_low + sh;
1192: /*
1193: * quadratic rehash increment
1194: * starts at 1 and incremented
1195: * by two each rehash.
1196: */
1197: i = 1;
1198: do {
1199: if (*h == 0) {
1200: if (htp->ht_used > (HASHINC * 3)/4)
1201: break;
1202: htp->ht_used++;
1203: *h = savestr(cp);
1204: return (*h);
1205: }
1206: if (**h == *cp && strcmp(*h, cp) == 0)
1207: return (*h);
1208: h += i;
1209: i += 2;
1210: if (h >= htp->ht_high)
1211: h -= HASHINC;
1212: } while (i < HASHINC);
1213: }
1214: cerror("ran out of hash tables");
1215: }
1216: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.