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