1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1986-2009 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * Glenn Fowler
23 * AT&T Research
24 *
25 * miscellaneous preprocessor support
26 */
27
28 #include "pplib.h"
29
30 /*
31 * macro symbol def|ref
32 */
33
34 struct ppsymbol*
pprefmac(char * name,int ref)35 pprefmac(char* name, int ref)
36 {
37 register struct ppsymbol* sym;
38
39 if (!(sym = ppsymget(pp.symtab, name)) && (ref <= REF_NORMAL && pp.macref || ref == REF_CREATE || ref == REF_DELETE && (pp.mode & (INIT|READONLY))))
40 {
41 if ((pp.state & COMPILE) && pp.truncate && strlen(name) > pp.truncate)
42 name[pp.truncate] = 0;
43 sym = ppsymset(pp.symtab, NiL);
44 }
45 if (sym && ref <= REF_NORMAL)
46 {
47 if (pp.macref) (*pp.macref)(sym, error_info.file, error_info.line, ref == REF_NORMAL && (pp.state & CONDITIONAL) ? REF_IF : ref, 0L);
48 if (!sym->macro) sym = 0;
49 }
50 #if COMPATIBLE
51 if (!(pp.state & COMPATIBILITY))
52 #endif
53 if (ref == REF_IF && sym && (sym->flags & SYM_PREDEFINED) && *name != '_' && !(pp.mode & (HOSTED|INACTIVE)))
54 {
55 if (pp.state & STRICT)
56 {
57 error(1, "%s: obsolete predefined symbol reference disabled", name);
58 return(0);
59 }
60 error(1, "%s: obsolete predefined symbol referenced", name);
61 }
62 return(sym);
63 }
64
65 /*
66 * common predicate assertion operations
67 * op is DEFINE or UNDEF
68 */
69
70 void
ppassert(int op,char * pred,char * args)71 ppassert(int op, char* pred, char* args)
72 {
73 register struct pplist* a;
74 register struct ppsymbol* sym;
75 register struct pplist* p;
76 register struct pplist* q;
77
78 if (!args) switch (op)
79 {
80 case DEFINE:
81 goto mark;
82 case UNDEF:
83 a = 0;
84 goto unmark;
85 }
86 if (a = (struct pplist*)hashget(pp.prdtab, pred))
87 {
88 p = 0;
89 q = a;
90 while (q)
91 {
92 if (streq(q->value, args))
93 {
94 if (op == DEFINE) return;
95 q = q->next;
96 if (p) p->next = q;
97 else a = q;
98 }
99 else
100 {
101 p = q;
102 q = q->next;
103 }
104 }
105 if (op == UNDEF)
106 {
107 unmark:
108 hashput(pp.prdtab, pred, a);
109 if (sym = ppsymref(pp.symtab, pred))
110 sym->flags &= ~SYM_PREDICATE;
111 return;
112 }
113 }
114 if (op == DEFINE)
115 {
116 p = newof(0, struct pplist, 1, 0);
117 p->next = a;
118 p->value = strdup(args);
119 hashput(pp.prdtab, NiL, p);
120 mark:
121 if ((pp.state & COMPILE) && pp.truncate) return;
122 if (sym = ppsymset(pp.symtab, pred))
123 sym->flags |= SYM_PREDICATE;
124 }
125 }
126
127 /*
128 * parse a predicate argument list
129 * the args are placed in pp.args
130 * the first non-space/paren argument token type is returned
131 * forms:
132 *
133 * predicate <identifier> type=T_ID
134 * predicate ( <identifier> ) type=T_ID
135 * predicate ( ) type=0
136 * predicate ( <balanced-paren-list> ) type=T_STRING
137 * otherwise type=<other>
138 */
139
140 int
pppredargs(void)141 pppredargs(void)
142 {
143 register int c;
144 register int n;
145 register int type;
146 char* pptoken;
147
148 pptoken = pp.token;
149 pp.token = pp.args;
150 switch (type = pplex())
151 {
152 case '(':
153 type = 0;
154 n = 1;
155 pp.state |= HEADER;
156 pp.state &= ~STRIP;
157 c = pplex();
158 pp.state &= ~NOSPACE;
159 for (;;)
160 {
161 switch (c)
162 {
163 case '(':
164 n++;
165 break;
166 case '\n':
167 ungetchr(c);
168 error(2, "missing %d )%s in predicate argument list", n, n == 1 ? "" : "'s");
169 type = 0;
170 goto done;
171 case ')':
172 if (!--n) goto done;
173 break;
174 }
175 pp.token = pp.toknxt;
176 if (c != ' ')
177 {
178 if (type) type = T_STRING;
179 else type = (c == T_ID) ? T_ID : T_STRING;
180 }
181 c = pplex();
182 }
183 done:
184 pp.state &= ~HEADER;
185 pp.state |= NOSPACE|STRIP;
186 if (pp.token > pp.args && *(pp.token - 1) == ' ') pp.token--;
187 *pp.token = 0;
188 break;
189 case '\n':
190 ungetchr('\n');
191 type = 0;
192 break;
193 }
194 pp.token = pptoken;
195 return(type);
196 }
197
198 /*
199 * sync output line number
200 */
201
202 int
ppsync(void)203 ppsync(void)
204 {
205 long m;
206
207 if ((pp.state & (ADD|HIDDEN)))
208 {
209 if (pp.state & ADD)
210 {
211 pp.state &= ~ADD;
212 m = pp.addp - pp.addbuf;
213 pp.addp = pp.addbuf;
214 ppprintf("%-.*s", m, pp.addbuf);
215 }
216 if (pp.linesync)
217 {
218 if ((pp.state & SYNCLINE) || pp.hidden >= MAXHIDDEN)
219 {
220 pp.hidden = 0;
221 pp.state &= ~(HIDDEN|SYNCLINE);
222 if (error_info.line)
223 (*pp.linesync)(error_info.line, error_info.file);
224 }
225 else
226 {
227 m = pp.hidden;
228 pp.hidden = 0;
229 pp.state &= ~HIDDEN;
230 while (m-- > 0)
231 ppputchar('\n');
232 }
233 }
234 else
235 {
236 pp.hidden = 0;
237 pp.state &= ~HIDDEN;
238 ppputchar('\n');
239 }
240 }
241 return 0;
242 }
243