1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*34f9b3eeSRoland Mainz * Copyright (c) 1986-2009 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * Glenn Fowler
23da2e3ebdSchin * AT&T Research
24da2e3ebdSchin *
25da2e3ebdSchin * preprocessor library control interface
26da2e3ebdSchin */
27da2e3ebdSchin
28da2e3ebdSchin #include "pplib.h"
29da2e3ebdSchin #include "pptab.h"
30da2e3ebdSchin
31da2e3ebdSchin #include <ls.h>
32da2e3ebdSchin
33da2e3ebdSchin #define REFONE (pp.truncate?(Hash_table_t*)0:pp.symtab)
34da2e3ebdSchin #define REFALL (pp.truncate?pp.dirtab:pp.symtab)
35da2e3ebdSchin
36da2e3ebdSchin #define ppiskey(t,v,p) (p=t,v>=p->value&&value<=(p+elementsof(t)-2)->value)
37da2e3ebdSchin
38da2e3ebdSchin /*
39da2e3ebdSchin * set option value
40da2e3ebdSchin * initialization files have lowest precedence
41da2e3ebdSchin */
42da2e3ebdSchin
43da2e3ebdSchin static void
set(register long * p,register long op,int val)44da2e3ebdSchin set(register long* p, register long op, int val)
45da2e3ebdSchin {
46da2e3ebdSchin long* r;
47da2e3ebdSchin
48da2e3ebdSchin r = p == &pp.state ? &pp.ro_state : p == &pp.mode ? &pp.ro_mode : &pp.ro_option;
49da2e3ebdSchin if (!(pp.mode & INIT) || !(pp.in->type == IN_FILE) || !(*r & op))
50da2e3ebdSchin {
51da2e3ebdSchin if (!pp.initialized && !(pp.mode & INIT))
52da2e3ebdSchin *r |= op;
53da2e3ebdSchin if (val)
54da2e3ebdSchin *p |= op;
55da2e3ebdSchin else
56da2e3ebdSchin *p &= ~op;
57da2e3ebdSchin }
58da2e3ebdSchin debug((-7, "set(%s)=%s", p == &pp.state ? "state" : p == &pp.mode ? "mode" : "option", p == &pp.state ? ppstatestr(*p) : p == &pp.mode ? ppmodestr(*p) : ppoptionstr(*p)));
59da2e3ebdSchin }
60da2e3ebdSchin
61da2e3ebdSchin /*
62da2e3ebdSchin * initialize hash table with keywords from key
63da2e3ebdSchin */
64da2e3ebdSchin
65da2e3ebdSchin static void
inithash(register Hash_table_t * tab,register struct ppkeyword * key)66da2e3ebdSchin inithash(register Hash_table_t* tab, register struct ppkeyword* key)
67da2e3ebdSchin {
68da2e3ebdSchin register char* s;
69da2e3ebdSchin
70da2e3ebdSchin for (; s = key->name; key++)
71da2e3ebdSchin {
72da2e3ebdSchin if (!ppisid(*s))
73da2e3ebdSchin s++;
74da2e3ebdSchin hashput(tab, s, key->value);
75da2e3ebdSchin }
76da2e3ebdSchin }
77da2e3ebdSchin
78da2e3ebdSchin /*
79da2e3ebdSchin * return ppkeyword table name given value
80da2e3ebdSchin */
81da2e3ebdSchin
82da2e3ebdSchin char*
ppkeyname(register int value,int dir)83da2e3ebdSchin ppkeyname(register int value, int dir)
84da2e3ebdSchin {
85da2e3ebdSchin register char* s;
86da2e3ebdSchin register struct ppkeyword* p;
87da2e3ebdSchin
88da2e3ebdSchin if (dir && ppiskey(directives, value, p) || !dir && (ppiskey(options, value, p) || ppiskey(predicates, value, p) || ppiskey(variables, value, p)))
89da2e3ebdSchin {
90da2e3ebdSchin s = (p + (value - p->value))->name;
91da2e3ebdSchin return s + !ppisid(*s);
92da2e3ebdSchin }
93da2e3ebdSchin #if DEBUG
94da2e3ebdSchin error(PANIC, "no keyword table name for value=%d", value);
95da2e3ebdSchin #endif
96da2e3ebdSchin return "UNKNOWN";
97da2e3ebdSchin }
98da2e3ebdSchin
99da2e3ebdSchin /*
100da2e3ebdSchin * add to the include maps
101da2e3ebdSchin */
102da2e3ebdSchin
103da2e3ebdSchin void
ppmapinclude(char * file,register char * s)104da2e3ebdSchin ppmapinclude(char* file, register char* s)
105da2e3ebdSchin {
106da2e3ebdSchin register int c;
107da2e3ebdSchin register struct ppdirs* dp;
108da2e3ebdSchin int fd;
109da2e3ebdSchin int flags;
110da2e3ebdSchin int index;
111da2e3ebdSchin int token;
112da2e3ebdSchin char* t;
113da2e3ebdSchin char* old_file;
114da2e3ebdSchin long old_state;
115da2e3ebdSchin struct ppfile* fp;
116da2e3ebdSchin struct ppfile* mp;
117da2e3ebdSchin
118da2e3ebdSchin old_file = error_info.file;
119da2e3ebdSchin old_state = pp.state;
120da2e3ebdSchin if (s)
121da2e3ebdSchin PUSH_BUFFER("mapinclude", s, 1);
122da2e3ebdSchin else if (file)
123da2e3ebdSchin {
124da2e3ebdSchin if (*file == '-')
125da2e3ebdSchin {
126da2e3ebdSchin if (!error_info.file)
127da2e3ebdSchin {
128da2e3ebdSchin error(1, "%s: input file name required for %s ignore", file, dirname(INCLUDE));
129da2e3ebdSchin return;
130da2e3ebdSchin }
131da2e3ebdSchin s = t = strcopy(pp.tmpbuf, error_info.file);
132da2e3ebdSchin c = *++file;
133da2e3ebdSchin for (;;)
134da2e3ebdSchin {
135da2e3ebdSchin if (s <= pp.tmpbuf || *s == '/')
136da2e3ebdSchin {
137da2e3ebdSchin s = t;
138da2e3ebdSchin break;
139da2e3ebdSchin }
140da2e3ebdSchin else if (*s == c)
141da2e3ebdSchin break;
142da2e3ebdSchin s--;
143da2e3ebdSchin }
144da2e3ebdSchin strcpy(s, file);
145da2e3ebdSchin file = pp.tmpbuf;
146da2e3ebdSchin }
147da2e3ebdSchin if ((fd = ppsearch(file, INC_LOCAL, SEARCH_INCLUDE)) < 0)
148da2e3ebdSchin return;
149da2e3ebdSchin PUSH_FILE(file, fd);
150da2e3ebdSchin }
151da2e3ebdSchin else
152da2e3ebdSchin return;
153da2e3ebdSchin #if CATSTRINGS
154da2e3ebdSchin pp.state |= (COMPILE|FILEPOP|HEADER|JOINING|STRIP|NOSPACE|PASSEOF);
155da2e3ebdSchin #else
156da2e3ebdSchin pp.state |= (COMPILE|FILEPOP|HEADER|STRIP|NOSPACE|PASSEOF);
157da2e3ebdSchin #endif
158da2e3ebdSchin pp.level++;
159da2e3ebdSchin flags = INC_MAPALL;
160da2e3ebdSchin fp = mp = 0;
161da2e3ebdSchin for (;;)
162da2e3ebdSchin {
163da2e3ebdSchin switch (token = pplex())
164da2e3ebdSchin {
165da2e3ebdSchin case 0:
166da2e3ebdSchin case T_STRING:
167da2e3ebdSchin case T_HEADER:
168da2e3ebdSchin if (fp)
169da2e3ebdSchin {
170da2e3ebdSchin fp->guard = INC_IGNORE;
171da2e3ebdSchin for (dp = pp.firstdir->next; dp; dp = dp->next)
172da2e3ebdSchin if (dp->name && (c = strlen(dp->name)) && !strncmp(dp->name, fp->name, c) && fp->name[c] == '/')
173da2e3ebdSchin {
174da2e3ebdSchin ppsetfile(fp->name + c + 1)->guard = INC_IGNORE;
175da2e3ebdSchin break;
176da2e3ebdSchin }
177da2e3ebdSchin }
178da2e3ebdSchin if (!token)
179da2e3ebdSchin break;
180da2e3ebdSchin pathcanon(pp.token, 0);
181da2e3ebdSchin fp = ppsetfile(pp.token);
182da2e3ebdSchin if (mp)
183da2e3ebdSchin {
184da2e3ebdSchin mp->flags |= flags;
185da2e3ebdSchin if (streq(fp->name, "."))
186da2e3ebdSchin mp->flags |= INC_MAPNOLOCAL;
187da2e3ebdSchin else
188da2e3ebdSchin mp->bound[index] = fp;
189da2e3ebdSchin
190da2e3ebdSchin fp = mp = 0;
191da2e3ebdSchin }
192da2e3ebdSchin else
193da2e3ebdSchin index = token == T_HEADER ? INC_STANDARD : INC_LOCAL;
194da2e3ebdSchin continue;
195da2e3ebdSchin case '=':
196da2e3ebdSchin if (!(mp = fp))
197da2e3ebdSchin error(3, "%s: \"name\" = \"binding\" expected");
198da2e3ebdSchin fp = 0;
199da2e3ebdSchin continue;
200da2e3ebdSchin case '\n':
201da2e3ebdSchin continue;
202da2e3ebdSchin case T_ID:
203da2e3ebdSchin if (streq(pp.token, "all"))
204da2e3ebdSchin {
205da2e3ebdSchin flags = INC_MAPALL;
206da2e3ebdSchin continue;
207da2e3ebdSchin }
208da2e3ebdSchin else if (streq(pp.token, "hosted"))
209da2e3ebdSchin {
210da2e3ebdSchin flags = INC_MAPHOSTED;
211da2e3ebdSchin continue;
212da2e3ebdSchin }
213da2e3ebdSchin else if (streq(pp.token, "nohosted"))
214da2e3ebdSchin {
215da2e3ebdSchin flags = INC_MAPNOHOSTED;
216da2e3ebdSchin continue;
217da2e3ebdSchin }
218da2e3ebdSchin /*FALLTHROUGH*/
219da2e3ebdSchin default:
220da2e3ebdSchin error(3, "%s unexpected in %s map list", pptokstr(pp.token, 0), dirname(INCLUDE));
221da2e3ebdSchin break;
222da2e3ebdSchin }
223da2e3ebdSchin break;
224da2e3ebdSchin }
225da2e3ebdSchin pp.level--;
226da2e3ebdSchin error_info.file = old_file;
227da2e3ebdSchin pp.state = old_state;
228da2e3ebdSchin }
229da2e3ebdSchin
230da2e3ebdSchin /*
231da2e3ebdSchin * return non-0 if file is identical to fd
232da2e3ebdSchin */
233da2e3ebdSchin
234da2e3ebdSchin static int
identical(char * file,int fd)235da2e3ebdSchin identical(char* file, int fd)
236da2e3ebdSchin {
237da2e3ebdSchin struct stat a;
238da2e3ebdSchin struct stat b;
239da2e3ebdSchin
240da2e3ebdSchin return !stat(file, &a) && !fstat(fd, &b) && a.st_dev == b.st_dev && a.st_ino == b.st_ino;
241da2e3ebdSchin }
242da2e3ebdSchin
243da2e3ebdSchin /*
244da2e3ebdSchin * compare up to pp.truncate chars
245da2e3ebdSchin *
246da2e3ebdSchin * NOTE: __STD* and symbols containing ' ' are not truncated
247da2e3ebdSchin */
248da2e3ebdSchin
249da2e3ebdSchin static int
trunccomp(register char * a,register char * b)250da2e3ebdSchin trunccomp(register char* a, register char* b)
251da2e3ebdSchin {
252da2e3ebdSchin return !strchr(b, ' ') && !strneq(b, "__STD", 5) ? strncmp(a, b, pp.truncate) : strcmp(a, b);
253da2e3ebdSchin }
254da2e3ebdSchin
255da2e3ebdSchin /*
256da2e3ebdSchin * hash up to pp.truncate chars
257da2e3ebdSchin *
258da2e3ebdSchin * NOTE: __STD* and symbols containing ' ' are not truncated
259da2e3ebdSchin */
260da2e3ebdSchin
261da2e3ebdSchin static unsigned int
trunchash(char * a)262da2e3ebdSchin trunchash(char* a)
263da2e3ebdSchin {
264da2e3ebdSchin int n;
265da2e3ebdSchin
266da2e3ebdSchin return memhash(a, (n = strlen(a)) > pp.truncate && !strchr(a, ' ') && !strneq(a, "__STD", 5) ? pp.truncate : n);
267da2e3ebdSchin }
268da2e3ebdSchin
269da2e3ebdSchin #if DEBUG & TRACE_debug
270da2e3ebdSchin /*
271da2e3ebdSchin * append context to debug trace
272da2e3ebdSchin */
273da2e3ebdSchin
274da2e3ebdSchin static int
context(Sfio_t * sp,int level,int flags)275da2e3ebdSchin context(Sfio_t* sp, int level, int flags)
276da2e3ebdSchin {
277da2e3ebdSchin static int state;
278da2e3ebdSchin
279da2e3ebdSchin NoP(level);
280da2e3ebdSchin NoP(flags);
281da2e3ebdSchin if (error_info.trace <= -10 && pp.state != state)
282da2e3ebdSchin {
283da2e3ebdSchin state = pp.state;
284da2e3ebdSchin sfprintf(sp, " %s", ppstatestr(pp.state));
285da2e3ebdSchin }
286da2e3ebdSchin return 1;
287da2e3ebdSchin }
288da2e3ebdSchin #endif
289da2e3ebdSchin
290da2e3ebdSchin /*
291da2e3ebdSchin * reset include guard
292da2e3ebdSchin */
293da2e3ebdSchin
294da2e3ebdSchin static int
unguard(const char * name,char * v,void * handle)295da2e3ebdSchin unguard(const char* name, char* v, void* handle)
296da2e3ebdSchin {
297da2e3ebdSchin register struct ppfile* fp = (struct ppfile*)v;
298da2e3ebdSchin
299da2e3ebdSchin fp->guard = 0;
300da2e3ebdSchin return 0;
301da2e3ebdSchin }
302da2e3ebdSchin
303da2e3ebdSchin /*
304da2e3ebdSchin * reset macro definition
305da2e3ebdSchin */
306da2e3ebdSchin
307da2e3ebdSchin static void
undefine(void * p)308da2e3ebdSchin undefine(void* p)
309da2e3ebdSchin {
310da2e3ebdSchin struct ppmacro* mac = ((struct ppsymbol*)p)->macro;
311da2e3ebdSchin
312da2e3ebdSchin if (mac)
313da2e3ebdSchin {
314da2e3ebdSchin if (mac->formals)
315da2e3ebdSchin free(mac->formals);
316da2e3ebdSchin free(mac->value);
317da2e3ebdSchin free(mac);
318da2e3ebdSchin }
319da2e3ebdSchin }
320da2e3ebdSchin
321da2e3ebdSchin /*
322da2e3ebdSchin * pp operations
323da2e3ebdSchin *
324da2e3ebdSchin * NOTE: PP_INIT must be done before the first pplex() call
325da2e3ebdSchin * PP_DONE must be done after the last pplex() call
326da2e3ebdSchin * PP_INIT-PP_DONE must be done for each new PP_INPUT
327da2e3ebdSchin */
328da2e3ebdSchin
329da2e3ebdSchin void
ppop(int op,...)330da2e3ebdSchin ppop(int op, ...)
331da2e3ebdSchin {
332da2e3ebdSchin va_list ap;
333da2e3ebdSchin register char* p;
334da2e3ebdSchin register struct ppkeyword* kp;
335da2e3ebdSchin register char* s;
336da2e3ebdSchin int c;
337da2e3ebdSchin long n;
338da2e3ebdSchin char* t;
339da2e3ebdSchin struct ppdirs* dp;
340da2e3ebdSchin struct ppdirs* hp;
341da2e3ebdSchin struct ppsymkey* key;
342da2e3ebdSchin struct oplist* xp;
343da2e3ebdSchin Sfio_t* sp;
344da2e3ebdSchin struct stat st;
345da2e3ebdSchin PPCOMMENT ppcomment;
346da2e3ebdSchin PPLINESYNC pplinesync;
347da2e3ebdSchin
348da2e3ebdSchin static int initialized;
349da2e3ebdSchin
350da2e3ebdSchin va_start(ap, op);
351da2e3ebdSchin switch (op)
352da2e3ebdSchin {
353da2e3ebdSchin case PP_ASSERT:
354da2e3ebdSchin case PP_DEFINE:
355da2e3ebdSchin case PP_DIRECTIVE:
356da2e3ebdSchin case PP_OPTION:
357da2e3ebdSchin case PP_READ:
358da2e3ebdSchin case PP_UNDEF:
359da2e3ebdSchin if (pp.initialized)
360da2e3ebdSchin goto before;
361da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p)
362da2e3ebdSchin {
363da2e3ebdSchin if (pp.lastop)
364da2e3ebdSchin pp.lastop = (pp.lastop->next = newof(0, struct oplist, 1, 0));
365da2e3ebdSchin else
366da2e3ebdSchin pp.firstop = pp.lastop = newof(0, struct oplist, 1, 0);
367da2e3ebdSchin pp.lastop->op = op;
368da2e3ebdSchin pp.lastop->value = p;
369da2e3ebdSchin }
370da2e3ebdSchin break;
371da2e3ebdSchin case PP_BUILTIN:
372da2e3ebdSchin pp.builtin = va_arg(ap, PPBUILTIN);
373da2e3ebdSchin break;
374da2e3ebdSchin case PP_CDIR:
375da2e3ebdSchin p = va_arg(ap, char*);
376da2e3ebdSchin c = va_arg(ap, int);
377da2e3ebdSchin pp.cdir.path = 0;
378da2e3ebdSchin if (!p)
379da2e3ebdSchin pp.c = c;
380da2e3ebdSchin else if (streq(p, "-"))
381da2e3ebdSchin {
382da2e3ebdSchin pp.c = c;
383da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
384da2e3ebdSchin dp->c = c;
385da2e3ebdSchin }
386da2e3ebdSchin else if (!pp.c)
387da2e3ebdSchin {
388da2e3ebdSchin if (!*p || stat((pathcanon(p, 0), p), &st))
389da2e3ebdSchin pp.c = c;
390da2e3ebdSchin else
391da2e3ebdSchin {
392da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
393da2e3ebdSchin {
394da2e3ebdSchin if (!pp.c && (dp->c || dp->name && SAMEID(&dp->id, &st)))
395da2e3ebdSchin pp.c = 1;
396da2e3ebdSchin dp->c = pp.c == 1;
397da2e3ebdSchin }
398da2e3ebdSchin if (!pp.c)
399da2e3ebdSchin {
400da2e3ebdSchin pp.cdir.path = p;
401da2e3ebdSchin SAVEID(&pp.cdir.id, &st);
402da2e3ebdSchin }
403da2e3ebdSchin }
404da2e3ebdSchin }
405da2e3ebdSchin break;
406da2e3ebdSchin case PP_CHOP:
407da2e3ebdSchin if (p = va_arg(ap, char*))
408da2e3ebdSchin {
409da2e3ebdSchin c = strlen(p);
410da2e3ebdSchin xp = newof(0, struct oplist, 1, c + 1);
411da2e3ebdSchin xp->value = ((char*)xp) + sizeof(struct oplist);
412da2e3ebdSchin s = xp->value;
413da2e3ebdSchin c = *p++;
414da2e3ebdSchin while (*p && *p != c)
415da2e3ebdSchin *s++ = *p++;
416da2e3ebdSchin *s++ = '/';
417da2e3ebdSchin xp->op = s - xp->value;
418da2e3ebdSchin *s++ = 0;
419da2e3ebdSchin if (*p && *++p && *p != c)
420da2e3ebdSchin {
421da2e3ebdSchin while (*p && *p != c)
422da2e3ebdSchin *s++ = *p++;
423da2e3ebdSchin *s++ = '/';
424da2e3ebdSchin }
425da2e3ebdSchin *s = 0;
426da2e3ebdSchin xp->next = pp.chop;
427da2e3ebdSchin pp.chop = xp;
428da2e3ebdSchin }
429da2e3ebdSchin break;
430da2e3ebdSchin case PP_COMMENT:
431da2e3ebdSchin if (pp.comment = va_arg(ap, PPCOMMENT))
432da2e3ebdSchin pp.flags |= PP_comment;
433da2e3ebdSchin else
434da2e3ebdSchin pp.flags &= ~PP_comment;
435da2e3ebdSchin break;
436da2e3ebdSchin case PP_COMPATIBILITY:
437da2e3ebdSchin set(&pp.state, COMPATIBILITY, va_arg(ap, int));
438da2e3ebdSchin #if COMPATIBLE
439da2e3ebdSchin if (pp.initialized)
440da2e3ebdSchin ppfsm(FSM_COMPATIBILITY, NiL);
441da2e3ebdSchin #else
442da2e3ebdSchin if (pp.state & COMPATIBILITY)
443da2e3ebdSchin error(3, "preprocessor not compiled with compatibility dialect enabled [COMPATIBLE]");
444da2e3ebdSchin #endif
445da2e3ebdSchin if (pp.state & COMPATIBILITY)
446da2e3ebdSchin pp.flags |= PP_compatibility;
447da2e3ebdSchin else
448da2e3ebdSchin pp.flags &= ~PP_compatibility;
449da2e3ebdSchin break;
450da2e3ebdSchin case PP_COMPILE:
451da2e3ebdSchin if (pp.initialized)
452da2e3ebdSchin goto before;
453da2e3ebdSchin pp.state |= COMPILE;
454da2e3ebdSchin if (!pp.symtab)
455da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0);
456da2e3ebdSchin if (kp = va_arg(ap, struct ppkeyword*))
457da2e3ebdSchin for (; s = kp->name; kp++)
458da2e3ebdSchin {
459da2e3ebdSchin n = SYM_LEX;
460da2e3ebdSchin switch (*s)
461da2e3ebdSchin {
462da2e3ebdSchin case '-':
463da2e3ebdSchin s++;
464da2e3ebdSchin break;
465da2e3ebdSchin case '+':
466da2e3ebdSchin s++;
467da2e3ebdSchin if (!(pp.option & PLUSPLUS))
468da2e3ebdSchin break;
469da2e3ebdSchin /*FALLTHROUGH*/
470da2e3ebdSchin default:
471da2e3ebdSchin n |= SYM_KEYWORD;
472da2e3ebdSchin break;
473da2e3ebdSchin }
474da2e3ebdSchin if (key = ppkeyset(pp.symtab, s))
475da2e3ebdSchin {
476da2e3ebdSchin key->sym.flags = n;
477da2e3ebdSchin key->lex = kp->value;
478da2e3ebdSchin }
479da2e3ebdSchin }
480da2e3ebdSchin break;
481da2e3ebdSchin case PP_DEBUG:
482da2e3ebdSchin error_info.trace = va_arg(ap, int);
483da2e3ebdSchin break;
484da2e3ebdSchin case PP_DEFAULT:
485da2e3ebdSchin if (p = va_arg(ap, char*))
486da2e3ebdSchin p = strdup(p);
487da2e3ebdSchin if (pp.ppdefault)
488da2e3ebdSchin free(pp.ppdefault);
489da2e3ebdSchin pp.ppdefault = p;
490da2e3ebdSchin break;
491da2e3ebdSchin case PP_DONE:
492da2e3ebdSchin #if CHECKPOINT
493da2e3ebdSchin if (pp.mode & DUMP)
494da2e3ebdSchin ppdump();
495da2e3ebdSchin #endif
496da2e3ebdSchin if (pp.mode & FILEDEPS)
497da2e3ebdSchin {
498da2e3ebdSchin sfputc(pp.filedeps.sp, '\n');
499da2e3ebdSchin if (pp.filedeps.sp == sfstdout)
500da2e3ebdSchin sfsync(pp.filedeps.sp);
501da2e3ebdSchin else
502da2e3ebdSchin sfclose(pp.filedeps.sp);
503da2e3ebdSchin }
504da2e3ebdSchin if (pp.state & STANDALONE)
505da2e3ebdSchin {
506da2e3ebdSchin if ((pp.state & (NOTEXT|HIDDEN)) == HIDDEN && pplastout() != '\n')
507da2e3ebdSchin ppputchar('\n');
508da2e3ebdSchin ppflushout();
509da2e3ebdSchin }
510da2e3ebdSchin error_info.file = 0;
511da2e3ebdSchin break;
512da2e3ebdSchin case PP_DUMP:
513da2e3ebdSchin set(&pp.mode, DUMP, va_arg(ap, int));
514da2e3ebdSchin #if !CHECKPOINT
515da2e3ebdSchin if (pp.mode & DUMP)
516da2e3ebdSchin error(3, "preprocessor not compiled with checkpoint enabled [CHECKPOINT]");
517da2e3ebdSchin #endif
518da2e3ebdSchin break;
519da2e3ebdSchin case PP_FILEDEPS:
520da2e3ebdSchin if (n = va_arg(ap, int))
521da2e3ebdSchin pp.filedeps.flags |= n;
522da2e3ebdSchin else
523da2e3ebdSchin pp.filedeps.flags = 0;
524da2e3ebdSchin break;
525da2e3ebdSchin case PP_FILENAME:
526da2e3ebdSchin error_info.file = va_arg(ap, char*);
527da2e3ebdSchin break;
528da2e3ebdSchin case PP_HOSTDIR:
529da2e3ebdSchin if (!(pp.mode & INIT))
530da2e3ebdSchin pp.ro_mode |= HOSTED;
531da2e3ebdSchin else if (pp.ro_mode & HOSTED)
532da2e3ebdSchin break;
533da2e3ebdSchin pp.ro_mode |= INIT;
534da2e3ebdSchin p = va_arg(ap, char*);
535da2e3ebdSchin c = va_arg(ap, int);
536da2e3ebdSchin pp.hostdir.path = 0;
537da2e3ebdSchin if (!p)
538da2e3ebdSchin pp.hosted = c;
539da2e3ebdSchin else if (streq(p, "-"))
540da2e3ebdSchin {
541da2e3ebdSchin if (pp.initialized)
542da2e3ebdSchin set(&pp.mode, HOSTED, c);
543da2e3ebdSchin else
544da2e3ebdSchin {
545da2e3ebdSchin pp.hosted = c ? 1 : 2;
546da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
547da2e3ebdSchin if (pp.hosted == 1)
548da2e3ebdSchin dp->type |= TYPE_HOSTED;
549da2e3ebdSchin else
550da2e3ebdSchin dp->type &= ~TYPE_HOSTED;
551da2e3ebdSchin }
552da2e3ebdSchin }
553da2e3ebdSchin else if (!pp.hosted)
554da2e3ebdSchin {
555da2e3ebdSchin if (!*p || stat((pathcanon(p, 0), p), &st))
556da2e3ebdSchin pp.hosted = 1;
557da2e3ebdSchin else
558da2e3ebdSchin {
559da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
560da2e3ebdSchin {
561da2e3ebdSchin if (!pp.hosted && ((dp->type & TYPE_HOSTED) || dp->name && SAMEID(&dp->id, &st)))
562da2e3ebdSchin pp.hosted = 1;
563da2e3ebdSchin if (pp.hosted == 1)
564da2e3ebdSchin dp->type |= TYPE_HOSTED;
565da2e3ebdSchin else
566da2e3ebdSchin dp->type &= ~TYPE_HOSTED;
567da2e3ebdSchin }
568da2e3ebdSchin if (!pp.hosted)
569da2e3ebdSchin {
570da2e3ebdSchin pp.hostdir.path = p;
571da2e3ebdSchin SAVEID(&pp.hostdir.id, &st);
572da2e3ebdSchin }
573da2e3ebdSchin }
574da2e3ebdSchin }
575da2e3ebdSchin break;
576da2e3ebdSchin case PP_ID:
577da2e3ebdSchin p = va_arg(ap, char*);
578da2e3ebdSchin c = va_arg(ap, int);
579da2e3ebdSchin if (p)
580da2e3ebdSchin ppfsm(c ? FSM_IDADD : FSM_IDDEL, p);
581da2e3ebdSchin break;
582da2e3ebdSchin case PP_IGNORE:
583da2e3ebdSchin if (p = va_arg(ap, char*))
584da2e3ebdSchin {
585da2e3ebdSchin pathcanon(p, 0);
586da2e3ebdSchin ppsetfile(p)->guard = INC_IGNORE;
587da2e3ebdSchin message((-3, "%s: ignore", p));
588da2e3ebdSchin }
589da2e3ebdSchin break;
590da2e3ebdSchin case PP_IGNORELIST:
591da2e3ebdSchin if (pp.initialized)
592da2e3ebdSchin goto before;
593da2e3ebdSchin pp.ignore = va_arg(ap, char*);
594da2e3ebdSchin break;
595da2e3ebdSchin case PP_INCLUDE:
596da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p)
597da2e3ebdSchin {
598da2e3ebdSchin pathcanon(p, 0);
599da2e3ebdSchin if (stat(p, &st))
600da2e3ebdSchin break;
601da2e3ebdSchin for (dp = pp.stddirs; dp = dp->next;)
602da2e3ebdSchin if (dp->name && SAMEID(&dp->id, &st))
603da2e3ebdSchin break;
604da2e3ebdSchin if (pp.cdir.path && SAMEID(&pp.cdir.id, &st))
605da2e3ebdSchin {
606da2e3ebdSchin pp.cdir.path = 0;
607da2e3ebdSchin pp.c = 1;
608da2e3ebdSchin }
609da2e3ebdSchin if (pp.hostdir.path && SAMEID(&pp.hostdir.id, &st))
610da2e3ebdSchin {
611da2e3ebdSchin pp.hostdir.path = 0;
612da2e3ebdSchin pp.hosted = 1;
613da2e3ebdSchin }
614da2e3ebdSchin if ((pp.mode & INIT) && !(pp.ro_mode & INIT))
615da2e3ebdSchin pp.hosted = 1;
616da2e3ebdSchin c = dp && dp->c || pp.c == 1;
617da2e3ebdSchin n = dp && (dp->type & TYPE_HOSTED) || pp.hosted == 1;
618da2e3ebdSchin if (!dp || dp == pp.lastdir->next)
619da2e3ebdSchin {
620da2e3ebdSchin if (dp)
621da2e3ebdSchin {
622da2e3ebdSchin c = dp->c;
623da2e3ebdSchin n = dp->type & TYPE_HOSTED;
624da2e3ebdSchin }
625da2e3ebdSchin dp = newof(0, struct ppdirs, 1, 0);
626da2e3ebdSchin dp->name = p;
627da2e3ebdSchin SAVEID(&dp->id, &st);
628da2e3ebdSchin dp->type |= TYPE_INCLUDE;
629da2e3ebdSchin dp->index = INC_LOCAL + pp.ignoresrc != 0;
630da2e3ebdSchin dp->next = pp.lastdir->next;
631da2e3ebdSchin pp.lastdir = pp.lastdir->next = dp;
632da2e3ebdSchin }
633da2e3ebdSchin dp->c = c;
634da2e3ebdSchin if (n)
635da2e3ebdSchin dp->type |= TYPE_HOSTED;
636da2e3ebdSchin else
637da2e3ebdSchin dp->type &= ~TYPE_HOSTED;
638da2e3ebdSchin }
639da2e3ebdSchin break;
640da2e3ebdSchin case PP_INCREF:
641da2e3ebdSchin pp.incref = va_arg(ap, PPINCREF);
642da2e3ebdSchin break;
643da2e3ebdSchin case PP_RESET:
644da2e3ebdSchin pp.reset.on = 1;
645da2e3ebdSchin break;
646da2e3ebdSchin case PP_INIT:
647da2e3ebdSchin if (pp.initialized)
648da2e3ebdSchin {
649da2e3ebdSchin error_info.errors = 0;
650da2e3ebdSchin error_info.warnings = 0;
651da2e3ebdSchin }
652da2e3ebdSchin else
653da2e3ebdSchin {
654da2e3ebdSchin /*
655da2e3ebdSchin * context initialization
656da2e3ebdSchin */
657da2e3ebdSchin
658da2e3ebdSchin if (!initialized)
659da2e3ebdSchin {
660da2e3ebdSchin /*
661da2e3ebdSchin * out of malloc is fatal
662da2e3ebdSchin */
663da2e3ebdSchin
664da2e3ebdSchin memfatal();
665da2e3ebdSchin
666da2e3ebdSchin /*
667da2e3ebdSchin * initialize the error message interface
668da2e3ebdSchin */
669da2e3ebdSchin
670da2e3ebdSchin error_info.version = (char*)pp.version;
671da2e3ebdSchin #if DEBUG & TRACE_debug
672da2e3ebdSchin error_info.auxilliary = context;
673da2e3ebdSchin pptrace(0);
674da2e3ebdSchin #endif
675da2e3ebdSchin
676da2e3ebdSchin /*
677da2e3ebdSchin * initialize pplex tables
678da2e3ebdSchin */
679da2e3ebdSchin
680da2e3ebdSchin ppfsm(FSM_INIT, NiL);
681da2e3ebdSchin
682da2e3ebdSchin /*
683da2e3ebdSchin * fixed macro stack size -- room for improvement
684da2e3ebdSchin */
685da2e3ebdSchin
686da2e3ebdSchin pp.macp = newof(0, struct ppmacstk, DEFMACSTACK, 0);
687da2e3ebdSchin pp.macp->next = pp.macp + 1;
688da2e3ebdSchin pp.maxmac = (char*)pp.macp + DEFMACSTACK;
689da2e3ebdSchin initialized = 1;
690da2e3ebdSchin
691da2e3ebdSchin /*
692da2e3ebdSchin * initial include/if control stack
693da2e3ebdSchin */
694da2e3ebdSchin
695da2e3ebdSchin pp.control = newof(0, long, pp.constack, 0);
696da2e3ebdSchin pp.maxcon = pp.control + pp.constack - 1;
697da2e3ebdSchin }
698da2e3ebdSchin
699da2e3ebdSchin /*
700da2e3ebdSchin * validate modes
701da2e3ebdSchin */
702da2e3ebdSchin
703da2e3ebdSchin switch (pp.arg_mode)
704da2e3ebdSchin {
705da2e3ebdSchin case 'a':
706da2e3ebdSchin case 'C':
707da2e3ebdSchin ppop(PP_COMPATIBILITY, 0);
708da2e3ebdSchin ppop(PP_TRANSITION, 1);
709da2e3ebdSchin break;
710da2e3ebdSchin case 'A':
711da2e3ebdSchin case 'c':
712da2e3ebdSchin ppop(PP_COMPATIBILITY, 0);
713da2e3ebdSchin ppop(PP_STRICT, 1);
714da2e3ebdSchin break;
715da2e3ebdSchin case 'f':
716da2e3ebdSchin ppop(PP_COMPATIBILITY, 1);
717da2e3ebdSchin ppop(PP_PLUSPLUS, 1);
718da2e3ebdSchin ppop(PP_TRANSITION, 1);
719da2e3ebdSchin break;
720da2e3ebdSchin case 'F':
721da2e3ebdSchin ppop(PP_COMPATIBILITY, 0);
722da2e3ebdSchin ppop(PP_PLUSPLUS, 1);
723da2e3ebdSchin break;
724da2e3ebdSchin case 'k':
725da2e3ebdSchin case 's':
726da2e3ebdSchin ppop(PP_COMPATIBILITY, 1);
727da2e3ebdSchin ppop(PP_STRICT, 1);
728da2e3ebdSchin break;
729da2e3ebdSchin case 'o':
730da2e3ebdSchin case 'O':
731da2e3ebdSchin ppop(PP_COMPATIBILITY, 1);
732da2e3ebdSchin ppop(PP_TRANSITION, 0);
733da2e3ebdSchin break;
734da2e3ebdSchin case 't':
735da2e3ebdSchin ppop(PP_COMPATIBILITY, 1);
736da2e3ebdSchin ppop(PP_TRANSITION, 1);
737da2e3ebdSchin break;
738da2e3ebdSchin }
7397c2fbfb3SApril Chin if (!(pp.state & WARN) && !(pp.arg_style & STYLE_gnu))
740da2e3ebdSchin ppop(PP_PEDANTIC, 1);
741da2e3ebdSchin if (pp.state & PASSTHROUGH)
742da2e3ebdSchin {
743da2e3ebdSchin if (pp.state & COMPILE)
744da2e3ebdSchin {
745da2e3ebdSchin pp.state &= ~PASSTHROUGH;
746da2e3ebdSchin error(1, "passthrough ignored for compile");
747da2e3ebdSchin }
748da2e3ebdSchin else
749da2e3ebdSchin {
750da2e3ebdSchin ppop(PP_COMPATIBILITY, 1);
751da2e3ebdSchin ppop(PP_HOSTDIR, "-", 1);
752da2e3ebdSchin ppop(PP_SPACEOUT, 1);
753da2e3ebdSchin set(&pp.state, DISABLE, va_arg(ap, int));
754da2e3ebdSchin }
755da2e3ebdSchin }
756da2e3ebdSchin
757da2e3ebdSchin /*
758da2e3ebdSchin * create the hash tables
759da2e3ebdSchin */
760da2e3ebdSchin
761da2e3ebdSchin if (!pp.symtab)
762da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0);
763da2e3ebdSchin if (!pp.dirtab)
764da2e3ebdSchin {
765da2e3ebdSchin pp.dirtab = hashalloc(REFONE, HASH_name, "directives", 0);
766da2e3ebdSchin inithash(pp.dirtab, directives);
767da2e3ebdSchin }
768da2e3ebdSchin if (!pp.filtab)
769da2e3ebdSchin pp.filtab = hashalloc(REFALL, HASH_name, "files", 0);
770da2e3ebdSchin if (!pp.prdtab)
771da2e3ebdSchin pp.prdtab = hashalloc(REFALL, HASH_name, "predicates", 0);
772da2e3ebdSchin if (!pp.strtab)
773da2e3ebdSchin {
774da2e3ebdSchin pp.strtab = hashalloc(REFALL, HASH_name, "strings", 0);
775da2e3ebdSchin inithash(pp.strtab, options);
776da2e3ebdSchin inithash(pp.strtab, predicates);
777da2e3ebdSchin inithash(pp.strtab, variables);
778da2e3ebdSchin }
779da2e3ebdSchin pp.optflags[X_PROTOTYPED] = OPT_GLOBAL;
780da2e3ebdSchin pp.optflags[X_SYSTEM_HEADER] = OPT_GLOBAL|OPT_PASS;
781da2e3ebdSchin
782da2e3ebdSchin /*
783da2e3ebdSchin * mark macros that are builtin predicates
784da2e3ebdSchin */
785da2e3ebdSchin
786da2e3ebdSchin for (kp = predicates; s = kp->name; kp++)
787da2e3ebdSchin {
788da2e3ebdSchin if (!ppisid(*s))
789da2e3ebdSchin s++;
790da2e3ebdSchin ppassert(DEFINE, s, 0);
791da2e3ebdSchin }
792da2e3ebdSchin
793da2e3ebdSchin /*
794da2e3ebdSchin * the remaining entry names must be allocated
795da2e3ebdSchin */
796da2e3ebdSchin
797da2e3ebdSchin hashset(pp.dirtab, HASH_ALLOCATE);
798da2e3ebdSchin hashset(pp.filtab, HASH_ALLOCATE);
799da2e3ebdSchin hashset(pp.prdtab, HASH_ALLOCATE);
800da2e3ebdSchin hashset(pp.strtab, HASH_ALLOCATE);
801da2e3ebdSchin hashset(pp.symtab, HASH_ALLOCATE);
802da2e3ebdSchin if (pp.test & TEST_nonoise)
803da2e3ebdSchin {
804da2e3ebdSchin c = error_info.trace;
805da2e3ebdSchin error_info.trace = 0;
806da2e3ebdSchin }
807da2e3ebdSchin #if DEBUG
808da2e3ebdSchin if (!(pp.test & TEST_noinit))
809da2e3ebdSchin {
810da2e3ebdSchin #endif
811da2e3ebdSchin
812da2e3ebdSchin /*
813da2e3ebdSchin * compose, push and read the builtin initialization script
814da2e3ebdSchin */
815da2e3ebdSchin
816da2e3ebdSchin if (!(sp = sfstropen()))
817da2e3ebdSchin error(3, "temporary buffer allocation error");
818da2e3ebdSchin sfprintf(sp,
819da2e3ebdSchin "\
820da2e3ebdSchin #%s %s:%s \"/#<assert> /\" \"/assert /%s #/\"\n\
821da2e3ebdSchin #%s %s:%s \"/#<unassert> /\" \"/unassert /%s #/\"\n\
822da2e3ebdSchin ",
823da2e3ebdSchin dirname(PRAGMA),
824da2e3ebdSchin pp.pass,
825da2e3ebdSchin keyname(X_MAP),
826da2e3ebdSchin dirname(DEFINE),
827da2e3ebdSchin dirname(PRAGMA),
828da2e3ebdSchin pp.pass,
829da2e3ebdSchin keyname(X_MAP),
830da2e3ebdSchin dirname(UNDEF));
831da2e3ebdSchin if (pp.ppdefault && *pp.ppdefault)
832da2e3ebdSchin {
833da2e3ebdSchin if (pp.probe)
834da2e3ebdSchin {
835da2e3ebdSchin c = pp.lastdir->next->type;
836da2e3ebdSchin pp.lastdir->next->type = 0;
837da2e3ebdSchin }
838da2e3ebdSchin if (ppsearch(pp.ppdefault, T_STRING, SEARCH_EXISTS) < 0)
839da2e3ebdSchin {
840da2e3ebdSchin free(pp.ppdefault);
841da2e3ebdSchin if (!(pp.ppdefault = pathprobe(pp.path, NiL, "C", pp.pass, pp.probe ? pp.probe : PPPROBE, 0)))
842da2e3ebdSchin error(1, "cannot determine default definitions for %s", pp.probe ? pp.probe : PPPROBE);
843da2e3ebdSchin }
844da2e3ebdSchin if (pp.probe)
845da2e3ebdSchin pp.lastdir->next->type = c;
846da2e3ebdSchin }
847da2e3ebdSchin while (pp.firstop)
848da2e3ebdSchin {
849da2e3ebdSchin switch (pp.firstop->op)
850da2e3ebdSchin {
851da2e3ebdSchin case PP_ASSERT:
852da2e3ebdSchin sfprintf(sp, "#%s #%s\n", dirname(DEFINE), pp.firstop->value);
853da2e3ebdSchin break;
854da2e3ebdSchin case PP_DEFINE:
855da2e3ebdSchin if (*pp.firstop->value == '#')
856da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(DEFINE), pp.firstop->value);
857da2e3ebdSchin else
858da2e3ebdSchin {
859da2e3ebdSchin if (s = strchr(pp.firstop->value, '='))
860da2e3ebdSchin sfprintf(sp, "#%s %-.*s %s\n", dirname(DEFINE), s - pp.firstop->value, pp.firstop->value, s + 1);
861da2e3ebdSchin else
862da2e3ebdSchin sfprintf(sp, "#%s %s 1\n", dirname(DEFINE), pp.firstop->value);
863da2e3ebdSchin }
864da2e3ebdSchin break;
865da2e3ebdSchin case PP_DIRECTIVE:
866da2e3ebdSchin sfprintf(sp, "#%s\n", pp.firstop->value);
867da2e3ebdSchin break;
868da2e3ebdSchin case PP_OPTION:
869da2e3ebdSchin if (s = strchr(pp.firstop->value, '='))
870da2e3ebdSchin sfprintf(sp, "#%s %s:%-.*s %s\n", dirname(PRAGMA), pp.pass, s - pp.firstop->value, pp.firstop->value, s + 1);
871da2e3ebdSchin else
872da2e3ebdSchin sfprintf(sp, "#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.firstop->value);
873da2e3ebdSchin break;
874da2e3ebdSchin case PP_READ:
875da2e3ebdSchin sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.firstop->value);
876da2e3ebdSchin break;
877da2e3ebdSchin case PP_UNDEF:
878da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(UNDEF), pp.firstop->value);
879da2e3ebdSchin break;
880da2e3ebdSchin }
881da2e3ebdSchin pp.lastop = pp.firstop;
882da2e3ebdSchin pp.firstop = pp.firstop->next;
883da2e3ebdSchin free(pp.lastop);
884da2e3ebdSchin }
885da2e3ebdSchin sfprintf(sp,
886da2e3ebdSchin "\
887da2e3ebdSchin #%s %s:%s\n\
888da2e3ebdSchin #%s %s:%s\n\
889da2e3ebdSchin #%s !#%s(%s)\n\
890da2e3ebdSchin #%s !#%s(%s) || #%s(%s)\n\
891da2e3ebdSchin "
892da2e3ebdSchin , dirname(PRAGMA)
893da2e3ebdSchin , pp.pass
894da2e3ebdSchin , keyname(X_BUILTIN)
895da2e3ebdSchin , dirname(PRAGMA)
896da2e3ebdSchin , pp.pass
897da2e3ebdSchin , keyname(X_PREDEFINED)
898da2e3ebdSchin , dirname(IF)
899da2e3ebdSchin , keyname(X_OPTION)
900da2e3ebdSchin , keyname(X_PLUSPLUS)
901da2e3ebdSchin , dirname(IF)
902da2e3ebdSchin , keyname(X_OPTION)
903da2e3ebdSchin , keyname(X_COMPATIBILITY)
904da2e3ebdSchin , keyname(X_OPTION)
905da2e3ebdSchin , keyname(X_TRANSITION)
906da2e3ebdSchin );
907da2e3ebdSchin sfprintf(sp,
908da2e3ebdSchin "\
909da2e3ebdSchin #%s #%s(%s)\n\
910da2e3ebdSchin #%s %s:%s\n\
911da2e3ebdSchin #%s %s:%s\n\
912da2e3ebdSchin #%s __STRICT__ 1\n\
913da2e3ebdSchin #%s\n\
914da2e3ebdSchin #%s\n\
915da2e3ebdSchin "
916da2e3ebdSchin , dirname(IF)
917da2e3ebdSchin , keyname(X_OPTION)
918da2e3ebdSchin , keyname(X_STRICT)
919da2e3ebdSchin , dirname(PRAGMA)
920da2e3ebdSchin , pp.pass
921da2e3ebdSchin , keyname(X_ALLMULTIPLE)
922da2e3ebdSchin , dirname(PRAGMA)
923da2e3ebdSchin , pp.pass
924da2e3ebdSchin , keyname(X_READONLY)
925da2e3ebdSchin , dirname(DEFINE)
926da2e3ebdSchin , dirname(ENDIF)
927da2e3ebdSchin , dirname(ENDIF)
928da2e3ebdSchin );
929da2e3ebdSchin for (kp = readonlys; s = kp->name; kp++)
930da2e3ebdSchin {
931da2e3ebdSchin if (!ppisid(*s))
932da2e3ebdSchin s++;
933da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(UNDEF), s);
934da2e3ebdSchin }
935da2e3ebdSchin sfprintf(sp,
936da2e3ebdSchin "\
937da2e3ebdSchin #%s\n\
938da2e3ebdSchin #%s __STDPP__ 1\n\
939da2e3ebdSchin #%s %s:no%s\n\
940da2e3ebdSchin "
941da2e3ebdSchin , dirname(ENDIF)
942da2e3ebdSchin , dirname(DEFINE)
943da2e3ebdSchin , dirname(PRAGMA)
944da2e3ebdSchin , pp.pass
945da2e3ebdSchin , keyname(X_PREDEFINED)
946da2e3ebdSchin );
947da2e3ebdSchin if (!pp.truncate)
948da2e3ebdSchin sfprintf(sp,
949da2e3ebdSchin "\
950da2e3ebdSchin #%s __STDPP__directive #(%s)\n\
951da2e3ebdSchin "
952da2e3ebdSchin , dirname(DEFINE)
953da2e3ebdSchin , keyname(V_DIRECTIVE)
954da2e3ebdSchin );
955da2e3ebdSchin for (kp = variables; s = kp->name; kp++)
956da2e3ebdSchin if (ppisid(*s) || *s++ == '+')
957da2e3ebdSchin {
958da2e3ebdSchin t = *s == '_' ? "" : "__";
959da2e3ebdSchin sfprintf(sp, "#%s %s%s%s #(%s)\n" , dirname(DEFINE), t, s, t, s);
960da2e3ebdSchin }
961da2e3ebdSchin sfprintf(sp,
962da2e3ebdSchin "\
963da2e3ebdSchin #%s %s:no%s\n\
964da2e3ebdSchin #%s %s:no%s\n\
965da2e3ebdSchin "
966da2e3ebdSchin , dirname(PRAGMA)
967da2e3ebdSchin , pp.pass
968da2e3ebdSchin , keyname(X_READONLY)
969da2e3ebdSchin , dirname(PRAGMA)
970da2e3ebdSchin , pp.pass
971da2e3ebdSchin , keyname(X_BUILTIN)
972da2e3ebdSchin );
973*34f9b3eeSRoland Mainz if (pp.ppdefault && *pp.ppdefault)
974*34f9b3eeSRoland Mainz sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.ppdefault);
975*34f9b3eeSRoland Mainz sfprintf(sp,
976*34f9b3eeSRoland Mainz "\
977*34f9b3eeSRoland Mainz #%s !defined(__STDC__) && (!#option(compatibility) || #option(transition))\n\
978*34f9b3eeSRoland Mainz #%s __STDC__ #(STDC)\n\
979*34f9b3eeSRoland Mainz #%s\n\
980*34f9b3eeSRoland Mainz "
981*34f9b3eeSRoland Mainz , dirname(IF)
982*34f9b3eeSRoland Mainz , dirname(DEFINE)
983*34f9b3eeSRoland Mainz , dirname(ENDIF)
984*34f9b3eeSRoland Mainz );
985da2e3ebdSchin t = sfstruse(sp);
986da2e3ebdSchin debug((-9, "\n/* begin initialization */\n%s/* end initialization */", t));
987da2e3ebdSchin ppcomment = pp.comment;
988da2e3ebdSchin pp.comment = 0;
989da2e3ebdSchin pplinesync = pp.linesync;
990da2e3ebdSchin pp.linesync = 0;
991da2e3ebdSchin PUSH_INIT(pp.pass, t);
992da2e3ebdSchin pp.mode |= INIT;
993da2e3ebdSchin while (pplex());
994da2e3ebdSchin pp.mode &= ~INIT;
995da2e3ebdSchin pp.comment = ppcomment;
996da2e3ebdSchin pp.linesync = pplinesync;
997da2e3ebdSchin pp.prefix = 0;
998da2e3ebdSchin sfstrclose(sp);
999da2e3ebdSchin if (error_info.trace)
1000da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
1001da2e3ebdSchin message((-1, "include directory %s%s%s%s", dp->name, (dp->type & TYPE_VENDOR) ? " [VENDOR]" : "", (dp->type & TYPE_HOSTED) ? " [HOSTED]" : "", dp->c ? " [C]" : ""));
1002da2e3ebdSchin #if DEBUG
1003da2e3ebdSchin }
1004da2e3ebdSchin if (pp.test & TEST_nonoise)
1005da2e3ebdSchin error_info.trace = c;
1006da2e3ebdSchin #endif
1007da2e3ebdSchin {
1008da2e3ebdSchin /*
1009da2e3ebdSchin * this is sleazy but at least it's
1010da2e3ebdSchin * hidden in the library
1011da2e3ebdSchin */
1012da2e3ebdSchin #include <preroot.h>
1013da2e3ebdSchin #if FS_PREROOT
1014da2e3ebdSchin struct pplist* preroot;
1015da2e3ebdSchin
1016da2e3ebdSchin if ((preroot = (struct pplist*)hashget(pp.prdtab, "preroot")))
1017da2e3ebdSchin setpreroot(NiL, preroot->value);
1018da2e3ebdSchin #endif
1019da2e3ebdSchin }
1020da2e3ebdSchin if (pp.ignoresrc)
1021da2e3ebdSchin {
1022da2e3ebdSchin if (pp.ignoresrc > 1 && pp.stddirs != pp.firstdir)
1023da2e3ebdSchin error(1, "directories up to and including %s are for \"...\" include files only", pp.stddirs->name);
1024da2e3ebdSchin pp.lcldirs = pp.lcldirs->next;
1025da2e3ebdSchin }
1026da2e3ebdSchin if (pp.ignore)
1027da2e3ebdSchin {
1028da2e3ebdSchin if (*pp.ignore)
1029da2e3ebdSchin ppmapinclude(pp.ignore, NiL);
1030da2e3ebdSchin else
1031da2e3ebdSchin pp.ignore = 0;
1032da2e3ebdSchin }
1033da2e3ebdSchin if (pp.standalone)
1034da2e3ebdSchin pp.state |= STANDALONE;
1035da2e3ebdSchin #if COMPATIBLE
1036da2e3ebdSchin ppfsm(FSM_COMPATIBILITY, NiL);
1037da2e3ebdSchin #endif
1038da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL);
1039da2e3ebdSchin pp.initialized = 1;
1040da2e3ebdSchin if (pp.reset.on)
1041da2e3ebdSchin {
1042da2e3ebdSchin pp.reset.symtab = pp.symtab;
1043da2e3ebdSchin pp.symtab = 0;
1044da2e3ebdSchin pp.reset.ro_state = pp.ro_state;
1045da2e3ebdSchin pp.reset.ro_mode = pp.ro_mode;
1046da2e3ebdSchin pp.reset.ro_option = pp.ro_option;
1047da2e3ebdSchin }
1048da2e3ebdSchin }
1049da2e3ebdSchin if (pp.reset.on)
1050da2e3ebdSchin {
1051da2e3ebdSchin if (pp.symtab)
1052da2e3ebdSchin {
1053da2e3ebdSchin hashwalk(pp.filtab, 0, unguard, NiL);
1054da2e3ebdSchin hashfree(pp.symtab);
1055da2e3ebdSchin }
1056da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", HASH_free, undefine, HASH_set, HASH_ALLOCATE|HASH_BUCKET, 0);
1057da2e3ebdSchin hashview(pp.symtab, pp.reset.symtab);
1058da2e3ebdSchin pp.ro_state = pp.reset.ro_state;
1059da2e3ebdSchin pp.ro_mode = pp.reset.ro_mode;
1060da2e3ebdSchin pp.ro_option = pp.reset.ro_option;
1061da2e3ebdSchin }
1062da2e3ebdSchin #if CHECKPOINT
1063da2e3ebdSchin if (pp.mode & DUMP)
1064da2e3ebdSchin {
1065da2e3ebdSchin if (!pp.pragma)
1066da2e3ebdSchin error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
1067da2e3ebdSchin (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
1068da2e3ebdSchin }
1069da2e3ebdSchin #endif
1070da2e3ebdSchin if (n = pp.filedeps.flags)
1071da2e3ebdSchin {
1072da2e3ebdSchin if (!(n & PP_deps_file))
1073da2e3ebdSchin {
1074da2e3ebdSchin pp.state |= NOTEXT;
1075da2e3ebdSchin pp.option |= KEEPNOTEXT;
1076da2e3ebdSchin pp.linesync = 0;
1077da2e3ebdSchin }
1078da2e3ebdSchin if (n & PP_deps_generated)
1079da2e3ebdSchin pp.mode |= GENDEPS;
1080da2e3ebdSchin if (n & PP_deps_local)
1081da2e3ebdSchin pp.mode &= ~HEADERDEPS;
1082da2e3ebdSchin else if (!(pp.mode & FILEDEPS))
1083da2e3ebdSchin pp.mode |= HEADERDEPS;
1084da2e3ebdSchin pp.mode |= FILEDEPS;
1085da2e3ebdSchin }
1086da2e3ebdSchin
1087da2e3ebdSchin /*
1088da2e3ebdSchin * push the main input file -- special case for hosted mark
1089da2e3ebdSchin */
1090da2e3ebdSchin
1091da2e3ebdSchin if (pp.firstdir->type & TYPE_HOSTED)
1092da2e3ebdSchin pp.mode |= MARKHOSTED;
1093da2e3ebdSchin else
1094da2e3ebdSchin pp.mode &= ~MARKHOSTED;
1095da2e3ebdSchin #if CHECKPOINT
1096da2e3ebdSchin if (!(pp.mode & DUMP))
1097da2e3ebdSchin #endif
1098da2e3ebdSchin {
1099da2e3ebdSchin if (!(p = error_info.file))
1100da2e3ebdSchin p = "";
1101da2e3ebdSchin else
1102da2e3ebdSchin {
1103da2e3ebdSchin error_info.file = 0;
1104da2e3ebdSchin if (*p)
1105da2e3ebdSchin {
1106da2e3ebdSchin pathcanon(p, 0);
1107da2e3ebdSchin p = ppsetfile(p)->name;
1108da2e3ebdSchin }
1109da2e3ebdSchin }
1110da2e3ebdSchin PUSH_FILE(p, 0);
1111da2e3ebdSchin }
1112da2e3ebdSchin if (pp.mode & FILEDEPS)
1113da2e3ebdSchin {
1114da2e3ebdSchin if (s = strrchr(error_info.file, '/'))
1115da2e3ebdSchin s++;
1116da2e3ebdSchin else
1117da2e3ebdSchin s = error_info.file;
1118da2e3ebdSchin if (!*s)
1119da2e3ebdSchin s = "-";
1120da2e3ebdSchin s = strcpy(pp.tmpbuf, s);
1121da2e3ebdSchin if ((t = p = strrchr(s, '.')) && (*++p == 'c' || *p == 'C'))
1122da2e3ebdSchin {
1123da2e3ebdSchin if (c = *++p)
1124da2e3ebdSchin while (*++p == c);
1125da2e3ebdSchin if (*p)
1126da2e3ebdSchin t = 0;
1127da2e3ebdSchin else
1128da2e3ebdSchin t++;
1129da2e3ebdSchin }
1130da2e3ebdSchin if (!t)
1131da2e3ebdSchin {
1132da2e3ebdSchin t = s + strlen(s);
1133da2e3ebdSchin *t++ = '.';
1134da2e3ebdSchin }
1135da2e3ebdSchin *(t + 1) = 0;
1136da2e3ebdSchin if (pp.state & NOTEXT)
1137da2e3ebdSchin pp.filedeps.sp = sfstdout;
1138da2e3ebdSchin else
1139da2e3ebdSchin {
1140da2e3ebdSchin *t = 'd';
1141da2e3ebdSchin if (!(pp.filedeps.sp = sfopen(NiL, s, "w")))
1142da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot create", s);
1143da2e3ebdSchin }
1144da2e3ebdSchin *t = 'o';
1145da2e3ebdSchin pp.column = sfprintf(pp.filedeps.sp, "%s :", s);
1146da2e3ebdSchin if (*error_info.file)
1147da2e3ebdSchin pp.column += sfprintf(pp.filedeps.sp, " %s", error_info.file);
1148da2e3ebdSchin }
1149da2e3ebdSchin if (xp = pp.firsttx)
1150da2e3ebdSchin {
1151da2e3ebdSchin if (!(sp = sfstropen()))
1152da2e3ebdSchin error(3, "temporary buffer allocation error");
1153da2e3ebdSchin while (xp)
1154da2e3ebdSchin {
1155da2e3ebdSchin sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), xp->value);
1156da2e3ebdSchin xp = xp->next;
1157da2e3ebdSchin }
1158da2e3ebdSchin t = sfstruse(sp);
1159da2e3ebdSchin PUSH_BUFFER("options", t, 1);
1160da2e3ebdSchin sfstrclose(sp);
1161da2e3ebdSchin }
1162da2e3ebdSchin break;
1163da2e3ebdSchin case PP_INPUT:
1164da2e3ebdSchin #if CHECKPOINT && POOL
1165da2e3ebdSchin if (!(pp.mode & DUMP) || pp.pool.input)
1166da2e3ebdSchin #else
1167da2e3ebdSchin #if CHECKPOINT
1168da2e3ebdSchin if (!(pp.mode & DUMP))
1169da2e3ebdSchin #else
1170da2e3ebdSchin #if POOL
1171da2e3ebdSchin if (pp.pool.input)
1172da2e3ebdSchin #endif
1173da2e3ebdSchin #endif
1174da2e3ebdSchin #endif
1175da2e3ebdSchin {
1176da2e3ebdSchin p = va_arg(ap, char*);
1177da2e3ebdSchin if (!error_info.file)
1178da2e3ebdSchin error_info.file = p;
1179da2e3ebdSchin close(0);
1180da2e3ebdSchin if (open(p, O_RDONLY) != 0)
1181da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot read", p);
1182da2e3ebdSchin if (strmatch(p, "*.(s|S|as|AS|asm|ASM)"))
1183da2e3ebdSchin {
1184da2e3ebdSchin set(&pp.mode, CATLITERAL, 0);
1185da2e3ebdSchin ppop(PP_SPACEOUT, 1);
1186da2e3ebdSchin }
1187da2e3ebdSchin break;
1188da2e3ebdSchin }
1189da2e3ebdSchin /*FALLTHROUGH*/
1190da2e3ebdSchin case PP_TEXT:
1191da2e3ebdSchin if (pp.initialized)
1192da2e3ebdSchin goto before;
1193da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p)
1194da2e3ebdSchin {
1195da2e3ebdSchin if (pp.lasttx)
1196da2e3ebdSchin pp.lasttx = pp.lasttx->next = newof(0, struct oplist, 1, 0);
1197da2e3ebdSchin else
1198da2e3ebdSchin pp.firsttx = pp.lasttx = newof(0, struct oplist, 1, 0);
1199da2e3ebdSchin pp.lasttx->op = op;
1200da2e3ebdSchin pp.lasttx->value = p;
1201da2e3ebdSchin }
1202da2e3ebdSchin break;
1203da2e3ebdSchin case PP_KEYARGS:
1204da2e3ebdSchin if (pp.initialized)
1205da2e3ebdSchin goto before;
1206da2e3ebdSchin set(&pp.option, KEYARGS, va_arg(ap, int));
1207da2e3ebdSchin if (pp.option & KEYARGS)
1208da2e3ebdSchin #if MACKEYARGS
1209da2e3ebdSchin set(&pp.mode, CATLITERAL, 1);
1210da2e3ebdSchin #else
1211da2e3ebdSchin error(3, "preprocessor not compiled with macro keyword arguments enabled [MACKEYARGS]");
1212da2e3ebdSchin #endif
1213da2e3ebdSchin break;
1214da2e3ebdSchin case PP_LINE:
1215da2e3ebdSchin pp.linesync = va_arg(ap, PPLINESYNC);
1216da2e3ebdSchin break;
1217da2e3ebdSchin case PP_LINEBASE:
1218da2e3ebdSchin if (va_arg(ap, int))
1219da2e3ebdSchin pp.flags |= PP_linebase;
1220da2e3ebdSchin else
1221da2e3ebdSchin pp.flags &= ~PP_linebase;
1222da2e3ebdSchin break;
1223da2e3ebdSchin case PP_LINEFILE:
1224da2e3ebdSchin if (va_arg(ap, int))
1225da2e3ebdSchin pp.flags |= PP_linefile;
1226da2e3ebdSchin else
1227da2e3ebdSchin pp.flags &= ~PP_linefile;
1228da2e3ebdSchin break;
1229da2e3ebdSchin case PP_LINEID:
1230da2e3ebdSchin if (!(p = va_arg(ap, char*)))
1231da2e3ebdSchin pp.lineid = "";
1232da2e3ebdSchin else if (*p != '-')
1233da2e3ebdSchin pp.lineid = strdup(p);
1234da2e3ebdSchin else
1235da2e3ebdSchin pp.option |= IGNORELINE;
1236da2e3ebdSchin break;
1237da2e3ebdSchin case PP_LINETYPE:
1238da2e3ebdSchin if ((n = va_arg(ap, int)) >= 1)
1239da2e3ebdSchin pp.flags |= PP_linetype;
1240da2e3ebdSchin else
1241da2e3ebdSchin pp.flags &= ~PP_linetype;
1242da2e3ebdSchin if (n >= 2)
1243da2e3ebdSchin pp.flags |= PP_linehosted;
1244da2e3ebdSchin else
1245da2e3ebdSchin pp.flags &= ~PP_linehosted;
1246da2e3ebdSchin break;
1247da2e3ebdSchin case PP_LOCAL:
1248da2e3ebdSchin if (pp.initialized)
1249da2e3ebdSchin goto before;
1250da2e3ebdSchin pp.ignoresrc++;
1251da2e3ebdSchin pp.stddirs = pp.lastdir;
1252da2e3ebdSchin if (!(pp.ro_option & PREFIX))
1253da2e3ebdSchin pp.option &= ~PREFIX;
1254da2e3ebdSchin break;
1255da2e3ebdSchin case PP_MACREF:
1256da2e3ebdSchin pp.macref = va_arg(ap, PPMACREF);
1257da2e3ebdSchin break;
1258da2e3ebdSchin case PP_MULTIPLE:
1259da2e3ebdSchin set(&pp.mode, ALLMULTIPLE, va_arg(ap, int));
1260da2e3ebdSchin break;
1261da2e3ebdSchin case PP_NOHASH:
1262da2e3ebdSchin set(&pp.option, NOHASH, va_arg(ap, int));
1263da2e3ebdSchin break;
1264da2e3ebdSchin case PP_NOISE:
1265da2e3ebdSchin op = va_arg(ap, int);
1266da2e3ebdSchin set(&pp.option, NOISE, op);
1267da2e3ebdSchin set(&pp.option, NOISEFILTER, op < 0);
1268da2e3ebdSchin break;
1269da2e3ebdSchin case PP_OPTARG:
1270da2e3ebdSchin pp.optarg = va_arg(ap, PPOPTARG);
1271da2e3ebdSchin break;
1272da2e3ebdSchin case PP_OUTPUT:
1273da2e3ebdSchin pp.outfile = va_arg(ap, char*);
1274da2e3ebdSchin if (identical(pp.outfile, 0))
1275da2e3ebdSchin error(3, "%s: identical to input", pp.outfile);
1276da2e3ebdSchin close(1);
1277da2e3ebdSchin if (open(pp.outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
1278da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot create", pp.outfile);
1279da2e3ebdSchin break;
1280da2e3ebdSchin case PP_PASSTHROUGH:
1281da2e3ebdSchin if (!(pp.state & COMPILE))
1282da2e3ebdSchin set(&pp.state, PASSTHROUGH, va_arg(ap, int));
1283da2e3ebdSchin break;
1284da2e3ebdSchin case PP_PEDANTIC:
1285da2e3ebdSchin set(&pp.mode, PEDANTIC, va_arg(ap, int));
1286da2e3ebdSchin break;
1287da2e3ebdSchin case PP_PLUSCOMMENT:
1288da2e3ebdSchin set(&pp.option, PLUSCOMMENT, va_arg(ap, int));
1289da2e3ebdSchin if (pp.initialized)
1290da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL);
1291da2e3ebdSchin break;
1292da2e3ebdSchin case PP_PLUSPLUS:
1293da2e3ebdSchin set(&pp.option, PLUSPLUS, va_arg(ap, int));
1294da2e3ebdSchin set(&pp.option, PLUSCOMMENT, va_arg(ap, int));
1295da2e3ebdSchin if (pp.initialized)
1296da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL);
1297da2e3ebdSchin break;
1298da2e3ebdSchin case PP_POOL:
1299da2e3ebdSchin if (pp.initialized)
1300da2e3ebdSchin goto before;
1301da2e3ebdSchin if (va_arg(ap, int))
1302da2e3ebdSchin {
1303da2e3ebdSchin #if POOL
1304da2e3ebdSchin pp.pool.input = dup(0);
1305da2e3ebdSchin pp.pool.output = dup(1);
1306da2e3ebdSchin p = "/dev/null";
1307da2e3ebdSchin if (!identical(p, 0))
1308da2e3ebdSchin {
1309da2e3ebdSchin if (!identical(p, 1))
1310da2e3ebdSchin ppop(PP_OUTPUT, p);
1311da2e3ebdSchin ppop(PP_INPUT, p);
1312da2e3ebdSchin }
1313da2e3ebdSchin #else
1314da2e3ebdSchin error(3, "preprocessor not compiled with input pool enabled [POOL]");
1315da2e3ebdSchin #endif
1316da2e3ebdSchin }
1317da2e3ebdSchin break;
1318da2e3ebdSchin case PP_PRAGMA:
1319da2e3ebdSchin pp.pragma = va_arg(ap, PPPRAGMA);
1320da2e3ebdSchin break;
1321da2e3ebdSchin case PP_PRAGMAFLAGS:
1322da2e3ebdSchin if (p = va_arg(ap, char*))
1323da2e3ebdSchin {
1324da2e3ebdSchin n = OPT_GLOBAL;
1325da2e3ebdSchin if (*p == '-')
1326da2e3ebdSchin p++;
1327da2e3ebdSchin else
1328da2e3ebdSchin n |= OPT_PASS;
1329da2e3ebdSchin if ((c = (int)hashref(pp.strtab, p)) > 0 && c <= X_last_option)
1330da2e3ebdSchin pp.optflags[c] = n;
1331da2e3ebdSchin }
1332da2e3ebdSchin break;
1333da2e3ebdSchin case PP_PROBE:
1334da2e3ebdSchin pp.probe = va_arg(ap, char*);
1335da2e3ebdSchin break;
1336da2e3ebdSchin case PP_QUOTE:
1337da2e3ebdSchin p = va_arg(ap, char*);
1338da2e3ebdSchin c = va_arg(ap, int);
1339da2e3ebdSchin if (p)
1340da2e3ebdSchin ppfsm(c ? FSM_QUOTADD : FSM_QUOTDEL, p);
1341da2e3ebdSchin break;
1342da2e3ebdSchin case PP_REGUARD:
1343da2e3ebdSchin set(&pp.option, REGUARD, va_arg(ap, int));
1344da2e3ebdSchin break;
1345da2e3ebdSchin case PP_RESERVED:
1346da2e3ebdSchin if ((pp.state & COMPILE) && (p = va_arg(ap, char*)))
1347da2e3ebdSchin {
1348da2e3ebdSchin if (!(sp = sfstropen()))
1349da2e3ebdSchin error(3, "temporary buffer allocation error");
1350da2e3ebdSchin sfputr(sp, p, -1);
1351da2e3ebdSchin p = sfstruse(sp);
1352da2e3ebdSchin if (s = strchr(p, '='))
1353da2e3ebdSchin *s++ = 0;
1354da2e3ebdSchin else
1355da2e3ebdSchin s = p;
1356da2e3ebdSchin while (*s == '_')
1357da2e3ebdSchin s++;
1358da2e3ebdSchin for (t = s + strlen(s); t > s && *(t - 1) == '_'; t--);
1359da2e3ebdSchin if (*t == '_')
1360da2e3ebdSchin *t = 0;
1361da2e3ebdSchin else
1362da2e3ebdSchin t = 0;
1363da2e3ebdSchin op = ((key = ppkeyref(pp.symtab, s)) && (key->sym.flags & SYM_LEX)) ? key->lex : T_NOISE;
1364da2e3ebdSchin if (pp.test & 0x0400)
1365da2e3ebdSchin error(1, "reserved#1 `%s' %d", s, op);
1366da2e3ebdSchin if (t)
1367da2e3ebdSchin *t = '_';
1368da2e3ebdSchin if (!(key = ppkeyget(pp.symtab, p)))
1369da2e3ebdSchin key = ppkeyset(pp.symtab, NiL);
1370da2e3ebdSchin else if (!(key->sym.flags & SYM_LEX))
1371da2e3ebdSchin {
1372da2e3ebdSchin struct ppsymbol tmp;
1373da2e3ebdSchin
1374da2e3ebdSchin tmp = key->sym;
1375da2e3ebdSchin hashlook(pp.symtab, p, HASH_DELETE, NiL);
1376da2e3ebdSchin key = ppkeyset(pp.symtab, NiL);
1377da2e3ebdSchin key->sym.flags = tmp.flags;
1378da2e3ebdSchin key->sym.macro = tmp.macro;
1379da2e3ebdSchin key->sym.value = tmp.value;
1380da2e3ebdSchin key->sym.hidden = tmp.hidden;
1381da2e3ebdSchin }
1382da2e3ebdSchin if (!(key->sym.flags & SYM_KEYWORD))
1383da2e3ebdSchin {
1384da2e3ebdSchin key->sym.flags |= SYM_KEYWORD|SYM_LEX;
1385da2e3ebdSchin key->lex = op;
1386da2e3ebdSchin if (pp.test & 0x0400)
1387da2e3ebdSchin error(1, "reserved#2 `%s' %d", p, op);
1388da2e3ebdSchin }
1389da2e3ebdSchin sfstrclose(sp);
1390da2e3ebdSchin }
1391da2e3ebdSchin break;
1392da2e3ebdSchin case PP_SPACEOUT:
1393da2e3ebdSchin set(&pp.state, SPACEOUT, va_arg(ap, int));
1394da2e3ebdSchin break;
1395da2e3ebdSchin case PP_STANDALONE:
1396da2e3ebdSchin if (pp.initialized)
1397da2e3ebdSchin goto before;
1398da2e3ebdSchin pp.standalone = 1;
1399da2e3ebdSchin break;
1400da2e3ebdSchin case PP_STANDARD:
1401da2e3ebdSchin if ((pp.lastdir->next->name = ((p = va_arg(ap, char*)) && *p) ? p : NiL) && !stat(p, &st))
1402da2e3ebdSchin SAVEID(&pp.lastdir->next->id, &st);
1403da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
1404da2e3ebdSchin if (dp->name)
1405da2e3ebdSchin for (hp = pp.firstdir; hp != dp; hp = hp->next)
1406da2e3ebdSchin if (hp->name && SAMEID(&hp->id, &dp->id))
1407da2e3ebdSchin {
1408da2e3ebdSchin hp->c = dp->c;
1409da2e3ebdSchin if (dp->type & TYPE_HOSTED)
1410da2e3ebdSchin hp->type |= TYPE_HOSTED;
1411da2e3ebdSchin else
1412da2e3ebdSchin hp->type &= ~TYPE_HOSTED;
1413da2e3ebdSchin }
1414da2e3ebdSchin break;
1415da2e3ebdSchin case PP_STRICT:
1416da2e3ebdSchin set(&pp.state, TRANSITION, 0);
1417da2e3ebdSchin pp.flags &= ~PP_transition;
1418da2e3ebdSchin set(&pp.state, STRICT, va_arg(ap, int));
1419da2e3ebdSchin if (pp.state & STRICT)
1420da2e3ebdSchin pp.flags |= PP_strict;
1421da2e3ebdSchin else
1422da2e3ebdSchin pp.flags &= ~PP_strict;
1423da2e3ebdSchin break;
1424da2e3ebdSchin case PP_TEST:
1425da2e3ebdSchin if (p = va_arg(ap, char*))
1426da2e3ebdSchin for (;;)
1427da2e3ebdSchin {
1428da2e3ebdSchin while (*p == ' ' || *p == '\t') p++;
1429da2e3ebdSchin for (s = p; n = *s; s++)
1430da2e3ebdSchin if (n == ',' || n == ' ' || n == '\t')
1431da2e3ebdSchin {
1432da2e3ebdSchin *s++ = 0;
1433da2e3ebdSchin break;
1434da2e3ebdSchin }
1435da2e3ebdSchin if (!*p)
1436da2e3ebdSchin break;
1437da2e3ebdSchin n = 0;
1438da2e3ebdSchin if (*p == 'n' && *(p + 1) == 'o')
1439da2e3ebdSchin {
1440da2e3ebdSchin p += 2;
1441da2e3ebdSchin op = 0;
1442da2e3ebdSchin }
1443da2e3ebdSchin else
1444da2e3ebdSchin op = 1;
1445da2e3ebdSchin if (streq(p, "count"))
1446da2e3ebdSchin n = TEST_count;
1447da2e3ebdSchin else if (streq(p, "hashcount"))
1448da2e3ebdSchin n = TEST_hashcount;
1449da2e3ebdSchin else if (streq(p, "hashdump"))
1450da2e3ebdSchin n = TEST_hashdump;
1451da2e3ebdSchin else if (streq(p, "hit"))
1452da2e3ebdSchin n = TEST_hit;
1453da2e3ebdSchin else if (streq(p, "init"))
1454da2e3ebdSchin n = TEST_noinit|TEST_INVERT;
1455da2e3ebdSchin else if (streq(p, "noise"))
1456da2e3ebdSchin n = TEST_nonoise|TEST_INVERT;
1457da2e3ebdSchin else if (streq(p, "proto"))
1458da2e3ebdSchin n = TEST_noproto|TEST_INVERT;
1459da2e3ebdSchin else if (*p >= '0' && *p <= '9')
1460da2e3ebdSchin n = strtoul(p, NiL, 0);
1461da2e3ebdSchin else
1462da2e3ebdSchin {
1463da2e3ebdSchin error(1, "%s: unknown test", p);
1464da2e3ebdSchin break;
1465da2e3ebdSchin }
1466da2e3ebdSchin if (n & TEST_INVERT)
1467da2e3ebdSchin {
1468da2e3ebdSchin n &= ~TEST_INVERT;
1469da2e3ebdSchin op = !op;
1470da2e3ebdSchin }
1471da2e3ebdSchin if (op)
1472da2e3ebdSchin pp.test |= n;
1473da2e3ebdSchin else
1474da2e3ebdSchin pp.test &= ~n;
1475da2e3ebdSchin p = s;
1476da2e3ebdSchin debug((-4, "test = 0%o", pp.test));
1477da2e3ebdSchin }
1478da2e3ebdSchin break;
1479da2e3ebdSchin case PP_TRANSITION:
1480da2e3ebdSchin set(&pp.state, STRICT, 0);
1481da2e3ebdSchin pp.flags &= ~PP_strict;
1482da2e3ebdSchin set(&pp.state, TRANSITION, va_arg(ap, int));
1483da2e3ebdSchin if (pp.state & TRANSITION)
1484da2e3ebdSchin pp.flags |= PP_transition;
1485da2e3ebdSchin else
1486da2e3ebdSchin pp.flags &= ~PP_transition;
1487da2e3ebdSchin break;
1488da2e3ebdSchin case PP_TRUNCATE:
1489da2e3ebdSchin if (pp.initialized)
1490da2e3ebdSchin goto before;
1491da2e3ebdSchin if ((op = va_arg(ap, int)) < 0)
1492da2e3ebdSchin op = 0;
1493da2e3ebdSchin set(&pp.option, TRUNCATE, op);
1494da2e3ebdSchin if (pp.option & TRUNCATE)
1495da2e3ebdSchin {
1496da2e3ebdSchin Hash_bucket_t* b;
1497da2e3ebdSchin Hash_bucket_t* p;
1498da2e3ebdSchin Hash_position_t* pos;
1499da2e3ebdSchin Hash_table_t* tab;
1500da2e3ebdSchin
1501da2e3ebdSchin pp.truncate = op;
1502da2e3ebdSchin tab = pp.symtab;
1503da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_set, tab ? HASH_ALLOCATE : 0, HASH_compare, trunccomp, HASH_hash, trunchash, HASH_name, "truncate", 0);
1504da2e3ebdSchin if (tab && (pos = hashscan(tab, 0)))
1505da2e3ebdSchin {
1506da2e3ebdSchin if (p = hashnext(pos))
1507da2e3ebdSchin do
1508da2e3ebdSchin {
1509da2e3ebdSchin b = hashnext(pos);
1510da2e3ebdSchin hashlook(pp.symtab, (char*)p, HASH_BUCKET|HASH_INSTALL, NiL);
1511da2e3ebdSchin } while (p = b);
1512da2e3ebdSchin hashdone(pos);
1513da2e3ebdSchin }
1514da2e3ebdSchin }
1515da2e3ebdSchin else
1516da2e3ebdSchin pp.truncate = 0;
1517da2e3ebdSchin break;
1518da2e3ebdSchin case PP_VENDOR:
1519da2e3ebdSchin p = va_arg(ap, char*);
1520da2e3ebdSchin c = va_arg(ap, int) != 0;
1521da2e3ebdSchin if (!p || !*p)
1522da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
1523da2e3ebdSchin dp->type &= ~TYPE_VENDOR;
1524da2e3ebdSchin else if (streq(p, "-"))
1525da2e3ebdSchin {
1526da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
1527da2e3ebdSchin if (c)
1528da2e3ebdSchin dp->type |= TYPE_VENDOR;
1529da2e3ebdSchin else
1530da2e3ebdSchin dp->type &= ~TYPE_VENDOR;
1531da2e3ebdSchin }
1532da2e3ebdSchin else if (!stat((pathcanon(p, 0), p), &st))
1533da2e3ebdSchin {
1534da2e3ebdSchin c = 0;
1535da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next)
1536da2e3ebdSchin {
1537da2e3ebdSchin if (!c && ((dp->type & TYPE_VENDOR) || dp->name && SAMEID(&dp->id, &st)))
1538da2e3ebdSchin c = 1;
1539da2e3ebdSchin if (c)
1540da2e3ebdSchin dp->type |= TYPE_VENDOR;
1541da2e3ebdSchin else
1542da2e3ebdSchin dp->type &= ~TYPE_VENDOR;
1543da2e3ebdSchin }
1544da2e3ebdSchin }
1545da2e3ebdSchin break;
1546da2e3ebdSchin case PP_WARN:
1547da2e3ebdSchin set(&pp.state, WARN, va_arg(ap, int));
1548da2e3ebdSchin break;
1549da2e3ebdSchin before:
1550da2e3ebdSchin error(3, "ppop(%d): preprocessor operation must be done before PP_INIT", op);
1551da2e3ebdSchin break;
1552da2e3ebdSchin default:
1553da2e3ebdSchin error(3, "ppop(%d): invalid preprocessor operation", op);
1554da2e3ebdSchin break;
1555da2e3ebdSchin }
1556da2e3ebdSchin va_end(ap);
1557da2e3ebdSchin }
1558