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