13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <stdio.h> 43e12c5d1SDavid du Colombier #include "cpp.h" 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier extern int getopt(int, char **, char *); 73e12c5d1SDavid du Colombier extern char *optarg; 83e12c5d1SDavid du Colombier extern int optind; 93e12c5d1SDavid du Colombier int verbose; 10bd389b36SDavid du Colombier int Mflag; 113e12c5d1SDavid du Colombier int Cplusplus; 127dd7cddfSDavid du Colombier int nolineinfo; 13bd389b36SDavid du Colombier Nlist *kwdefined; 14219b2ee8SDavid du Colombier char wd[128]; 153e12c5d1SDavid du Colombier 163e12c5d1SDavid du Colombier #define NLSIZE 128 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier Nlist *nlist[NLSIZE]; 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier struct kwtab { 213e12c5d1SDavid du Colombier char *kw; 223e12c5d1SDavid du Colombier int val; 233e12c5d1SDavid du Colombier int flag; 243e12c5d1SDavid du Colombier } kwtab[] = { 253e12c5d1SDavid du Colombier "if", KIF, ISKW, 263e12c5d1SDavid du Colombier "ifdef", KIFDEF, ISKW, 273e12c5d1SDavid du Colombier "ifndef", KIFNDEF, ISKW, 283e12c5d1SDavid du Colombier "elif", KELIF, ISKW, 293e12c5d1SDavid du Colombier "else", KELSE, ISKW, 303e12c5d1SDavid du Colombier "endif", KENDIF, ISKW, 313e12c5d1SDavid du Colombier "include", KINCLUDE, ISKW, 323e12c5d1SDavid du Colombier "define", KDEFINE, ISKW, 333e12c5d1SDavid du Colombier "undef", KUNDEF, ISKW, 343e12c5d1SDavid du Colombier "line", KLINE, ISKW, 353e12c5d1SDavid du Colombier "error", KERROR, ISKW, 363e12c5d1SDavid du Colombier "pragma", KPRAGMA, ISKW, 373e12c5d1SDavid du Colombier "eval", KEVAL, ISKW, 38bd389b36SDavid du Colombier "defined", KDEFINED, ISDEFINED+ISUNCHANGE, 393e12c5d1SDavid du Colombier "__LINE__", KLINENO, ISMAC+ISUNCHANGE, 403e12c5d1SDavid du Colombier "__FILE__", KFILE, ISMAC+ISUNCHANGE, 413e12c5d1SDavid du Colombier "__DATE__", KDATE, ISMAC+ISUNCHANGE, 423e12c5d1SDavid du Colombier "__TIME__", KTIME, ISMAC+ISUNCHANGE, 433e12c5d1SDavid du Colombier "__STDC__", KSTDC, ISUNCHANGE, 443e12c5d1SDavid du Colombier NULL 453e12c5d1SDavid du Colombier }; 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier unsigned long namebit[077+1]; 48bd389b36SDavid du Colombier Nlist *np; 493e12c5d1SDavid du Colombier 503e12c5d1SDavid du Colombier void 513e12c5d1SDavid du Colombier setup(int argc, char **argv) 523e12c5d1SDavid du Colombier { 533e12c5d1SDavid du Colombier struct kwtab *kp; 543e12c5d1SDavid du Colombier Nlist *np; 553e12c5d1SDavid du Colombier Token t; 563e12c5d1SDavid du Colombier int fd, i; 573e12c5d1SDavid du Colombier char *fp, *dp; 583e12c5d1SDavid du Colombier Tokenrow tr; 593e12c5d1SDavid du Colombier char *objtype; 607dd7cddfSDavid du Colombier char *includeenv; 617dd7cddfSDavid du Colombier int firstinclude; 623e12c5d1SDavid du Colombier static char nbuf[40]; 63bd389b36SDavid du Colombier static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }}; 64bd389b36SDavid du Colombier static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 }; 657dd7cddfSDavid du Colombier int debuginclude = 0; 667dd7cddfSDavid du Colombier char xx[2] = { 0, 0}; 673e12c5d1SDavid du Colombier 683e12c5d1SDavid du Colombier for (kp=kwtab; kp->kw; kp++) { 693e12c5d1SDavid du Colombier t.t = (uchar*)kp->kw; 703e12c5d1SDavid du Colombier t.len = strlen(kp->kw); 713e12c5d1SDavid du Colombier np = lookup(&t, 1); 723e12c5d1SDavid du Colombier np->flag = kp->flag; 733e12c5d1SDavid du Colombier np->val = kp->val; 74bd389b36SDavid du Colombier if (np->val == KDEFINED) { 75bd389b36SDavid du Colombier kwdefined = np; 76bd389b36SDavid du Colombier np->val = NAME; 77bd389b36SDavid du Colombier np->vp = &deftr; 78bd389b36SDavid du Colombier np->ap = 0; 79bd389b36SDavid du Colombier } 803e12c5d1SDavid du Colombier } 813e12c5d1SDavid du Colombier /* 823e12c5d1SDavid du Colombier * For Plan 9, search /objtype/include, then /sys/include 837dd7cddfSDavid du Colombier * (Note that includelist is searched from high end to low) 843e12c5d1SDavid du Colombier */ 853e12c5d1SDavid du Colombier if ((objtype = getenv("objtype"))){ 86*4d44ba9bSDavid du Colombier snprintf(nbuf, sizeof nbuf, "/%s/include", objtype); 873e12c5d1SDavid du Colombier includelist[1].file = nbuf; 883e12c5d1SDavid du Colombier includelist[1].always = 1; 893e12c5d1SDavid du Colombier } else { 903e12c5d1SDavid du Colombier includelist[1].file = NULL; 913e12c5d1SDavid du Colombier error(WARNING, "Unknown $objtype"); 923e12c5d1SDavid du Colombier } 93219b2ee8SDavid du Colombier if (getwd(wd, sizeof(wd))==0) 94219b2ee8SDavid du Colombier wd[0] = '\0'; 953e12c5d1SDavid du Colombier includelist[0].file = "/sys/include"; 963e12c5d1SDavid du Colombier includelist[0].always = 1; 977dd7cddfSDavid du Colombier firstinclude = NINCLUDE-2; 987dd7cddfSDavid du Colombier if ((includeenv=getenv("include")) != NULL) { 997dd7cddfSDavid du Colombier char *cp; 1007dd7cddfSDavid du Colombier includeenv = strdup(includeenv); 1017dd7cddfSDavid du Colombier for (;firstinclude>0; firstinclude--) { 1027dd7cddfSDavid du Colombier cp = strtok(includeenv, " "); 1037dd7cddfSDavid du Colombier if (cp==NULL) 1047dd7cddfSDavid du Colombier break; 1057dd7cddfSDavid du Colombier includelist[firstinclude].file = cp; 1067dd7cddfSDavid du Colombier includelist[firstinclude].always = 1; 1077dd7cddfSDavid du Colombier includeenv = NULL; 1087dd7cddfSDavid du Colombier } 1097dd7cddfSDavid du Colombier } 1103e12c5d1SDavid du Colombier setsource("", -1, 0); 1113e12c5d1SDavid du Colombier ARGBEGIN { 1123e12c5d1SDavid du Colombier case 'N': 1133e12c5d1SDavid du Colombier for (i=0; i<NINCLUDE; i++) 1143e12c5d1SDavid du Colombier if (includelist[i].always==1) 1153e12c5d1SDavid du Colombier includelist[i].deleted = 1; 1163e12c5d1SDavid du Colombier break; 1173e12c5d1SDavid du Colombier case 'I': 1187dd7cddfSDavid du Colombier for (i=firstinclude; i>=0; i--) { 1193e12c5d1SDavid du Colombier if (includelist[i].file==NULL) { 1203e12c5d1SDavid du Colombier includelist[i].always = 1; 1213e12c5d1SDavid du Colombier includelist[i].file = ARGF(); 1223e12c5d1SDavid du Colombier break; 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier } 1253e12c5d1SDavid du Colombier if (i<0) 1267dd7cddfSDavid du Colombier error(WARNING, "Too many -I directives"); 1273e12c5d1SDavid du Colombier break; 1283e12c5d1SDavid du Colombier case 'D': 1293e12c5d1SDavid du Colombier case 'U': 1303e12c5d1SDavid du Colombier setsource("<cmdarg>", -1, ARGF()); 1313e12c5d1SDavid du Colombier maketokenrow(3, &tr); 1323e12c5d1SDavid du Colombier gettokens(&tr, 1); 1333e12c5d1SDavid du Colombier doadefine(&tr, ARGC()); 1343e12c5d1SDavid du Colombier unsetsource(); 1353e12c5d1SDavid du Colombier break; 136bd389b36SDavid du Colombier case 'M': 137bd389b36SDavid du Colombier Mflag++; 138bd389b36SDavid du Colombier break; 1393e12c5d1SDavid du Colombier case 'V': 1403e12c5d1SDavid du Colombier verbose++; 1413e12c5d1SDavid du Colombier break; 1423e12c5d1SDavid du Colombier case '+': 1433e12c5d1SDavid du Colombier Cplusplus++; 1443e12c5d1SDavid du Colombier break; 1457dd7cddfSDavid du Colombier case 'i': 1467dd7cddfSDavid du Colombier debuginclude++; 1477dd7cddfSDavid du Colombier break; 1487dd7cddfSDavid du Colombier case 'P': 1497dd7cddfSDavid du Colombier nolineinfo++; 150219b2ee8SDavid du Colombier break; 1513e12c5d1SDavid du Colombier default: 1527dd7cddfSDavid du Colombier xx[0] = ARGC(); 1537dd7cddfSDavid du Colombier error(FATAL, "Unknown argument '%s'", xx); 1543e12c5d1SDavid du Colombier break; 1553e12c5d1SDavid du Colombier } ARGEND 1563e12c5d1SDavid du Colombier dp = "."; 1573e12c5d1SDavid du Colombier fp = "<stdin>"; 1583e12c5d1SDavid du Colombier fd = 0; 1593e12c5d1SDavid du Colombier if (argc > 0) { 1603e12c5d1SDavid du Colombier if ((fp = strrchr(argv[0], '/')) != NULL) { 1613e12c5d1SDavid du Colombier int len = fp - argv[0]; 1623e12c5d1SDavid du Colombier dp = (char*)newstring((uchar*)argv[0], len+1, 0); 1633e12c5d1SDavid du Colombier dp[len] = '\0'; 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0); 1663e12c5d1SDavid du Colombier if ((fd = open(fp, 0)) <= 0) 1673e12c5d1SDavid du Colombier error(FATAL, "Can't open input file %s", fp); 1683e12c5d1SDavid du Colombier } 1693e12c5d1SDavid du Colombier if (argc > 1) { 1703e12c5d1SDavid du Colombier int fdo = create(argv[1], 1, 0666); 1713e12c5d1SDavid du Colombier if (fdo<0) 1723e12c5d1SDavid du Colombier error(FATAL, "Can't open output file %s", argv[1]); 1733e12c5d1SDavid du Colombier dup(fdo, 1); 1743e12c5d1SDavid du Colombier } 175bd389b36SDavid du Colombier if (Mflag) 176bd389b36SDavid du Colombier setobjname(fp); 1773e12c5d1SDavid du Colombier includelist[NINCLUDE-1].always = 0; 1783e12c5d1SDavid du Colombier includelist[NINCLUDE-1].file = dp; 1793e12c5d1SDavid du Colombier setsource(fp, fd, NULL); 1807dd7cddfSDavid du Colombier if (debuginclude) { 1817dd7cddfSDavid du Colombier for (i=0; i<NINCLUDE; i++) 1827dd7cddfSDavid du Colombier if (includelist[i].file && includelist[i].deleted==0) 1837dd7cddfSDavid du Colombier error(WARNING, "Include: %s", includelist[i].file); 1847dd7cddfSDavid du Colombier } 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier Nlist * 1883e12c5d1SDavid du Colombier lookup(Token *tp, int install) 1893e12c5d1SDavid du Colombier { 1903e12c5d1SDavid du Colombier unsigned int h; 1913e12c5d1SDavid du Colombier Nlist *np; 1923e12c5d1SDavid du Colombier uchar *cp, *cpe; 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier h = 0; 1953e12c5d1SDavid du Colombier for (cp=tp->t, cpe=cp+tp->len; cp<cpe; ) 1963e12c5d1SDavid du Colombier h += *cp++; 1973e12c5d1SDavid du Colombier h %= NLSIZE; 1983e12c5d1SDavid du Colombier np = nlist[h]; 1993e12c5d1SDavid du Colombier while (np) { 2003e12c5d1SDavid du Colombier if (*tp->t==*np->name && tp->len==np->len 2013e12c5d1SDavid du Colombier && strncmp((char*)tp->t, (char*)np->name, tp->len)==0) 2023e12c5d1SDavid du Colombier return np; 2033e12c5d1SDavid du Colombier np = np->next; 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier if (install) { 2063e12c5d1SDavid du Colombier np = new(Nlist); 207219b2ee8SDavid du Colombier np->val = 0; 2083e12c5d1SDavid du Colombier np->vp = NULL; 2093e12c5d1SDavid du Colombier np->ap = NULL; 2103e12c5d1SDavid du Colombier np->flag = 0; 2113e12c5d1SDavid du Colombier np->len = tp->len; 2123e12c5d1SDavid du Colombier np->name = newstring(tp->t, tp->len, 0); 2133e12c5d1SDavid du Colombier np->next = nlist[h]; 2143e12c5d1SDavid du Colombier nlist[h] = np; 2153e12c5d1SDavid du Colombier quickset(tp->t[0], tp->len>1? tp->t[1]:0); 2163e12c5d1SDavid du Colombier return np; 2173e12c5d1SDavid du Colombier } 2183e12c5d1SDavid du Colombier return NULL; 2193e12c5d1SDavid du Colombier } 220