1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
4 #include "cpp.h"
5
6 extern int getopt(int, char **, char *);
7 extern char *optarg;
8 extern int optind;
9 int verbose;
10 int Mflag;
11 int Cplusplus;
12 int nolineinfo;
13 Nlist *kwdefined;
14 char wd[128];
15
16 #define NLSIZE 128
17
18 Nlist *nlist[NLSIZE];
19
20 struct kwtab {
21 char *kw;
22 int val;
23 int flag;
24 } kwtab[] = {
25 "if", KIF, ISKW,
26 "ifdef", KIFDEF, ISKW,
27 "ifndef", KIFNDEF, ISKW,
28 "elif", KELIF, ISKW,
29 "else", KELSE, ISKW,
30 "endif", KENDIF, ISKW,
31 "include", KINCLUDE, ISKW,
32 "define", KDEFINE, ISKW,
33 "undef", KUNDEF, ISKW,
34 "line", KLINE, ISKW,
35 "error", KERROR, ISKW,
36 "warning", KWARNING, ISKW, // extension to ANSI
37 "pragma", KPRAGMA, ISKW,
38 "eval", KEVAL, ISKW,
39 "defined", KDEFINED, ISDEFINED+ISUNCHANGE,
40 "__LINE__", KLINENO, ISMAC+ISUNCHANGE,
41 "__FILE__", KFILE, ISMAC+ISUNCHANGE,
42 "__DATE__", KDATE, ISMAC+ISUNCHANGE,
43 "__TIME__", KTIME, ISMAC+ISUNCHANGE,
44 "__STDC__", KSTDC, ISUNCHANGE,
45 NULL
46 };
47
48 unsigned long namebit[077+1];
49 Nlist *np;
50
51 void
setup(int argc,char ** argv)52 setup(int argc, char **argv)
53 {
54 struct kwtab *kp;
55 Nlist *np;
56 Token t;
57 int fd, i;
58 char *fp, *dp;
59 Tokenrow tr;
60 char *objtype;
61 char *includeenv;
62 int firstinclude;
63 static char nbuf[40];
64 static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
65 static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
66 int debuginclude = 0;
67 int nodot = 0;
68 char xx[2] = { 0, 0};
69
70 for (kp=kwtab; kp->kw; kp++) {
71 t.t = (uchar*)kp->kw;
72 t.len = strlen(kp->kw);
73 np = lookup(&t, 1);
74 np->flag = kp->flag;
75 np->val = kp->val;
76 if (np->val == KDEFINED) {
77 kwdefined = np;
78 np->val = NAME;
79 np->vp = &deftr;
80 np->ap = 0;
81 }
82 }
83 /*
84 * For Plan 9, search /objtype/include, then /sys/include
85 * (Note that includelist is searched from high end to low)
86 */
87 if ((objtype = getenv("objtype"))){
88 snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
89 includelist[1].file = nbuf;
90 includelist[1].always = 1;
91 } else {
92 includelist[1].file = NULL;
93 error(WARNING, "Unknown $objtype");
94 }
95 if (getwd(wd, sizeof(wd))==0)
96 wd[0] = '\0';
97 includelist[0].file = "/sys/include";
98 includelist[0].always = 1;
99 firstinclude = NINCLUDE-2;
100 if ((includeenv=getenv("include")) != NULL) {
101 char *cp;
102 includeenv = strdup(includeenv);
103 for (;firstinclude>0; firstinclude--) {
104 cp = strtok(includeenv, " ");
105 if (cp==NULL)
106 break;
107 includelist[firstinclude].file = cp;
108 includelist[firstinclude].always = 1;
109 includeenv = NULL;
110 }
111 }
112 setsource("", -1, 0);
113 ARGBEGIN {
114 case 'N':
115 for (i=0; i<NINCLUDE; i++)
116 if (includelist[i].always==1)
117 includelist[i].deleted = 1;
118 break;
119 case 'I':
120 for (i=firstinclude; i>=0; i--) {
121 if (includelist[i].file==NULL) {
122 includelist[i].always = 1;
123 includelist[i].file = ARGF();
124 break;
125 }
126 }
127 if (i<0)
128 error(WARNING, "Too many -I directives");
129 break;
130 case 'D':
131 case 'U':
132 setsource("<cmdarg>", -1, ARGF());
133 maketokenrow(3, &tr);
134 gettokens(&tr, 1);
135 doadefine(&tr, ARGC());
136 unsetsource();
137 break;
138 case 'M':
139 Mflag++;
140 break;
141 case 'V':
142 verbose++;
143 break;
144 case '+':
145 Cplusplus++;
146 break;
147 case 'i':
148 debuginclude++;
149 break;
150 case 'P':
151 nolineinfo++;
152 break;
153 case '.':
154 nodot++;
155 break;
156 default:
157 xx[0] = ARGC();
158 error(FATAL, "Unknown argument '%s'", xx);
159 break;
160 } ARGEND
161 dp = ".";
162 fp = "<stdin>";
163 fd = 0;
164 if (argc > 2)
165 error(FATAL, "Too many file arguments; see cpp(1)");
166 if (argc > 0) {
167 if ((fp = strrchr(argv[0], '/')) != NULL) {
168 int len = fp - argv[0];
169 dp = (char*)newstring((uchar*)argv[0], len+1, 0);
170 dp[len] = '\0';
171 }
172 fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
173 if ((fd = open(fp, 0)) < 0)
174 error(FATAL, "Can't open input file %s", fp);
175 }
176 if (argc > 1) {
177 int fdo = create(argv[1], 1, 0666);
178 if (fdo<0)
179 error(FATAL, "Can't open output file %s", argv[1]);
180 dup(fdo, 1);
181 }
182 if (Mflag)
183 setobjname(fp);
184 includelist[NINCLUDE-1].always = 0;
185 includelist[NINCLUDE-1].file = dp;
186 if(nodot)
187 includelist[NINCLUDE-1].deleted = 1;
188 setsource(fp, fd, NULL);
189 if (debuginclude) {
190 for (i=0; i<NINCLUDE; i++)
191 if (includelist[i].file && includelist[i].deleted==0)
192 error(WARNING, "Include: %s", includelist[i].file);
193 }
194 }
195
196 Nlist *
lookup(Token * tp,int install)197 lookup(Token *tp, int install)
198 {
199 unsigned int h;
200 Nlist *np;
201 uchar *cp, *cpe;
202
203 h = 0;
204 for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
205 h += *cp++;
206 h %= NLSIZE;
207 np = nlist[h];
208 while (np) {
209 if (*tp->t==*np->name && tp->len==np->len
210 && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
211 return np;
212 np = np->next;
213 }
214 if (install) {
215 np = new(Nlist);
216 np->val = 0;
217 np->vp = NULL;
218 np->ap = NULL;
219 np->flag = 0;
220 np->len = tp->len;
221 np->name = newstring(tp->t, tp->len, 0);
222 np->next = nlist[h];
223 nlist[h] = np;
224 quickset(tp->t[0], tp->len>1? tp->t[1]:0);
225 return np;
226 }
227 return NULL;
228 }
229