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,
36ad1af469SDavid du Colombier "warning", KWARNING, ISKW, // extension to ANSI
373e12c5d1SDavid du Colombier "pragma", KPRAGMA, ISKW,
383e12c5d1SDavid du Colombier "eval", KEVAL, ISKW,
39bd389b36SDavid du Colombier "defined", KDEFINED, ISDEFINED+ISUNCHANGE,
403e12c5d1SDavid du Colombier "__LINE__", KLINENO, ISMAC+ISUNCHANGE,
413e12c5d1SDavid du Colombier "__FILE__", KFILE, ISMAC+ISUNCHANGE,
423e12c5d1SDavid du Colombier "__DATE__", KDATE, ISMAC+ISUNCHANGE,
433e12c5d1SDavid du Colombier "__TIME__", KTIME, ISMAC+ISUNCHANGE,
443e12c5d1SDavid du Colombier "__STDC__", KSTDC, ISUNCHANGE,
453e12c5d1SDavid du Colombier NULL
463e12c5d1SDavid du Colombier };
473e12c5d1SDavid du Colombier
483e12c5d1SDavid du Colombier unsigned long namebit[077+1];
49bd389b36SDavid du Colombier Nlist *np;
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier void
setup(int argc,char ** argv)523e12c5d1SDavid du Colombier setup(int argc, char **argv)
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier struct kwtab *kp;
553e12c5d1SDavid du Colombier Nlist *np;
563e12c5d1SDavid du Colombier Token t;
573e12c5d1SDavid du Colombier int fd, i;
583e12c5d1SDavid du Colombier char *fp, *dp;
593e12c5d1SDavid du Colombier Tokenrow tr;
603e12c5d1SDavid du Colombier char *objtype;
617dd7cddfSDavid du Colombier char *includeenv;
627dd7cddfSDavid du Colombier int firstinclude;
633e12c5d1SDavid du Colombier static char nbuf[40];
64bd389b36SDavid du Colombier static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
65bd389b36SDavid du Colombier static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
667dd7cddfSDavid du Colombier int debuginclude = 0;
678deabd96SDavid du Colombier int nodot = 0;
687dd7cddfSDavid du Colombier char xx[2] = { 0, 0};
693e12c5d1SDavid du Colombier
703e12c5d1SDavid du Colombier for (kp=kwtab; kp->kw; kp++) {
713e12c5d1SDavid du Colombier t.t = (uchar*)kp->kw;
723e12c5d1SDavid du Colombier t.len = strlen(kp->kw);
733e12c5d1SDavid du Colombier np = lookup(&t, 1);
743e12c5d1SDavid du Colombier np->flag = kp->flag;
753e12c5d1SDavid du Colombier np->val = kp->val;
76bd389b36SDavid du Colombier if (np->val == KDEFINED) {
77bd389b36SDavid du Colombier kwdefined = np;
78bd389b36SDavid du Colombier np->val = NAME;
79bd389b36SDavid du Colombier np->vp = &deftr;
80bd389b36SDavid du Colombier np->ap = 0;
81bd389b36SDavid du Colombier }
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier /*
843e12c5d1SDavid du Colombier * For Plan 9, search /objtype/include, then /sys/include
857dd7cddfSDavid du Colombier * (Note that includelist is searched from high end to low)
863e12c5d1SDavid du Colombier */
873e12c5d1SDavid du Colombier if ((objtype = getenv("objtype"))){
884d44ba9bSDavid du Colombier snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
893e12c5d1SDavid du Colombier includelist[1].file = nbuf;
903e12c5d1SDavid du Colombier includelist[1].always = 1;
913e12c5d1SDavid du Colombier } else {
923e12c5d1SDavid du Colombier includelist[1].file = NULL;
933e12c5d1SDavid du Colombier error(WARNING, "Unknown $objtype");
943e12c5d1SDavid du Colombier }
95219b2ee8SDavid du Colombier if (getwd(wd, sizeof(wd))==0)
96219b2ee8SDavid du Colombier wd[0] = '\0';
973e12c5d1SDavid du Colombier includelist[0].file = "/sys/include";
983e12c5d1SDavid du Colombier includelist[0].always = 1;
997dd7cddfSDavid du Colombier firstinclude = NINCLUDE-2;
1007dd7cddfSDavid du Colombier if ((includeenv=getenv("include")) != NULL) {
1017dd7cddfSDavid du Colombier char *cp;
1027dd7cddfSDavid du Colombier includeenv = strdup(includeenv);
1037dd7cddfSDavid du Colombier for (;firstinclude>0; firstinclude--) {
1047dd7cddfSDavid du Colombier cp = strtok(includeenv, " ");
1057dd7cddfSDavid du Colombier if (cp==NULL)
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier includelist[firstinclude].file = cp;
1087dd7cddfSDavid du Colombier includelist[firstinclude].always = 1;
1097dd7cddfSDavid du Colombier includeenv = NULL;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier }
1123e12c5d1SDavid du Colombier setsource("", -1, 0);
1133e12c5d1SDavid du Colombier ARGBEGIN {
1143e12c5d1SDavid du Colombier case 'N':
1153e12c5d1SDavid du Colombier for (i=0; i<NINCLUDE; i++)
1163e12c5d1SDavid du Colombier if (includelist[i].always==1)
1173e12c5d1SDavid du Colombier includelist[i].deleted = 1;
1183e12c5d1SDavid du Colombier break;
1193e12c5d1SDavid du Colombier case 'I':
1207dd7cddfSDavid du Colombier for (i=firstinclude; i>=0; i--) {
1213e12c5d1SDavid du Colombier if (includelist[i].file==NULL) {
1223e12c5d1SDavid du Colombier includelist[i].always = 1;
1233e12c5d1SDavid du Colombier includelist[i].file = ARGF();
1243e12c5d1SDavid du Colombier break;
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier }
1273e12c5d1SDavid du Colombier if (i<0)
1287dd7cddfSDavid du Colombier error(WARNING, "Too many -I directives");
1293e12c5d1SDavid du Colombier break;
1303e12c5d1SDavid du Colombier case 'D':
1313e12c5d1SDavid du Colombier case 'U':
1323e12c5d1SDavid du Colombier setsource("<cmdarg>", -1, ARGF());
1333e12c5d1SDavid du Colombier maketokenrow(3, &tr);
1343e12c5d1SDavid du Colombier gettokens(&tr, 1);
1353e12c5d1SDavid du Colombier doadefine(&tr, ARGC());
1363e12c5d1SDavid du Colombier unsetsource();
1373e12c5d1SDavid du Colombier break;
138bd389b36SDavid du Colombier case 'M':
139bd389b36SDavid du Colombier Mflag++;
140bd389b36SDavid du Colombier break;
1413e12c5d1SDavid du Colombier case 'V':
1423e12c5d1SDavid du Colombier verbose++;
1433e12c5d1SDavid du Colombier break;
1443e12c5d1SDavid du Colombier case '+':
1453e12c5d1SDavid du Colombier Cplusplus++;
1463e12c5d1SDavid du Colombier break;
1477dd7cddfSDavid du Colombier case 'i':
1487dd7cddfSDavid du Colombier debuginclude++;
1497dd7cddfSDavid du Colombier break;
1507dd7cddfSDavid du Colombier case 'P':
1517dd7cddfSDavid du Colombier nolineinfo++;
152219b2ee8SDavid du Colombier break;
1538deabd96SDavid du Colombier case '.':
1548deabd96SDavid du Colombier nodot++;
1558deabd96SDavid du Colombier break;
1563e12c5d1SDavid du Colombier default:
1577dd7cddfSDavid du Colombier xx[0] = ARGC();
1587dd7cddfSDavid du Colombier error(FATAL, "Unknown argument '%s'", xx);
1593e12c5d1SDavid du Colombier break;
1603e12c5d1SDavid du Colombier } ARGEND
1613e12c5d1SDavid du Colombier dp = ".";
1623e12c5d1SDavid du Colombier fp = "<stdin>";
1633e12c5d1SDavid du Colombier fd = 0;
1640b04b1f8SDavid du Colombier if (argc > 2)
1650b04b1f8SDavid du Colombier error(FATAL, "Too many file arguments; see cpp(1)");
1663e12c5d1SDavid du Colombier if (argc > 0) {
1673e12c5d1SDavid du Colombier if ((fp = strrchr(argv[0], '/')) != NULL) {
1683e12c5d1SDavid du Colombier int len = fp - argv[0];
1693e12c5d1SDavid du Colombier dp = (char*)newstring((uchar*)argv[0], len+1, 0);
1703e12c5d1SDavid du Colombier dp[len] = '\0';
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
173*401314a3SDavid du Colombier if ((fd = open(fp, 0)) < 0)
1743e12c5d1SDavid du Colombier error(FATAL, "Can't open input file %s", fp);
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier if (argc > 1) {
1773e12c5d1SDavid du Colombier int fdo = create(argv[1], 1, 0666);
1783e12c5d1SDavid du Colombier if (fdo<0)
1793e12c5d1SDavid du Colombier error(FATAL, "Can't open output file %s", argv[1]);
1803e12c5d1SDavid du Colombier dup(fdo, 1);
1813e12c5d1SDavid du Colombier }
182bd389b36SDavid du Colombier if (Mflag)
183bd389b36SDavid du Colombier setobjname(fp);
1843e12c5d1SDavid du Colombier includelist[NINCLUDE-1].always = 0;
1853e12c5d1SDavid du Colombier includelist[NINCLUDE-1].file = dp;
1868deabd96SDavid du Colombier if(nodot)
1878deabd96SDavid du Colombier includelist[NINCLUDE-1].deleted = 1;
1883e12c5d1SDavid du Colombier setsource(fp, fd, NULL);
1897dd7cddfSDavid du Colombier if (debuginclude) {
1907dd7cddfSDavid du Colombier for (i=0; i<NINCLUDE; i++)
1917dd7cddfSDavid du Colombier if (includelist[i].file && includelist[i].deleted==0)
1927dd7cddfSDavid du Colombier error(WARNING, "Include: %s", includelist[i].file);
1937dd7cddfSDavid du Colombier }
1943e12c5d1SDavid du Colombier }
1953e12c5d1SDavid du Colombier
1963e12c5d1SDavid du Colombier Nlist *
lookup(Token * tp,int install)1973e12c5d1SDavid du Colombier lookup(Token *tp, int install)
1983e12c5d1SDavid du Colombier {
1993e12c5d1SDavid du Colombier unsigned int h;
2003e12c5d1SDavid du Colombier Nlist *np;
2013e12c5d1SDavid du Colombier uchar *cp, *cpe;
2023e12c5d1SDavid du Colombier
2033e12c5d1SDavid du Colombier h = 0;
2043e12c5d1SDavid du Colombier for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
2053e12c5d1SDavid du Colombier h += *cp++;
2063e12c5d1SDavid du Colombier h %= NLSIZE;
2073e12c5d1SDavid du Colombier np = nlist[h];
2083e12c5d1SDavid du Colombier while (np) {
2093e12c5d1SDavid du Colombier if (*tp->t==*np->name && tp->len==np->len
2103e12c5d1SDavid du Colombier && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
2113e12c5d1SDavid du Colombier return np;
2123e12c5d1SDavid du Colombier np = np->next;
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier if (install) {
2153e12c5d1SDavid du Colombier np = new(Nlist);
216219b2ee8SDavid du Colombier np->val = 0;
2173e12c5d1SDavid du Colombier np->vp = NULL;
2183e12c5d1SDavid du Colombier np->ap = NULL;
2193e12c5d1SDavid du Colombier np->flag = 0;
2203e12c5d1SDavid du Colombier np->len = tp->len;
2213e12c5d1SDavid du Colombier np->name = newstring(tp->t, tp->len, 0);
2223e12c5d1SDavid du Colombier np->next = nlist[h];
2233e12c5d1SDavid du Colombier nlist[h] = np;
2243e12c5d1SDavid du Colombier quickset(tp->t[0], tp->len>1? tp->t[1]:0);
2253e12c5d1SDavid du Colombier return np;
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier return NULL;
2283e12c5d1SDavid du Colombier }
229