|
|
1.1 root 1: /*
2: * This file contains all of the lexical analysis routines
3: * for the portable C compiler.
4: */
5: #ifdef vax
6: #include "INC$LIB:cc0.h"
7: #else
8: #include "cc0.h"
9: #endif
10:
11: /*
12: * Character classes.
13: * Indexed by ASCII character code.
14: */
15: unsigned char ct[] = {
16: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK,
17: JUNK, SKIP, SKIP, SKIP, SKIP, SKIP, JUNK, JUNK,
18: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK,
19: JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK,
20: SKIP, NOT, STRING, SHARP, JUNK, REM, AND, QUOTE,
21: LPAREN, RPAREN, MUL, ADD, COMMA, SUB, DOT, DIV,
22: CON, CON, CON, CON, CON, CON, CON, CON,
23: CON, CON, COLON, SEMI, LT, ASSIGN, GT, QUEST,
24: JUNK, ID, ID, ID, ID, ID, ID, ID,
25: ID, ID, ID, ID, ID, ID, ID, ID,
26: ID, ID, ID, ID, ID, ID, ID, ID,
27: ID, ID, ID, LBRACK, BACKDIV,RBRACK, XOR, ID,
28: JUNK, ID, ID, ID, ID, ID, ID, ID,
29: ID, ID, ID, ID, ID, ID, ID, ID,
30: ID, ID, ID, ID, ID, ID, ID, ID,
31: ID, ID, ID, LBRACE, OR, RBRACE, COM, JUNK,
32: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0,
33: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0,
34: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0,
35: HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0, HIGH0,
36: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1,
37: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1,
38: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1,
39: HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1, HIGH1,
40: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2,
41: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2,
42: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2,
43: HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2, HIGH2,
44: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3,
45: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3,
46: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3,
47: HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3, HIGH3
48: };
49:
50: /*
51: * Read and decode the next token of the input.
52: * The token is returned and stored in 's'.
53: * Identifiers are packed into 'id'
54: * and their hash table slot is stashed in 'idhash'.
55: * Integers are returned in 'ival',
56: * long integers in 'lval' and doubles in 'dval'.
57: */
58: lex()
59: {
60: register SYM *sp;
61: register int c;
62: register int n;
63:
64: for (;;) {
65: if ((c=get()) < 0)
66: return (s = EOF);
67: switch (s = ct[c]) {
68:
69: case SKIP:
70: continue;
71:
72: case QUOTE:
73: n = 0;
74: lval = 0;
75: instring = c; /* to allow high-bit chars */
76: while ((c = getmap('\'')) >= 0) {
77: lval <<= 8;
78: lval |= c;
79: ++n;
80: }
81: instring = 0;
82: ival = lval;
83: tval = T_INT;
84: s = ICON;
85: #if 0
86: switch (n) {
87: case 0:
88: cwarn("empty character constant");
89: break;
90: case 2:
91: cwarn("multiple character constant");
92: tval = T_INT;
93: break;
94: case 1:
95: break;
96: case 3:
97: case 4:
98: cwarn("character constant promoted to long");
99: tval = T_LONG;
100: s = LCON;
101: break;
102: default:
103: cerror("character constant overflows long");
104: tval = T_LONG;
105: s = LCON;
106: break;
107: }
108: #else
109: if (n != 1)
110: cerror("multiple character constant");
111: #endif
112: break;
113:
114: case ADD:
115: if (nextis('+'))
116: s = INCBEF;
117: break;
118:
119: case SUB:
120: if (nextis('-'))
121: s = DECBEF;
122: else if (nextis('>'))
123: s = ARROW;
124: break;
125:
126: case LT:
127: if (nextis('='))
128: s = LE;
129: else if (nextis('<'))
130: s = SHL;
131: break;
132:
133: case GT:
134: if (nextis('='))
135: s = GE;
136: else if (nextis('>'))
137: s = SHR;
138: break;
139:
140: case ASSIGN:
141: if (nextis('='))
142: s = EQ;
143: break;
144:
145: case NOT:
146: if (nextis('='))
147: s = NE;
148: break;
149:
150: case AND:
151: if (nextis('&'))
152: s = ANDAND;
153: break;
154:
155: case OR:
156: if (nextis('|'))
157: s = OROR;
158: break;
159:
160: case DOT:
161: c = get();
162: if (c<0 || ct[c]!=CON) {
163: unget(c);
164: break;
165: }
166: getnum(c, 1);
167: break;
168:
169: case CON:
170: getnum(c, 0);
171: break;
172:
173: case ID:
174: if (expand(c))
175: continue;
176: for (sp = idp->t_sym; sp != NULL; sp = sp->s_sp)
177: if (sp->s_slevel == SL_KEY) {
178: s = sp->s_value;
179: break;
180: }
181: break;
182:
183: case JUNK:
184: case HIGH0:
185: case HIGH1:
186: case HIGH2:
187: case HIGH3:
188: cerror("illegal character (%d decimal)", c);
189: continue;
190:
191: }
192: if ((s>=ADD && s<=SHR) && nextis('='))
193: s += AADD-ADD;
194: return (s);
195: }
196: }
197:
198: /*
199: * Test if the next character in the input is 'n'.
200: * If it is, eat it up and return true;
201: * otherwise put it back and return false.
202: */
203: nextis(n) int n;
204: {
205: register int c;
206:
207: if ((c = get()) == n)
208: return (1);
209: unget(c);
210: return (0);
211: }
212:
213: /*
214: * Get the next non blank character from the input.
215: * This is for cpp, so we do not pass newline.
216: */
217: getnb()
218: {
219: register int c;
220:
221: while ((c = get())==' ' || c=='\t')
222: ;
223: return (c);
224: }
225:
226: /*
227: * Get the next non-skip character.
228: * Different from getnb() which chokes
229: * on newline.
230: */
231: getskip()
232: {
233: register int c;
234:
235: while ((c = get()) > 0 && ct[c] == SKIP)
236: ;
237: return c;
238: }
239:
240: /*
241: * Peek ahead in the input (ignoring whitespace)
242: * to see if the next character is 'n'.
243: * True return it it is.
244: * The character is left in the input stream.
245: * This routine is used to look for the ':' after labels
246: * and the '(' after undefined names in expressions.
247: */
248: spnextis(n) int n;
249: {
250: register int c;
251:
252: while ((c=get()) >= 0) {
253: if (ct[c] != SKIP) {
254: unget(c);
255: if (c == n)
256: return (1);
257: return (0);
258: }
259: }
260: return (0);
261: }
262:
263: /*
264: * This routine is like lex(), except that it correctly skips
265: * over any strings in the input.
266: * Used during error recovery.
267: */
268: skip()
269: {
270: if (s == STRING)
271: while (getmap('\"') >= 0)
272: ;
273: lex();
274: }
275:
276: /*
277: * Read the next character from a string or a character constant.
278: * Return -1 when either end of file or the delimiter 'd' is encountered.
279: */
280: getmap(d) int d;
281: {
282: register int c, n, v;
283:
284: if ((c=get()) == d)
285: return (-1);
286: if (c<0 || c=='\n') {
287: unget(c);
288: cerror("nonterminated string or character constant");
289: return (-1);
290: }
291: if (c == '\\') {
292: c = get();
293: switch (c) {
294:
295: case 'a':
296: c = '\07';
297: break;
298:
299: case 'b':
300: c = '\b';
301: break;
302:
303: case 'f':
304: c = '\f';
305: break;
306:
307: case 'n':
308: c = '\n';
309: break;
310:
311: case 'r':
312: c = '\r';
313: break;
314:
315: case 't':
316: c = '\t';
317: break;
318:
319: case 'v':
320: c = '\013';
321: break;
322:
323: case 'x':
324: notbook();
325: c = get();
326: n = 0;
327: v = 0;
328: while (++n<=3
329: && ( (c>='0' && c<='9')
330: || (c>='A' && c<='F')
331: || (c>='a' && c<='f') )) {
332: v <<= 4;
333: if (c>='0' && c<='9')
334: v += c - '0';
335: else if (c>='A' && c<='F')
336: v += c - 'A' + 10;
337: else
338: v += c - 'a' + 10;
339: c = get();
340: }
341: unget(c);
342: c = v;
343: break;
344:
345: case '0':
346: case '1':
347: case '2':
348: case '3':
349: case '4':
350: case '5':
351: case '6':
352: case '7':
353: n = 0;
354: v = 0;
355: while (++n<=3 && c>='0' && c<='7') {
356: v = (v<<3) + c - '0';
357: c = get();
358: }
359: unget(c);
360: c = v;
361: break;
362: }
363: }
364: return (c);
365: }
366:
367: /*
368: * Read an identifier into id[]
369: * and set idhash.
370: */
371: getid(ch) int ch;
372: {
373: {
374: register char *p;
375: register int c;
376: c = ch;
377: p = id;
378: idhash = 0;
379: idsize = 0;
380: idhide = -1; /* Universal */
381: do {
382: if (p < &id[NCSYMB-1]) {
383: *p++ = c;
384: idhash += c;
385: idsize += 1;
386: }
387: if ((c = get()) >= SET0) {
388: idhide = hideint(c, idhide);
389: c = get();
390: }
391: } while (c>=0 && (ct[c]==ID || ct[c]==CON));
392: unget(c);
393: if (idhide == -1)
394: idhide = SET0; /* Empty */
395: *p++ = 0;
396: *p++ = 0;
397: *p++ = 0;
398: }
399: {
400: register TOK *tp, **tpp;
401:
402: idhash %= NHASH;
403: for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp)
404: if (ideq(tp))
405: break;
406: if (tp == NULL)
407: *tpp = tp = newtoken();
408: idp = tp;
409: }
410: }
411:
412: setid(cp) char *cp;
413: {
414: {
415: register char *p1, *p2;
416: register int c;
417:
418: p1 = cp;
419: p2 = id;
420: idhash = 0;
421: idsize = 0;
422: while (c = *p1++) {
423: if (p2 < &id[NCSYMB-1]) {
424: *p2++ = c;
425: idhash += c;
426: idsize += 1;
427: }
428: }
429: *p2 = 0;
430: }
431: {
432: register TOK *tp, **tpp;
433:
434: idhash %= NHASH;
435: for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp)
436: if (ideq(tp))
437: break;
438: if (tp == NULL)
439: *tpp = tp = newtoken();
440: idp = tp;
441: }
442: }
443:
444: /*
445: * Read number into id[].
446: * Set 's' appropriately.
447: */
448: getnum(c, dotf) register int c; int dotf;
449: {
450: register char *np;
451: int expf, sgnf, ntlf, base;
452: int islong, isunsigned, isfloat;
453: long n;
454: static char ulong[] = "unsigned long";
455: # define slong (ulong+9)
456: #if NATIVEFP
457: double d;
458: char *cp, *dp;
459: extern double atof();
460: #endif
461:
462: expf = 0;
463: ntlf = 0;
464: sgnf = 1;
465: base = 10;
466: islong = 0;
467: isunsigned = 0;
468: isfloat = 0;
469: np = id;
470: n = 0;
471: if (dotf)
472: *np++ = '.';
473: if (dotf==0 && c=='0') {
474: base = 8;
475: if ((c = get()) == 'x' || c == 'X') {
476: *np++ = '0';
477: *np++ = c;
478: base = 16;
479: c = get();
480: } else {
481: unget(c);
482: c = '0';
483: }
484: }
485: do {
486: if (base!=16 && c=='.') {
487: if (dotf++)
488: break;
489: } else if (c=='+' || c=='-') {
490: if (sgnf++)
491: break;
492: } else if (base!=16 && (c=='e' || c=='E')) {
493: if (expf++)
494: break;
495: sgnf = 0;
496: } else if (c<'0' || c>'9') {
497: if (base != 16)
498: break;
499: if (!((c>='A' && c<='F') || (c>='a' && c<='f')))
500: break;
501: } else
502: ++sgnf;
503: if (np < &id[NCSYMB-1])
504: *np++ = c;
505: else
506: ntlf = 1;
507: if (base == 8)
508: n <<= 3;
509: else if (base == 10)
510: n = (n<<3) + (n<<1);
511: else
512: n <<= 4;
513: if (c>='A' && c<='F')
514: c -= 'A'-10;
515: else if (c>='a' && c<='f')
516: c -= 'a'-10;
517: else
518: c -= '0';
519: n += c;
520: } while ((c = get()) >= 0);
521: for (;;) {
522: if (c=='l' || c=='L') {
523: ++islong;
524: *np++ = c;
525: c = get();
526: } else if (c == 'u' || c == 'U') {
527: ++isunsigned;
528: *np++ = c;
529: c = get();
530: } else if (c == 'f' || c == 'F') {
531: ++isfloat;
532: *np++ = c;
533: c = get();
534: } else {
535: unget(c);
536: *np = 0;
537: break;
538: }
539: }
540: s = ICON;
541: tval = T_INT;
542: ival = lval = n;
543: if (ntlf) {
544: cerror("number has too many digits");
545: return;
546: }
547: if (dotf || expf || isfloat) {
548: if (isunsigned || (isfloat+islong > 1)) {
549: cerror("illegal floating constant suffix");
550: return;
551: }
552: tval = isfloat ? T_FLOAT : islong ? T_LDOUBLE : T_DOUBLE;
553: #if NATIVEFP
554: d = atof(id);
555: for (dp = (char *)dval, cp = ((char *)&d)+sizeof(double)-1; cp >= &d; )
556: *dp++ = *cp--;
557: #else
558: dvalread((char *)dval, id);
559: #endif
560: s = DCON;
561: return;
562: }
563: if (isunsigned > 1 || islong > 1) {
564: cerror("illegal integer constant suffix");
565: return;
566: }
567: np = NULL;
568: if (islong) {
569: s = LCON;
570: tval = T_LONG;
571: if (isunsigned || (n&SLMASK) != 0)
572: tval = T_ULONG;
573: } else if (isunsigned) {
574: tval = T_UINT;
575: if ((n&UIMASK) != 0) {
576: s = LCON;
577: tval = T_ULONG;
578: np = ulong;
579: }
580: } else if (base == 10 && (n&SIMASK) != 0) {
581: s = LCON;
582: tval = T_LONG;
583: np = slong;
584: if ((n&SLMASK) != 0) {
585: tval = T_ULONG;
586: np = ulong;
587: }
588: } else if ((n&SIMASK) != 0) {
589: tval = T_UINT;
590: if ((n&UIMASK) != 0) {
591: s = LCON;
592: tval = T_LONG;
593: np = slong;
594: if ((n&SLMASK) != 0) {
595: tval = T_ULONG;
596: np = ulong;
597: }
598: }
599: }
600: if (tval == T_ULONG) {
601: /* Test for unsigned long overflow */
602: /* and set np = NULL if a diagnostic is given */
603: ;
604: }
605: if (incpp == 0 && np != NULL && isvariant(VSLCON))
606: cwarn("\"%s\" promoted to %s", id, np);
607: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.