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