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