|
|
1.1 root 1: /*
2: * C compiler.
3: * Syntax analyser mainline.
4: * Impure stuff.
5: */
6: #ifdef vax
7: #include "INC$LIB:cc0.h"
8: #else
9: #include "cc0.h"
10: #endif
11:
12: /*
13: * Impure areas.
14: * All external impure data is here
15: * and is reinitialized by the overlaid version of the mainline.
16: * This permits the compiler to be called many times if loaded as a big block.
17: */
18: #if !OVERLAID
19: int line = 1; /* Source line */
20: char file[NFNAME]; /* Source file name */
21: TOK *tfile; /* Source file token */
22: char id[NCSYMB]; /* Identifier buffer */
23: FILE *ifp; /* Input file pointer */
24: FILE *ofp; /* Output file pointer */
25: VARIANT variant; /* Variant template */
26: #endif
27:
28: /* Cpp variables */
29: char dbuf[NDBUF]; /* Substitution buffer */
30: char *dputp = dbuf; /* Define buffer pointer */
31: char *dpshp = dbuf+sizeof(dbuf); /* Define buffer pointer */
32: DSTACK dstack[NDLEV]; /* Substitution stack */
33: DSTACK *dlistp=dstack; /* Substitution list */
34: DSTACK *dstackp=dstack+NDLEV-1; /* Input stack */
35: ISTACK istack[NLEV]; /* Include stack */
36: ISTACK *istackp=istack+NLEV; /* Include stack pointer */
37: CSTACK cstack[NLEV]; /* Condition stack pointer */
38: CSTACK *cstackp=cstack+NLEV; /* Condition stack pointer */
39: int cstate = 0; /* Conditional state == true */
40: int ndirs; /* Number of include directories */
41: char *incdirs[NDIRS+3]; /* Include directory list */
42: char deftrue[] = "1";
43: char deffalse[] = "0";
44: long curtime; /* NB should be time_t */
45:
46: int incpp; /* "in a cpp control" flag */
47: int instring; /* "in a string" flag */
48: int notskip; /* count of not skipped chars */
49: int lastchar; /* Last character read from a file */
50: int ininit; /* "in an initializer" flag */
51: int incase; /* "in a case" flag */
52: int nargs; /* # of args this function */
53: SYM *args[NARGS]; /* The args themselves */
54: int llex; /* Lexical level */
55: int lsym = SL_MOS; /* Symbol table level */
56: ival_t ival; /* Return for lex */
57: lval_t lval; /* Return for lex */
58: dval_t dval; /* Return for lex */
59: short tval; /* Return for lex int/long constant type */
60: unsigned idhash; /* Hash number for symbol */
61: unsigned idhide; /* Hide set for symbol */
62: HIDESET *hidefree, *hidesets; /* Hide set management */
63: int idsize; /* Length of symbol */
64: TOK *idp; /* Hashed identifier token */
65: TOK *hash0[NHASH]; /* Hash table */
66: int cblab; /* Break label */
67: int cclab; /* Continue label */
68: SBLOCK *sbp; /* Current switch block */
69: SYM *cfsym; /* Current symbol */
70: int cflab; /* Current return label */
71: int s; /* Lexical window */
72:
73: /*
74: * It all starts here.
75: * Open the source file.
76: * Open the output stream file.
77: * Put reserved words into the symbol table.
78: * Parse externals until end of file.
79: * Finish off the output stream and exit.
80: */
81: #if !OVERLAID
82: main(argc, argv)
83: char *argv[];
84: {
85: register char *p;
86: register int i;
87: extern char *index();
88: extern char *getenv();
89:
90: passname = "cc0";
91: if (argc < 4)
92: usage();
93: getvariant(argv[1]);
94: if ((ifp=fopen(argv[2], "r")) == NULL) {
95: fprintf(stderr, "%s: cannot open.\n", argv[2]);
96: exit(BAD);
97: }
98: if (isvariant(VCPP)) {
99: if (strcmp(argv[3], "-") == 0)
100: ofp = stdout;
101: else if ((ofp = fopen(argv[3], "w")) == NULL) {
102: fprintf(stderr, "%s: cannot create.\n", argv[3]);
103: exit(BAD);
104: }
105: } else if ((ofp=fopen(argv[3], SWMODE)) == NULL) {
106: fprintf(stderr, "%s: cannot create.\n", argv[3]);
107: exit(BAD);
108: }
109: vinit();
110: kinit();
111: time(&curtime);
112: newtree(sizeof(TREE));
113: cppd(MACHINE, deftrue);
114: cppd(SYSTEM, deftrue);
115: cppd(LOCATION, deftrue);
116: cppi(argv[2]); /* Source directory will be parsed later */
117: for (i=4; i<argc; ++i) {
118: if (argv[i][0] != '-')
119: break;
120: switch (argv[i][1]) {
121: case 'I': cppi(argv[i]+2); break;
122: case 'U': cppu(argv[i]+2); break;
123: case 'D':
124: if (p = index(argv[i]+2, '='))
125: *p++ = 0;
126: else
127: p = deftrue;
128: cppd(argv[i]+2, p);
129: break;
130: default:
131: usage();
132: }
133: }
134: if ((p = getenv("INCDIR")) == 0)
135: p = DEFDISK;
136: cppi(p);
137: cppi(argv[2]); /* Second copy of source directory */
138: setid(argv[2]);
139: setfname();
140: /* Now parse the source file directory */
141: i = 0;
142: #if COHERENT
143: for (p = argv[2]; *p != 0; p += 1)
144: if (*p == '/')
145: i = p-argv[2];
146: #endif
147: #if GEMDOS || MSDOS
148: for (p = argv[2]; *p != 0; p += 1)
149: if (*p == '\\')
150: i = p-argv[2];
151: #endif
152: argv[2][i] = 0;
153: emptyfilep();
154: if (notvariant(VCPP)) {
155: dbfname(file);
156: setmname();
157: labgen = 0;
158: oldseg = -1;
159: while (lex() != EOF)
160: xdef();
161: llex = -1;
162: downlex();
163: bput(FINISH);
164: } else
165: cppwork();
166: if (nerr != 0)
167: exit(BAD);
168: exit(OK);
169: }
170:
171: /*
172: * Print usage message.
173: */
174: usage()
175: {
176: fprintf(stderr,
177: "Usage: cc0 variant in out [-Dname[=value]] [-Idirectory] [-Uname]\n"
178: );
179: exit(BAD);
180: }
181:
182: #else
183: #assert 0 /* This is not ready for the new conventions */
184: /* The argv syntax needs to be worked out */
185: /* Cleaning up the HIDESET and TOK and SYM pools as well */
186: /*
187: * This is the mainline of the syntax analysis phase
188: * if the compiler is being run as an overlay job.
189: * The impure area must be reinitialized if monolithic,
190: * because the code can be called again and again.
191: */
192: cc0()
193: {
194: register char *p;
195: register int i;
196: extern char *index();
197:
198: passname = "cc0";
199: if (setjmp(death) != 0) {
200: llex = -1;
201: downlex();
202: cppfinal();
203: return (ABORT);
204: }
205: vinit();
206: kinit();
207: cppi("");
208: time(&curtime);
209: newtree(sizeof(TREE));
210: for (i=4; i<argc; ++i) {
211: if (argv[i][0] != '-')
212: break;
213: switch (argv[i][1]) {
214: case 'I':
215: cppi(argv[i]+2);
216: break;
217: case 'U':
218: cppu(argv[i]+2);
219: break;
220: case 'D':
221: if (p = index(argv[i]+2, '='))
222: *p++ = 0;
223: else
224: p = deftrue;
225: cppd(argv[i]+2, p);
226: break;
227: default:
228: cbotch("cpp args");
229: }
230: }
231: cppi(DEFDISK);
232: cppi("");
233: labgen = 0;
234: oldseg = -1;
235: line = 1;
236: #if MONOLITHIC
237: incpp = 0;
238: instring = 0;
239: lastchar = 0;
240: ininit = 0;
241: incase = 0;
242: cblab = 0;
243: cclab = 0;
244: sbp = NULL;
245: cfsym = NULL;
246: lsym = SL_MOS;
247: ndirs = 0;
248: dputp = dbuf;
249: dpshp = dbuf+sizeof(dbuf);
250: dstackp = dstack + NDLEV-1;
251: dlistp = dstack;
252: istackp = istack + NLEV;
253: cstackp = cstack + NLEV;
254: cstate = 0;
255: #endif
256: setid(argv[2]);
257: setfname();
258: if (notvariant(VCPP)) {
259: setmname();
260: while (lex() != EOF)
261: xdef();
262: llex = -1;
263: downlex();
264: bput(FINISH);
265: } else
266: cppwork();
267: cppfinal();
268: if (nerr != 0)
269: return (BAD);
270: return (OK);
271: }
272: #endif
273:
274: /*
275: * Given the file name token in idp,
276: * inform the usual parties of the change.
277: */
278: setfname()
279: {
280: tfile = idp;
281: strncpy(file, idp->t_id, NFNAME);
282: if (notvariant(VCPP)) {
283: bput(FNAME);
284: sput(file);
285: } else if (notvariant(VCPPE))
286: fprintf(ofp, "#line %d \"%s\"\n", line, file);
287: }
288:
289: /*
290: * Given a file name string,
291: * make up the associated module name.
292: * And then send it on it's way.
293: * This routine is tinkered for UDI, DEC systems, MS-DOS
294: * and for the Coherent-like systems.
295: * Of course, the MNAME item is pointless
296: * to all systems except .omf, but we do
297: * it anyway.
298: * NB, id[] is used as a buffer
299: * to construct the module name.
300: */
301: setmname()
302: {
303: register char *tp, *p1, *p2;
304:
305: tp = id;
306: p1 = file;
307: while (*p1 != 0)
308: ++p1;
309: p2 = p1;
310: while (p1>file
311: && (p1[-1]!=':' && p1[-1]!='/' && p1[-1]!=']' && p1[-1]!='\\'))
312: --p1;
313: while (p2>p1 && p2[0]!='.')
314: --p2;
315: while (p1 < p2)
316: *tp++ = *p1++;
317: *tp = 0;
318: bput(MNAME);
319: sput(id);
320: }
321:
322: /*
323: * Process an external declaration.
324: * On entry, 's' contains the first token of the external.
325: * On exit, 's' contains the last token in the declaration.
326: */
327: xdef()
328: {
329: register SYM *sp;
330: SYM *nsp;
331: DIM *dp, *ndp;
332: INFO *ip;
333: int c;
334: int t;
335: int rf;
336: int seg;
337:
338: if (s == SEMI)
339: return;
340: gcandt(&c, &t, &dp, &ip, &rf);
341: if (c == C_NONE)
342: c = C_GDEF;
343: else if (c == C_SIN)
344: c = C_SEX;
345: else if (c!=C_GREF && c!=C_TYPE) {
346: cerror("bad external storage class");
347: c = C_GDEF;
348: }
349: if (s == SEMI) {
350: xdropinfo(t, ip);
351: return;
352: }
353: if (t == T_NONE)
354: t = T_INT;
355: for (;;) {
356: if (!gdecl(&nsp, &ndp, dp, c, SL_VAR)) {
357: cerror("external syntax");
358: while (s!=EOF && s!=SEMI && s!=LBRACE && s!=RBRACE)
359: skip();
360: if (s == LBRACE)
361: statement();
362: break;
363: }
364: sp = nsp;
365: sp = declare(sp, c, t, ndp, ip, rf);
366: if (c!=C_GREF && sp->s_class!=C_GREF && sp->s_class!=C_TYPE) {
367: if (isfunc(sp)) {
368: xfunc(sp);
369: break;
370: }
371: seg = SPURE;
372: if (s==EOF || s==COMMA || s==SEMI) {
373: if ((rf&S_RONLY) == 0)
374: seg = SBSS;
375: sp->s_seg = seg;
376: if (isvariant(VCOMM)
377: && sp->s_class == C_GDEF
378: && seg == SBSS) {
379: sp->s_class = C_GREF;
380: bput(COMM);
381: nput(sp->s_id);
382: } else {
383: newseg(seg);
384: align(sp);
385: xlabel(sp);
386: bput(BLOCK);
387: }
388: zput(ssize(sp));
389: } else {
390: if ((rf&S_RONLY) == 0)
391: seg = SDATA;
392: sp->s_seg = seg;
393: newseg(seg);
394: align(sp);
395: xlabel(sp);
396: /*
397: * The following gives a warning rather than an
398: * error (over steve's objection) so programs
399: * using old style initializers e.g. "int i 1;"
400: * will compile; see K&R "Anachronisms" p. 212.
401: */
402: if (s != ASSIGN)
403: cwarn("missing '='");
404: else
405: lex();
406: init(sp, sp->s_dp, (sizeof_t)0, 1);
407: }
408: dbdecl(sp);
409: }
410: if (s != COMMA) {
411: if (s != SEMI)
412: cerror("missing semicolon");
413: break;
414: }
415: lex();
416: }
417: xdropinfo(t, ip);
418: }
419:
420: /*
421: * Test if the symbol pointed to by 'sp' is a function.
422: */
423: isfunc(sp)
424: SYM *sp;
425: {
426: register DIM *dp;
427:
428: if ((dp=sp->s_dp)!=NULL && dp->d_type==D_FUNC)
429: return (1);
430: return (0);
431: }
432:
433: /*
434: * Compile a function.
435: * 'sp' points at the symbol table node for the function name.
436: * 's' is the first token after the function declaration.
437: */
438: xfunc(sp)
439: register SYM *sp;
440: {
441: register SYM *fsp;
442: SYM *nfsp;
443: DIM *dp, *fdp;
444: INFO *ip;
445: int c;
446: int t;
447: int rf;
448: int fline;
449:
450: fline = line;
451: for (;;) {
452: gcandt(&c, &t, &dp, &ip, &rf);
453: if (c==C_NONE && t==T_NONE)
454: break;
455: if (c == C_NONE)
456: c = C_PAUTO;
457: else if (c == C_REG)
458: c = C_PREG;
459: else {
460: cerror("bad argument storage class");
461: c = C_PAUTO;
462: }
463: if (t == T_NONE)
464: t = T_INT;
465: for (;;) {
466: if (gdecl(&nfsp, &fdp, dp, c, SL_VAR)) {
467: fsp = nfsp;
468: fsp = declare(fsp, c, t, fdp, ip, rf);
469: }
470: if (s != COMMA)
471: break;
472: lex();
473: }
474: xdropinfo(t, ip);
475: mustbe(SEMI);
476: }
477: initlocals();
478: bindargs();
479: newseg(SCODE);
480: sp->s_seg = SCODE;
481: xlabel(sp);
482: bput(PROLOG);
483: loadargs();
484: dbdecl(sp);
485: dbargs();
486: dbstat(LBRACE, line);
487: cfsym = sp;
488: cflab = newlab();
489: if (s != LBRACE)
490: cerror("compound statement required");
491: else
492: lex();
493: llex = LL_AUTO;
494: locals();
495: putautos();
496: while (s!=EOF && s!=RBRACE)
497: statement();
498: if (s != RBRACE)
499: cerror("missing right brace");
500: llex = LL_EXT;
501: downlex();
502: label(cflab);
503: dbstat(RBRACE, line);
504: bput(EPILOG);
505: cfsym = NULL;
506: }
507:
508: /*
509: * Emit an external label.
510: */
511: xlabel(sp)
512: register SYM *sp;
513: {
514: bput((sp->s_class==C_GDEF) ? GLABEL : SLABEL);
515: nput(sp->s_id);
516: }
517:
518: /*
519: * Conditionally drop a structure information block.
520: * Sometimes a non null info pointer is a symbol table pointer!
521: */
522: xdropinfo(t, ip)
523: register int t;
524: register INFO *ip;
525: {
526: if (t==T_FSTRUCT || t==T_FUNION || t==T_FENUM)
527: return;
528: dropinfo(ip);
529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.