1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1986-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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