1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1986-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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 macro call
26da2e3ebdSchin  */
27da2e3ebdSchin 
28da2e3ebdSchin #include "pplib.h"
29da2e3ebdSchin 
30da2e3ebdSchin #include <ctype.h>
31da2e3ebdSchin 
32da2e3ebdSchin /*
33da2e3ebdSchin  * call a macro by pushing its value on the input stream
34da2e3ebdSchin  * only the macro token itself has been consumed
35da2e3ebdSchin  * -1 returned if macro disabled
36da2e3ebdSchin  *  0 returned if tok==0 and sym->mac->value to be copied to output by caller
37da2e3ebdSchin  *  1 returned if value pushed on input
38da2e3ebdSchin  */
39da2e3ebdSchin 
40da2e3ebdSchin int
ppcall(register struct ppsymbol * sym,int tok)41da2e3ebdSchin ppcall(register struct ppsymbol* sym, int tok)
42da2e3ebdSchin {
43da2e3ebdSchin 	register int			c;
44da2e3ebdSchin 	register char*			p;
45da2e3ebdSchin 	register char*			q;
46da2e3ebdSchin 	register struct ppmacro*	mac;
47da2e3ebdSchin 	int				n;
48da2e3ebdSchin 	int				m;
49da2e3ebdSchin 	int				ret;
50da2e3ebdSchin 	int				old_hidden;
51da2e3ebdSchin 	int				last_line;
52da2e3ebdSchin 	long				old_state;
53da2e3ebdSchin 	char*				last_file;
5434f9b3eeSRoland Mainz 	char*				old_next;
55da2e3ebdSchin 	char*				old_token;
56da2e3ebdSchin 	struct ppmacstk*		mp;
57da2e3ebdSchin 	struct ppinstk*			old_in;
58da2e3ebdSchin 	struct ppinstk*			kp;
59da2e3ebdSchin 	struct pptuple*			tp;
60da2e3ebdSchin 
61da2e3ebdSchin 	ret = -1;
62da2e3ebdSchin 	sym->flags |= SYM_NOTICED;
63da2e3ebdSchin 	if (mac = sym->macro)
64da2e3ebdSchin 	{
65da2e3ebdSchin 		count(macro);
66da2e3ebdSchin 		if ((sym->flags & SYM_PREDICATE) && (pp.state & (CONDITIONAL|WARN)) == (CONDITIONAL|WARN))
67da2e3ebdSchin 			error(1, "%s: macro definition overrides assertion: use #%s ...", sym->name, sym->name);
68da2e3ebdSchin 		if (sym->flags & SYM_DISABLED)
69da2e3ebdSchin #if COMPATIBLE
70da2e3ebdSchin 			if ((pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY || !mac->arity)
71da2e3ebdSchin #endif
72da2e3ebdSchin 		{
73da2e3ebdSchin 			pp.mode |= MARKMACRO;
74da2e3ebdSchin #if COMPATIBLE
75da2e3ebdSchin 			if ((pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
76da2e3ebdSchin 				error(1, "%s: macro recursion inhibited", sym->name);
77da2e3ebdSchin #endif
78da2e3ebdSchin 			goto disable;
79da2e3ebdSchin 		}
80da2e3ebdSchin 		if ((sym->flags & SYM_PREDEFINED) && !(pp.mode & (HOSTED|INACTIVE)))
81da2e3ebdSchin 		{
82da2e3ebdSchin #if COMPATIBLE
83da2e3ebdSchin 			if (*sym->name != '_' && !(pp.state & COMPATIBILITY))
84da2e3ebdSchin #else
85da2e3ebdSchin 			if (*sym->name != '_')
86da2e3ebdSchin #endif
87da2e3ebdSchin 			{
88da2e3ebdSchin 				if (pp.state & STRICT)
89da2e3ebdSchin 				{
90da2e3ebdSchin 					error(1, "%s: obsolete predefined symbol expansion disabled", sym->name);
91da2e3ebdSchin 					goto disable;
92da2e3ebdSchin 				}
93da2e3ebdSchin 				error(1, "%s: obsolete predefined symbol expanded%s", sym->name, (pp.state & DIRECTIVE) ? "" : " outside of directive");
94da2e3ebdSchin 			}
95da2e3ebdSchin 			else if (!(pp.state & DIRECTIVE) && mac->value && (ppisdig(*mac->value) || *mac->value == '#'))
96da2e3ebdSchin 				error(1, "%s: predefined symbol expanded outside of directive", sym->name);
97da2e3ebdSchin 		}
98da2e3ebdSchin 		debug((-5, "macro %s = %s", sym->name, mac->value));
99da2e3ebdSchin 		if (pp.macref)
100da2e3ebdSchin 			(*pp.macref)(sym, error_info.file, error_info.line, (pp.state & CONDITIONAL) ? REF_IF : REF_NORMAL, 0L);
101da2e3ebdSchin 		if (tp = mac->tuple)
102da2e3ebdSchin 		{
103da2e3ebdSchin 			old_state = pp.state;
104da2e3ebdSchin 			pp.state |= DEFINITION|NOSPACE;
105da2e3ebdSchin 			old_token = pp.token;
106da2e3ebdSchin 			n = 2 * MAXTOKEN;
107da2e3ebdSchin 			pp.token = p = oldof(0, char, 0, n);
108da2e3ebdSchin 			q = p + MAXTOKEN;
109da2e3ebdSchin 			*pp.token++ = ' ';
110da2e3ebdSchin 			old_hidden = pp.hidden;
111da2e3ebdSchin 			while (c = pplex())
112da2e3ebdSchin 			{
113da2e3ebdSchin 				if (c == '\n')
114da2e3ebdSchin 				{
115da2e3ebdSchin 					pp.hidden++;
116da2e3ebdSchin 					pp.state |= HIDDEN|NEWLINE;
117da2e3ebdSchin 					old_state |= HIDDEN|NEWLINE;
118da2e3ebdSchin 					error_info.line++;
119da2e3ebdSchin 				}
120da2e3ebdSchin 				else if (c == '#')
121da2e3ebdSchin 				{
122da2e3ebdSchin 					ungetchr(c);
123da2e3ebdSchin 					break;
124da2e3ebdSchin 				}
125da2e3ebdSchin 				else
126da2e3ebdSchin 				{
127da2e3ebdSchin 					for (;;)
128da2e3ebdSchin 					{
129da2e3ebdSchin 						if (streq(pp.token, tp->token))
130da2e3ebdSchin 						{
131da2e3ebdSchin 							if (!(tp = tp->match))
132da2e3ebdSchin 								break;
133da2e3ebdSchin 							if (!tp->nomatch)
134da2e3ebdSchin 							{
135da2e3ebdSchin 								free(p);
136da2e3ebdSchin 								pp.state = old_state;
137da2e3ebdSchin 								pp.token = old_token;
138da2e3ebdSchin 								PUSH_TUPLE(sym, tp->token);
139da2e3ebdSchin 								ret = 1;
140da2e3ebdSchin 								goto disable;
141da2e3ebdSchin 							}
142da2e3ebdSchin 						}
143da2e3ebdSchin 						else if (!(tp = tp->nomatch))
144da2e3ebdSchin 							break;
145da2e3ebdSchin 					}
146da2e3ebdSchin 					if (!tp)
147da2e3ebdSchin 					{
148da2e3ebdSchin 						pp.token = pp.toknxt;
149da2e3ebdSchin 						break;
150da2e3ebdSchin 					}
151da2e3ebdSchin 				}
152da2e3ebdSchin 				if ((pp.token = pp.toknxt) > q)
153da2e3ebdSchin 				{
154da2e3ebdSchin 					c = pp.token - p;
155da2e3ebdSchin 					p = newof(p, char, n += MAXTOKEN, 0);
156da2e3ebdSchin 					q = p + n - MAXTOKEN;
157da2e3ebdSchin 					pp.token = p + c;
158da2e3ebdSchin 				}
159da2e3ebdSchin 				*pp.token++ = ' ';
160da2e3ebdSchin 			}
161da2e3ebdSchin 			if (pp.token > p && *(pp.token - 1) == ' ')
162da2e3ebdSchin 				pp.token--;
163da2e3ebdSchin 			if (pp.hidden != old_hidden)
164da2e3ebdSchin 				*pp.token++ = '\n';
165da2e3ebdSchin 			else
166da2e3ebdSchin 				*pp.token++ = ' ';
167da2e3ebdSchin 			*pp.token = 0;
168da2e3ebdSchin 			pp.state = old_state;
169da2e3ebdSchin 			pp.token = old_token;
170da2e3ebdSchin 			if (*p)
171da2e3ebdSchin 				PUSH_RESCAN(p);
172da2e3ebdSchin 			else
173da2e3ebdSchin 				free(p);
174da2e3ebdSchin 			if (!mac->value)
175da2e3ebdSchin 				goto disable;
176da2e3ebdSchin 		}
177da2e3ebdSchin 		if (sym->flags & SYM_FUNCTION)
178da2e3ebdSchin 		{
179da2e3ebdSchin 			/*
180da2e3ebdSchin 			 * a quick and dirty '(' peek to avoid possibly
181da2e3ebdSchin 			 * inappropriate ungetchr()'s below
182da2e3ebdSchin 			 */
183da2e3ebdSchin 
184da2e3ebdSchin 			for (p = pp.in->nextchr; isspace(*p); p++);
185da2e3ebdSchin 			if ((c = *p) != '(' && c != '/' && c != 0 && c != MARK)
186da2e3ebdSchin 				goto disable;
18734f9b3eeSRoland Mainz 			old_next = (c == MARK) ? pp.in->nextchr : NiL;
188da2e3ebdSchin 			old_token = pp.token;
189da2e3ebdSchin 			mp = pp.macp->next;
190da2e3ebdSchin 			if ((pp.token = (char*)&mp->arg[mac->arity + 1]) > pp.maxmac)
191da2e3ebdSchin 				error(3, "%s: too many nested function-like macros", sym->name);
192da2e3ebdSchin 			old_hidden = pp.hidden;
193da2e3ebdSchin 			old_state = pp.state;
194da2e3ebdSchin 			pp.state |= DEFINITION|FILEPOP|NOSPACE;
195da2e3ebdSchin 			while ((c = pplex()) == '\n')
196da2e3ebdSchin 			{
197da2e3ebdSchin 				pp.hidden++;
198da2e3ebdSchin 				pp.state |= HIDDEN|NEWLINE;
199da2e3ebdSchin 				old_state |= HIDDEN|NEWLINE;
200da2e3ebdSchin 				error_info.line++;
201da2e3ebdSchin 			}
202da2e3ebdSchin 			if (c != '(')
203da2e3ebdSchin 			{
204da2e3ebdSchin 				pp.state = old_state;
20534f9b3eeSRoland Mainz 				if (old_next)
20634f9b3eeSRoland Mainz 					pp.in->nextchr = old_next;
20734f9b3eeSRoland Mainz 				else
208da2e3ebdSchin 				{
20934f9b3eeSRoland Mainz 					if (c)
21034f9b3eeSRoland Mainz 					{
21134f9b3eeSRoland Mainz 						p = pp.toknxt;
21234f9b3eeSRoland Mainz 						while (p > pp.token)
21334f9b3eeSRoland Mainz 							ungetchr(*--p);
214da2e3ebdSchin #if COMPATIBLE
21534f9b3eeSRoland Mainz 						if ((pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
21634f9b3eeSRoland Mainz 							error(1, "%s: macro arguments omitted", sym->name);
217da2e3ebdSchin #endif
21834f9b3eeSRoland Mainz 						if (c == T_ID && !(pp.state & HIDDEN))
21934f9b3eeSRoland Mainz 							ungetchr(' ');
22034f9b3eeSRoland Mainz 					}
22134f9b3eeSRoland Mainz 					if (pp.hidden != old_hidden)
22234f9b3eeSRoland Mainz 					{
22334f9b3eeSRoland Mainz 						ungetchr('\n');
22434f9b3eeSRoland Mainz 						error_info.line--;
22534f9b3eeSRoland Mainz 						if (pp.hidden && !--pp.hidden)
22634f9b3eeSRoland Mainz 							pp.state &= ~HIDDEN;
22734f9b3eeSRoland Mainz 					}
228da2e3ebdSchin 				}
229da2e3ebdSchin 				pp.token = old_token;
230da2e3ebdSchin 				goto disable;
231da2e3ebdSchin 			}
232da2e3ebdSchin 			pp.state = old_state;
233da2e3ebdSchin 
234da2e3ebdSchin 			/*
235da2e3ebdSchin 			 * arg[i][-1] is an extra char for each actual i
236da2e3ebdSchin 			 * for a possible ungetchr('"') during IN_QUOTE
237da2e3ebdSchin 			 * arg[i][-1]==0 if arg i need not be expanded
238da2e3ebdSchin 			 * arg[0][-2] holds the actual arg count
239da2e3ebdSchin 			 */
240da2e3ebdSchin 
241da2e3ebdSchin 			c = 0;
242da2e3ebdSchin 			m = 0;
243da2e3ebdSchin 			n = 0;
244da2e3ebdSchin 			mp = pp.macp->next;
245da2e3ebdSchin 			p = pp.token = (char*)&mp->arg[mac->arity + 1];
246da2e3ebdSchin 			pp.state |= COLLECTING|NOEXPAND;
247da2e3ebdSchin 			pp.state &= ~FILEPOP;
248da2e3ebdSchin 			sym->flags |= SYM_ACTIVE;
249da2e3ebdSchin 			old_in = pp.in;
250da2e3ebdSchin 			last_line = error_info.line;
251da2e3ebdSchin 			last_file = error_info.file;
252da2e3ebdSchin 			mp->line = error_info.line;
253da2e3ebdSchin #if MACKEYARGS
254da2e3ebdSchin 			if (pp.option & KEYARGS)
255da2e3ebdSchin 			{
256da2e3ebdSchin 				for (c = 0; c < mac->arity; c++)
257da2e3ebdSchin 					mp->arg[c] = mac->args.key[c].value + 1;
258da2e3ebdSchin 				mp->arg[0]++;
259da2e3ebdSchin 			}
260da2e3ebdSchin 			else
261da2e3ebdSchin #endif
262da2e3ebdSchin 			{
263da2e3ebdSchin 				*++p = ' ';
264da2e3ebdSchin 				mp->arg[0] = ++p;
265da2e3ebdSchin 			}
266da2e3ebdSchin #if MACKEYARGS
267da2e3ebdSchin 		keyarg:
268da2e3ebdSchin 			if (pp.option & KEYARGS)
269da2e3ebdSchin 			{
270da2e3ebdSchin 				pp.state |= NOSPACE;
271da2e3ebdSchin 				switch (pplex())
272da2e3ebdSchin 				{
273da2e3ebdSchin 				case T_ID:
274da2e3ebdSchin 					break;
275da2e3ebdSchin 				case ')':	/* no actual key args */
276da2e3ebdSchin 					if (!(pp.state & NOEXPAND))
277da2e3ebdSchin 						pp.state |= NOEXPAND;
278da2e3ebdSchin 					for (c = 0; c < mac->arity; c++)
279da2e3ebdSchin 						mp->arg[c][-1] = 0;
280da2e3ebdSchin 					c = 0;
281da2e3ebdSchin 					goto endactuals;
282da2e3ebdSchin 				default:
283da2e3ebdSchin 					error(3, "%s: invalid keyword macro argument", pp.token);
284da2e3ebdSchin 					break;
285da2e3ebdSchin 				}
286da2e3ebdSchin 				for (c = 0; c < mac->arity; c++)
287da2e3ebdSchin 					if (streq(pp.token, mac->args.key[c].name)) break;
288da2e3ebdSchin 				if (c >= mac->arity)
289da2e3ebdSchin 					error(2, "%s: invalid macro argument keyword", pp.token);
290da2e3ebdSchin 				if (pplex() != '=')
291da2e3ebdSchin 					error(2, "= expected in keyword macro argument");
292da2e3ebdSchin 				pp.state &= ~NOSPACE;
293da2e3ebdSchin 				if (!c)
294da2e3ebdSchin 					p++;
295da2e3ebdSchin 				pp.token = mp->arg[c] = ++p;
296da2e3ebdSchin 			}
297da2e3ebdSchin #endif
298da2e3ebdSchin 			for (;;)
299da2e3ebdSchin 			{
300da2e3ebdSchin 				if ((pp.mactop = pp.token = p) >= pp.maxmac)
301da2e3ebdSchin 					error(3, "%s: too many nested function-like macros", sym->name);
302da2e3ebdSchin 				switch (pplex())
303da2e3ebdSchin 				{
304da2e3ebdSchin 				case '(':
305da2e3ebdSchin 					n++;
306da2e3ebdSchin 					break;
307da2e3ebdSchin 				case ')':
308da2e3ebdSchin 					if (!n--)
309da2e3ebdSchin 					{
310da2e3ebdSchin 						if (p > mp->arg[c] && *(p - 1) == ' ')
311da2e3ebdSchin 							p--;
312da2e3ebdSchin 						if (p > mp->arg[c] && *(p - 1) == '\\')
313da2e3ebdSchin 						{
314da2e3ebdSchin 							for (q = mp->arg[c]; q < p; q++)
315da2e3ebdSchin 								if (*q == '\\')
316da2e3ebdSchin 									q++;
317da2e3ebdSchin 							if (q > p)
318da2e3ebdSchin 								*p++ = '\\';
319da2e3ebdSchin 						}
320da2e3ebdSchin #if MACKEYARGS
321da2e3ebdSchin 						*p = 0;
322da2e3ebdSchin 						m++;
323da2e3ebdSchin #endif
324da2e3ebdSchin 						goto endactuals;
325da2e3ebdSchin 					}
326da2e3ebdSchin 					break;
327da2e3ebdSchin 				case ',':
328da2e3ebdSchin 					if (!n && (m++, (c < mac->arity - 1 || !(sym->flags & SYM_VARIADIC))))
329da2e3ebdSchin 					{
330da2e3ebdSchin 						if (p > mp->arg[c] && *(p - 1) == ' ')
331da2e3ebdSchin 							p--;
332da2e3ebdSchin 						*p++ = 0;
333da2e3ebdSchin 						if (!(pp.state & NOEXPAND))
334da2e3ebdSchin 							pp.state |= NOEXPAND;
335da2e3ebdSchin 						else
336da2e3ebdSchin 							mp->arg[c][-1] = 0;
337da2e3ebdSchin #if MACKEYARGS
338da2e3ebdSchin 						if (pp.option & KEYARGS)
339da2e3ebdSchin 						{
340da2e3ebdSchin 							pp.token = p + 1;
341da2e3ebdSchin 							goto keyarg;
342da2e3ebdSchin 						}
343da2e3ebdSchin #endif
344da2e3ebdSchin 						{
345da2e3ebdSchin 							if ((pp.state & STRICT) && p == mp->arg[c])
346da2e3ebdSchin 								error(1, "%s: macro call argument %d is null", sym->name, c + 1);
347da2e3ebdSchin 							if (c < mac->arity)
348da2e3ebdSchin 								c++;
349da2e3ebdSchin 							*p++ = ' ';
350da2e3ebdSchin 						}
351da2e3ebdSchin 						pp.toknxt = mp->arg[c] = p;
352da2e3ebdSchin 					}
353da2e3ebdSchin 					break;
354da2e3ebdSchin 				case 0:
355da2e3ebdSchin 					if (pp.in == old_in)
356da2e3ebdSchin 						kp = 0;
357da2e3ebdSchin 					else
358da2e3ebdSchin 						for (kp = pp.in; kp && kp != old_in; kp = kp->prev);
359da2e3ebdSchin 					if (!kp)
360da2e3ebdSchin 					{
361da2e3ebdSchin 						error(
362da2e3ebdSchin #if COMPATIBLE
363da2e3ebdSchin 							(pp.state & COMPATIBILITY) ? 3 :
364da2e3ebdSchin #endif
365da2e3ebdSchin 							2, "%s: %s in macro argument list", sym->name, pptokchr(0));
366da2e3ebdSchin 						goto endactuals;
367da2e3ebdSchin 					}
368da2e3ebdSchin 					continue;
369da2e3ebdSchin 				case '\n':
370da2e3ebdSchin 					pp.state |= HIDDEN;
371da2e3ebdSchin 					error_info.line++;
372da2e3ebdSchin 					pp.hidden++;
373da2e3ebdSchin 					/*FALLTHROUGH*/
374da2e3ebdSchin 				case ' ':
375da2e3ebdSchin 					if (p > mp->arg[c] && *(p - 1) != ' ') *p++ = ' ';
376da2e3ebdSchin 					continue;
377da2e3ebdSchin 				}
378da2e3ebdSchin 				p = pp.toknxt;
379da2e3ebdSchin 				if (error_info.line != last_line)
380da2e3ebdSchin 				{
381da2e3ebdSchin 					SETLINE(p, error_info.line);
382da2e3ebdSchin 					last_line = error_info.line;
383da2e3ebdSchin 				}
384da2e3ebdSchin 				if (error_info.file != last_file)
385da2e3ebdSchin 				{
386da2e3ebdSchin 					SETFILE(p, error_info.file);
387da2e3ebdSchin 					last_file = error_info.file;
388da2e3ebdSchin 				}
389da2e3ebdSchin 			}
390da2e3ebdSchin  endactuals:
391da2e3ebdSchin 			if (pp.state & NOEXPAND)
392da2e3ebdSchin 				mp->arg[c][-1] = 0;
393da2e3ebdSchin 			pp.token = old_token;
394da2e3ebdSchin 			if (pp.in != old_in)
395da2e3ebdSchin 			{
396da2e3ebdSchin 				for (kp = pp.in; kp && kp != old_in; kp = kp->prev);
397da2e3ebdSchin 				if (kp)
398da2e3ebdSchin 					error(2, "%s: macro call starts and ends in different files", sym->name);
399da2e3ebdSchin 			}
400da2e3ebdSchin 			pp.state &= ~(COLLECTING|FILEPOP|NOEXPAND);
401da2e3ebdSchin 			sym->flags &= ~SYM_ACTIVE;
402da2e3ebdSchin #if MACKEYARGS
403da2e3ebdSchin 			if (!(pp.option & KEYARGS))
404da2e3ebdSchin #endif
405da2e3ebdSchin 			{
406da2e3ebdSchin 				if (p > mp->arg[0] && ++m || (sym->flags & SYM_VARIADIC))
407da2e3ebdSchin 					c++;
408*b30d1939SAndy Fiddaman 				if (c != (n = mac->arity) && (c > 0 || n > 1) && !(sym->flags & SYM_EMPTY))
409da2e3ebdSchin 				{
410da2e3ebdSchin 					if (!(sym->flags & SYM_VARIADIC))
411da2e3ebdSchin 						error(1, "%s: %d actual argument%s expected", sym->name, n, n == 1 ? "" : "s");
412da2e3ebdSchin 					else if (c < --n)
413da2e3ebdSchin 						error(1, "%s: at least %d actual argument%s expected", sym->name, n, n == 1 ? "" : "s");
414da2e3ebdSchin #if COMPATIBLE
415da2e3ebdSchin 					if (!c && (pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
416da2e3ebdSchin 						goto disable;
417da2e3ebdSchin #endif
418da2e3ebdSchin 				}
419da2e3ebdSchin 				if (!c)
420da2e3ebdSchin 					++c;
421da2e3ebdSchin 				while (c < mac->arity)
422da2e3ebdSchin 					mp->arg[c++] = (char*)"\0" + 1;
423da2e3ebdSchin 			}
424da2e3ebdSchin 			mp->arg[0][-2] = m;
425da2e3ebdSchin 			*p++ = 0;
426da2e3ebdSchin 			nextframe(mp, p);
427da2e3ebdSchin 			count(function);
428da2e3ebdSchin 		}
429da2e3ebdSchin 		if (!tok && (sym->flags & SYM_NOEXPAND))
430da2e3ebdSchin 		{
431da2e3ebdSchin 			if (sym->flags & SYM_FUNCTION)
432da2e3ebdSchin 				popframe(mp);
433da2e3ebdSchin 			ret = !mac->size;
434da2e3ebdSchin 		}
435da2e3ebdSchin 		else if (!(pp.state & HEADER) || (pp.option & HEADEREXPANDALL)  || pp.in->type != IN_COPY)
436da2e3ebdSchin 		{
437da2e3ebdSchin 			if (sym->flags & SYM_MULTILINE)
438da2e3ebdSchin 				PUSH_MULTILINE(sym);
439da2e3ebdSchin 			else
440da2e3ebdSchin 				PUSH_MACRO(sym);
441da2e3ebdSchin 			ret = 1;
442da2e3ebdSchin 		}
443da2e3ebdSchin 	}
444da2e3ebdSchin  disable:
445da2e3ebdSchin 	if (ret < 0 && sym->hidden && !(pp.mode & EXPOSE) && !(pp.state & HEADER) && (pp.in->type == IN_FILE || pp.in->type == IN_MACRO || pp.in->type == IN_EXPAND))
446da2e3ebdSchin 	{
447da2e3ebdSchin 		struct ppinstk*	inp;
448da2e3ebdSchin 
449da2e3ebdSchin 		for (inp = pp.in; inp->type != IN_FILE && inp->prev; inp = inp->prev);
450da2e3ebdSchin 		sfsprintf(pp.hidebuf, MAXTOKEN, "_%d_%s_hIDe", inp->index, sym->name);
451da2e3ebdSchin 		PUSH_STRING(pp.hidebuf);
452da2e3ebdSchin 		ret = 1;
453da2e3ebdSchin 	}
454da2e3ebdSchin 	pp.state &= ~NEWLINE;
455da2e3ebdSchin 	pp.in->flags |= IN_tokens;
456da2e3ebdSchin 	count(token);
457da2e3ebdSchin 	return ret;
458da2e3ebdSchin }
459