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