#include "cc.h"#include "y.tab.h" #ifndef CPP#define CPP "/bin/cpp"#endif /* * known debug flags * -o file output file * -D name define * -I path include * -a acid declaration output * -M constant multiplication * -B non ANSI * -A !B * -d print declarations * -t print type trees * -L print every NAME symbol * -i print initialization * -F format specification check * -r print registerization * -v verbose printing * -X abort on error * -w print warnings * -m print add/sub/mul trees * -s print structure offsets (with -a or -aa) * -n print acid to file (%.c=%.acid) (with -a or -aa) * -p use standard cpp ANSI preprocessor (not on windows) * -V enable void* conversion warnings */ voidmain(int argc, char *argv[]){ char *defs[50], *p; int nproc, nout, status, i, c, ndef; memset(debug, 0, sizeof(debug)); tinit(); cinit(); ginit(); arginit(); profileflg = 1; /* #pragma can turn it off */ tufield = simplet((1L<<tfield->etype) | BUNSIGNED); ndef = 0; outfile = 0; include[ninclude++] = "."; ARGBEGIN { default: c = ARGC(); if(c >= 0 && c < sizeof(debug)) debug[c]++; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) { defs[ndef++] = p; dodefine(p); } break; case 'I': p = ARGF(); setinclude(p); break; } ARGEND if(argc < 1 && outfile == 0) { print("usage: %cc [-options] files\n", thechar); errorexit(); } if(argc > 1 && systemtype(Windows)){ print("can't compile multiple files on windows\n"); errorexit(); } if(argc > 1 && !systemtype(Windows)) { nproc = 1; if(p = getenv("NPROC")) nproc = atol(p); /* */ c = 0; nout = 0; for(;;) { while(nout < nproc && argc > 0) { i = myfork(); if(i < 0) { i = mywait(&status); if(i < 0) { print("cannot create a process\n"); errorexit(); } if(status) c++; nout--; continue; } if(i == 0) { fprint(2, "%s:\n", *argv); if (compile(*argv, defs, ndef)) errorexit(); exits(0); } nout++; argc--; argv++; } i = mywait(&status); if(i < 0) { if(c) errorexit(); exits(0); } if(status) c++; nout--; } } if(argc == 0) c = compile("stdin", defs, ndef); else c = compile(argv[0], defs, ndef); if(c) errorexit(); exits(0);} intcompile(char *file, char **defs, int ndef){ char ofile[400], incfile[20]; char *p, *av[100], opt[256]; int i, c, fd[2]; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { *p++ = 0; if(!debug['.']) include[0] = strdup(ofile); } else p = ofile; if(outfile == 0) { outfile = p; if(outfile) { if(p = utfrrune(outfile, '.')) if(p[1] == 'c' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); if(debug['a'] && debug['n']) strcat(p, ".acid"); else if(debug['Z'] && debug['n']) strcat(p, "_pickle.c"); else { p[0] = '.'; p[1] = thechar; p[2] = 0; } } else outfile = "/dev/null"; } if(p = getenv("INCLUDE")) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile, "/%s/include", thestring); setinclude(strdup(incfile)); setinclude("/sys/include"); } } if((debug['a'] || debug['Z']) && !debug['n']) { outfile = 0; Binit(&outbuf, 1, OWRITE); Binit(&diagbuf, 2, OWRITE); } else { c = mycreat(outfile, 0664); if(c < 0) { diag(Z, "cannot open %s", outfile); outfile = 0; errorexit(); } Binit(&outbuf, c, OWRITE); Binit(&diagbuf, 1, OWRITE); } newio(); /* Use an ANSI preprocessor */ if(debug['p']) { if(systemtype(Windows)) { diag(Z, "-p option not supported on windows"); errorexit(); } if(myaccess(file) < 0) { diag(Z, "%s does not exist", file); errorexit(); } if(mypipe(fd) < 0) { diag(Z, "pipe failed"); errorexit(); } switch(myfork()) { case -1: diag(Z, "fork failed"); errorexit(); case 0: close(fd[0]); mydup(fd[1], 1); close(fd[1]); av[0] = CPP; i = 1; if(debug['+']) { sprint(opt, "-+"); av[i++] = strdup(opt); } for(c = 0; c < ndef; c++) { sprint(opt, "-D%s", defs[c]); av[i++] = strdup(opt); } for(c = 0; c < ninclude; c++) { sprint(opt, "-I%s", include[c]); av[i++] = strdup(opt); } if(strcmp(file, "stdin") != 0) av[i++] = file; av[i] = 0; if(debug['p'] > 1) { for(c = 0; c < i; c++) fprint(2, "%s ", av[c]); fprint(2, "\n"); } myexec(av[0], av); fprint(2, "can't exec C preprocessor %s: %r\n", CPP); errorexit(); default: close(fd[1]); newfile(file, fd[0]); break; } } else { if(strcmp(file, "stdin") == 0) newfile(file, 0); else newfile(file, -1); } yyparse(); if(!debug['a'] && !debug['Z']) gclean(); return nerrors;} voiderrorexit(void){ if(outfile) remove(outfile); exits("error");} voidpushio(void){ Io *i; i = iostack; if(i == I) { yyerror("botch in pushio"); errorexit(); } i->p = fi.p; i->c = fi.c;} voidnewio(void){ Io *i; static int pushdepth = 0; i = iofree; if(i == I) { pushdepth++; if(pushdepth > 1000) { yyerror("macro/io expansion too deep"); errorexit(); } i = alloc(sizeof(*i)); } else iofree = i->link; i->c = 0; i->f = -1; ionext = i;} voidnewfile(char *s, int f){ Io *i; if(debug['e']) print("%L: %s\n", lineno, s); i = ionext; i->link = iostack; iostack = i; i->f = f; if(f < 0) i->f = open(s, 0); if(i->f < 0) { yyerror("%cc: %r: %s", thechar, s); errorexit(); } fi.c = 0; linehist(s, 0);} Sym*slookup(char *s){ strcpy(symb, s); return lookup();} Sym*lookup(void){ Sym *s; ulong h; char *p; int c, n; h = 0; for(p=symb; *p;) { h = h * 3; h += *p++; } n = (p - symb) + 1; if((long)h < 0) h = ~h; h %= NHASH; c = symb[0]; for(s = hash[h]; s != S; s = s->link) { if(s->name[0] != c) continue; if(strcmp(s->name, symb) == 0) return s; } s = alloc(sizeof(*s)); s->name = alloc(n); memmove(s->name, symb, n); strcpy(s->name, symb); s->link = hash[h]; hash[h] = s; syminit(s); return s;} voidsyminit(Sym *s){ s->lexical = LNAME; s->block = 0; s->offset = 0; s->type = T; s->suetag = T; s->class = CXXX; s->aused = 0; s->sig = SIGNONE;} #define EOF (-1)#define IGN (-2)#define ESC (1<<20)#define GETC() ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)) enum{ Numdec = 1<<0, Numlong = 1<<1, Numuns = 1<<2, Numvlong = 1<<3, Numflt = 1<<4,}; longyylex(void){ vlong vv; long c, c1, t; char *cp; Rune rune; Sym *s; if(peekc != IGN) { c = peekc; peekc = IGN; goto l1; }l0: c = GETC(); l1: if(c >= Runeself) { /* * extension -- * all multibyte runes are alpha */ cp = symb; goto talph; } if(isspace(c)) { if(c == '\n') lineno++; goto l0; } if(isalpha(c)) { cp = symb; if(c != 'L') goto talph; *cp++ = c; c = GETC(); if(c == '\'') { /* L'x' */ c = escchar('\'', 1, 0); if(c == EOF) c = '\''; c1 = escchar('\'', 1, 0); if(c1 != EOF) { yyerror("missing '"); peekc = c1; } yylval.vval = convvtox(c, TUSHORT); return LUCONST; } if(c == '"') { goto caselq; } goto talph; } if(isdigit(c)) goto tnum; switch(c) { case EOF: peekc = EOF; return -1; case '_': cp = symb; goto talph; case '#': domacro(); goto l0; case '.': c1 = GETC(); if(isdigit(c1)) { cp = symb; *cp++ = c; c = c1; c1 = 0; goto casedot; } break; case '"': strcpy(symb, "\"<string>\""); cp = alloc(0); c1 = 0; /* "..." */ for(;;) { c = escchar('"', 0, 1); if(c == EOF) break; if(c & ESC) { cp = allocn(cp, c1, 1); cp[c1++] = c; } else { rune = c; c = runelen(rune); cp = allocn(cp, c1, c); runetochar(cp+c1, &rune); c1 += c; } } yylval.sval.l = c1; do { cp = allocn(cp, c1, 1);Lines 1–500 of 1518. Load more
#include "cc.h" #include "y.tab.h" #ifndef CPP #define CPP "/bin/cpp" #endif /* * known debug flags * -o file output file * -D name define * -I path include * -a acid declaration output * -M constant multiplication * -B non ANSI * -A !B * -d print declarations * -t print type trees * -L print every NAME symbol * -i print initialization * -F format specification check * -r print registerization * -v verbose printing * -X abort on error * -w print warnings * -m print add/sub/mul trees * -s print structure offsets (with -a or -aa) * -n print acid to file (%.c=%.acid) (with -a or -aa) * -p use standard cpp ANSI preprocessor (not on windows) * -V enable void* conversion warnings */ void main(int argc, char *argv[]) { char *defs[50], *p; int nproc, nout, status, i, c, ndef; memset(debug, 0, sizeof(debug)); tinit(); cinit(); ginit(); arginit(); profileflg = 1; /* #pragma can turn it off */ tufield = simplet((1L<<tfield->etype) | BUNSIGNED); ndef = 0; outfile = 0; include[ninclude++] = "."; ARGBEGIN { default: c = ARGC(); if(c >= 0 && c < sizeof(debug)) debug[c]++; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) { defs[ndef++] = p; dodefine(p); } break; case 'I': p = ARGF(); setinclude(p); break; } ARGEND if(argc < 1 && outfile == 0) { print("usage: %cc [-options] files\n", thechar); errorexit(); } if(argc > 1 && systemtype(Windows)){ print("can't compile multiple files on windows\n"); errorexit(); } if(argc > 1 && !systemtype(Windows)) { nproc = 1; if(p = getenv("NPROC")) nproc = atol(p); /* */ c = 0; nout = 0; for(;;) { while(nout < nproc && argc > 0) { i = myfork(); if(i < 0) { i = mywait(&status); if(i < 0) { print("cannot create a process\n"); errorexit(); } if(status) c++; nout--; continue; } if(i == 0) { fprint(2, "%s:\n", *argv); if (compile(*argv, defs, ndef)) errorexit(); exits(0); } nout++; argc--; argv++; } i = mywait(&status); if(i < 0) { if(c) errorexit(); exits(0); } if(status) c++; nout--; } } if(argc == 0) c = compile("stdin", defs, ndef); else c = compile(argv[0], defs, ndef); if(c) errorexit(); exits(0); } int compile(char *file, char **defs, int ndef) { char ofile[400], incfile[20]; char *p, *av[100], opt[256]; int i, c, fd[2]; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { *p++ = 0; if(!debug['.']) include[0] = strdup(ofile); } else p = ofile; if(outfile == 0) { outfile = p; if(outfile) { if(p = utfrrune(outfile, '.')) if(p[1] == 'c' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); if(debug['a'] && debug['n']) strcat(p, ".acid"); else if(debug['Z'] && debug['n']) strcat(p, "_pickle.c"); else { p[0] = '.'; p[1] = thechar; p[2] = 0; } } else outfile = "/dev/null"; } if(p = getenv("INCLUDE")) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile, "/%s/include", thestring); setinclude(strdup(incfile)); setinclude("/sys/include"); } } if((debug['a'] || debug['Z']) && !debug['n']) { outfile = 0; Binit(&outbuf, 1, OWRITE); Binit(&diagbuf, 2, OWRITE); } else { c = mycreat(outfile, 0664); if(c < 0) { diag(Z, "cannot open %s", outfile); outfile = 0; errorexit(); } Binit(&outbuf, c, OWRITE); Binit(&diagbuf, 1, OWRITE); } newio(); /* Use an ANSI preprocessor */ if(debug['p']) { if(systemtype(Windows)) { diag(Z, "-p option not supported on windows"); errorexit(); } if(myaccess(file) < 0) { diag(Z, "%s does not exist", file); errorexit(); } if(mypipe(fd) < 0) { diag(Z, "pipe failed"); errorexit(); } switch(myfork()) { case -1: diag(Z, "fork failed"); errorexit(); case 0: close(fd[0]); mydup(fd[1], 1); close(fd[1]); av[0] = CPP; i = 1; if(debug['+']) { sprint(opt, "-+"); av[i++] = strdup(opt); } for(c = 0; c < ndef; c++) { sprint(opt, "-D%s", defs[c]); av[i++] = strdup(opt); } for(c = 0; c < ninclude; c++) { sprint(opt, "-I%s", include[c]); av[i++] = strdup(opt); } if(strcmp(file, "stdin") != 0) av[i++] = file; av[i] = 0; if(debug['p'] > 1) { for(c = 0; c < i; c++) fprint(2, "%s ", av[c]); fprint(2, "\n"); } myexec(av[0], av); fprint(2, "can't exec C preprocessor %s: %r\n", CPP); errorexit(); default: close(fd[1]); newfile(file, fd[0]); break; } } else { if(strcmp(file, "stdin") == 0) newfile(file, 0); else newfile(file, -1); } yyparse(); if(!debug['a'] && !debug['Z']) gclean(); return nerrors; } void errorexit(void) { if(outfile) remove(outfile); exits("error"); } void pushio(void) { Io *i; i = iostack; if(i == I) { yyerror("botch in pushio"); errorexit(); } i->p = fi.p; i->c = fi.c; } void newio(void) { Io *i; static int pushdepth = 0; i = iofree; if(i == I) { pushdepth++; if(pushdepth > 1000) { yyerror("macro/io expansion too deep"); errorexit(); } i = alloc(sizeof(*i)); } else iofree = i->link; i->c = 0; i->f = -1; ionext = i; } void newfile(char *s, int f) { Io *i; if(debug['e']) print("%L: %s\n", lineno, s); i = ionext; i->link = iostack; iostack = i; i->f = f; if(f < 0) i->f = open(s, 0); if(i->f < 0) { yyerror("%cc: %r: %s", thechar, s); errorexit(); } fi.c = 0; linehist(s, 0); } Sym* slookup(char *s) { strcpy(symb, s); return lookup(); } Sym* lookup(void) { Sym *s; ulong h; char *p; int c, n; h = 0; for(p=symb; *p;) { h = h * 3; h += *p++; } n = (p - symb) + 1; if((long)h < 0) h = ~h; h %= NHASH; c = symb[0]; for(s = hash[h]; s != S; s = s->link) { if(s->name[0] != c) continue; if(strcmp(s->name, symb) == 0) return s; } s = alloc(sizeof(*s)); s->name = alloc(n); memmove(s->name, symb, n); strcpy(s->name, symb); s->link = hash[h]; hash[h] = s; syminit(s); return s; } void syminit(Sym *s) { s->lexical = LNAME; s->block = 0; s->offset = 0; s->type = T; s->suetag = T; s->class = CXXX; s->aused = 0; s->sig = SIGNONE; } #define EOF (-1) #define IGN (-2) #define ESC (1<<20) #define GETC() ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)) enum { Numdec = 1<<0, Numlong = 1<<1, Numuns = 1<<2, Numvlong = 1<<3, Numflt = 1<<4, }; long yylex(void) { vlong vv; long c, c1, t; char *cp; Rune rune; Sym *s; if(peekc != IGN) { c = peekc; peekc = IGN; goto l1; } l0: c = GETC(); l1: if(c >= Runeself) { /* * extension -- * all multibyte runes are alpha */ cp = symb; goto talph; } if(isspace(c)) { if(c == '\n') lineno++; goto l0; } if(isalpha(c)) { cp = symb; if(c != 'L') goto talph; *cp++ = c; c = GETC(); if(c == '\'') { /* L'x' */ c = escchar('\'', 1, 0); if(c == EOF) c = '\''; c1 = escchar('\'', 1, 0); if(c1 != EOF) { yyerror("missing '"); peekc = c1; } yylval.vval = convvtox(c, TUSHORT); return LUCONST; } if(c == '"') { goto caselq; } goto talph; } if(isdigit(c)) goto tnum; switch(c) { case EOF: peekc = EOF; return -1; case '_': cp = symb; goto talph; case '#': domacro(); goto l0; case '.': c1 = GETC(); if(isdigit(c1)) { cp = symb; *cp++ = c; c = c1; c1 = 0; goto casedot; } break; case '"': strcpy(symb, "\"<string>\""); cp = alloc(0); c1 = 0; /* "..." */ for(;;) { c = escchar('"', 0, 1); if(c == EOF) break; if(c & ESC) { cp = allocn(cp, c1, 1); cp[c1++] = c; } else { rune = c; c = runelen(rune); cp = allocn(cp, c1, c); runetochar(cp+c1, &rune); c1 += c; } } yylval.sval.l = c1; do { cp = allocn(cp, c1, 1);