1 #ifndef lint
2 static char *sccsid ="@(#)scan.c 2.16 (Berkeley) 09/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 */
mainp1(argc,argv)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
lxenter(s,m)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
lxmore(c,m)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
lxinit()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
lxstr(ct)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
lxcom()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
yylex()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
lxres()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
lxtitle()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 *
savestr(cp)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 *
hash(s)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
1299