xref: /AOO41X/main/soltools/cpp/_macro.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir #ifdef _MSC_VER
2*cdf0e10cSrcweir #	define _POSIX_
3*cdf0e10cSrcweir #endif
4*cdf0e10cSrcweir #include <stdio.h>
5*cdf0e10cSrcweir #include <stdlib.h>
6*cdf0e10cSrcweir #include <string.h>
7*cdf0e10cSrcweir #ifdef __hpux
8*cdf0e10cSrcweir #	define _HPUX_SOURCE
9*cdf0e10cSrcweir #endif
10*cdf0e10cSrcweir #if defined(__IBMC__) || defined(__EMX__)
11*cdf0e10cSrcweir #   define PATH_MAX _MAX_PATH
12*cdf0e10cSrcweir #endif
13*cdf0e10cSrcweir #include <limits.h>
14*cdf0e10cSrcweir 
15*cdf0e10cSrcweir #include "cpp.h"
16*cdf0e10cSrcweir 
17*cdf0e10cSrcweir #define NCONCAT 16384
18*cdf0e10cSrcweir 
19*cdf0e10cSrcweir /*
20*cdf0e10cSrcweir  * do a macro definition.  tp points to the name being defined in the line
21*cdf0e10cSrcweir  */
22*cdf0e10cSrcweir void
23*cdf0e10cSrcweir     dodefine(Tokenrow * trp)
24*cdf0e10cSrcweir {
25*cdf0e10cSrcweir     Token *tp;
26*cdf0e10cSrcweir     Nlist *np;
27*cdf0e10cSrcweir     Source *s;
28*cdf0e10cSrcweir     Tokenrow *def, *args;
29*cdf0e10cSrcweir 	static uchar location[(PATH_MAX + 8) * NINC], *cp;
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir     tp = trp->tp + 1;
32*cdf0e10cSrcweir     if (tp >= trp->lp || tp->type != NAME)
33*cdf0e10cSrcweir     {
34*cdf0e10cSrcweir         error(ERROR, "#defined token is not a name");
35*cdf0e10cSrcweir         return;
36*cdf0e10cSrcweir     }
37*cdf0e10cSrcweir     np = lookup(tp, 1);
38*cdf0e10cSrcweir     if (np->flag & ISUNCHANGE)
39*cdf0e10cSrcweir     {
40*cdf0e10cSrcweir         error(ERROR, "#defined token %t can't be redefined", tp);
41*cdf0e10cSrcweir         return;
42*cdf0e10cSrcweir     }
43*cdf0e10cSrcweir     /* collect arguments */
44*cdf0e10cSrcweir     tp += 1;
45*cdf0e10cSrcweir     args = NULL;
46*cdf0e10cSrcweir     if (tp < trp->lp && tp->type == LP && tp->wslen == 0)
47*cdf0e10cSrcweir     {
48*cdf0e10cSrcweir         /* macro with args */
49*cdf0e10cSrcweir         int narg = 0;
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir         tp += 1;
52*cdf0e10cSrcweir         args = new(Tokenrow);
53*cdf0e10cSrcweir         maketokenrow(2, args);
54*cdf0e10cSrcweir         if (tp->type != RP)
55*cdf0e10cSrcweir         {
56*cdf0e10cSrcweir             int err = 0;
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir             for (;;)
59*cdf0e10cSrcweir             {
60*cdf0e10cSrcweir                 Token *atp;
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir                 if (tp->type != NAME)
63*cdf0e10cSrcweir                 {
64*cdf0e10cSrcweir                     err++;
65*cdf0e10cSrcweir                     break;
66*cdf0e10cSrcweir                 }
67*cdf0e10cSrcweir                 if (narg >= args->max)
68*cdf0e10cSrcweir                     growtokenrow(args);
69*cdf0e10cSrcweir                 for (atp = args->bp; atp < args->lp; atp++)
70*cdf0e10cSrcweir                     if (atp->len == tp->len
71*cdf0e10cSrcweir                         && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0)
72*cdf0e10cSrcweir                         error(ERROR, "Duplicate macro argument");
73*cdf0e10cSrcweir                 *args->lp++ = *tp;
74*cdf0e10cSrcweir                 narg++;
75*cdf0e10cSrcweir                 tp += 1;
76*cdf0e10cSrcweir                 if (tp->type == RP)
77*cdf0e10cSrcweir                     break;
78*cdf0e10cSrcweir                 if (tp->type != COMMA)
79*cdf0e10cSrcweir                 {
80*cdf0e10cSrcweir                     err++;
81*cdf0e10cSrcweir                     break;
82*cdf0e10cSrcweir                 }
83*cdf0e10cSrcweir                 tp += 1;
84*cdf0e10cSrcweir             }
85*cdf0e10cSrcweir             if (err)
86*cdf0e10cSrcweir             {
87*cdf0e10cSrcweir                 error(ERROR, "Syntax error in macro parameters");
88*cdf0e10cSrcweir                 return;
89*cdf0e10cSrcweir             }
90*cdf0e10cSrcweir         }
91*cdf0e10cSrcweir         tp += 1;
92*cdf0e10cSrcweir     }
93*cdf0e10cSrcweir     trp->tp = tp;
94*cdf0e10cSrcweir     if (((trp->lp) - 1)->type == NL)
95*cdf0e10cSrcweir         trp->lp -= 1;
96*cdf0e10cSrcweir     def = normtokenrow(trp);
97*cdf0e10cSrcweir     if (np->flag & ISDEFINED)
98*cdf0e10cSrcweir     {
99*cdf0e10cSrcweir         if (comparetokens(def, np->vp)
100*cdf0e10cSrcweir             || (np->ap == NULL) != (args == NULL)
101*cdf0e10cSrcweir             || (np->ap && comparetokens(args, np->ap)))
102*cdf0e10cSrcweir 		{
103*cdf0e10cSrcweir 			if ( np->loc )
104*cdf0e10cSrcweir             	error(ERROR,
105*cdf0e10cSrcweir 					"Macro redefinition of %t (already defined at %s)",
106*cdf0e10cSrcweir 					trp->bp + 2, np->loc);
107*cdf0e10cSrcweir 			else
108*cdf0e10cSrcweir             	error(ERROR,
109*cdf0e10cSrcweir 					"Macro redefinition of %t (already defined at %s)",
110*cdf0e10cSrcweir 					trp->bp + 2, "commandline" );
111*cdf0e10cSrcweir 		}
112*cdf0e10cSrcweir     }
113*cdf0e10cSrcweir     if (args)
114*cdf0e10cSrcweir     {
115*cdf0e10cSrcweir         Tokenrow *tap;
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir         tap = normtokenrow(args);
118*cdf0e10cSrcweir         dofree(args->bp);
119*cdf0e10cSrcweir         args = tap;
120*cdf0e10cSrcweir     }
121*cdf0e10cSrcweir     np->ap = args;
122*cdf0e10cSrcweir     np->vp = def;
123*cdf0e10cSrcweir     np->flag |= ISDEFINED;
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir 	/* build location string of macro definition */
126*cdf0e10cSrcweir     for (cp = location, s = cursource; s; s = s->next)
127*cdf0e10cSrcweir         if (*s->filename)
128*cdf0e10cSrcweir 		{
129*cdf0e10cSrcweir 			if (cp != location)
130*cdf0e10cSrcweir 				*cp++ = ' ';
131*cdf0e10cSrcweir             sprintf((char *)cp, "%s:%d", s->filename, s->line);
132*cdf0e10cSrcweir 			cp += strlen((char *)cp);
133*cdf0e10cSrcweir 		}
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir 	np->loc = newstring(location, strlen((char *)location), 0);
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir 	if (Mflag)
138*cdf0e10cSrcweir 	{
139*cdf0e10cSrcweir 		if (np->ap)
140*cdf0e10cSrcweir 			error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp);
141*cdf0e10cSrcweir 		else
142*cdf0e10cSrcweir 			error(INFO, "Macro definition of %s [%r]", np->name, np->vp);
143*cdf0e10cSrcweir 	}
144*cdf0e10cSrcweir }
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir /*
147*cdf0e10cSrcweir  * Definition received via -D or -U
148*cdf0e10cSrcweir  */
149*cdf0e10cSrcweir void
150*cdf0e10cSrcweir     doadefine(Tokenrow * trp, int type)
151*cdf0e10cSrcweir {
152*cdf0e10cSrcweir     Nlist *np;
153*cdf0e10cSrcweir 	static uchar onestr[2] = "1";
154*cdf0e10cSrcweir     static Token onetoken[1] = {{NUMBER, 0, 0, 1, onestr, 0}};
155*cdf0e10cSrcweir     static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1};
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir     trp->tp = trp->bp;
158*cdf0e10cSrcweir     if (type == 'U')
159*cdf0e10cSrcweir     {
160*cdf0e10cSrcweir         if (trp->lp - trp->tp != 2 || trp->tp->type != NAME)
161*cdf0e10cSrcweir             goto syntax;
162*cdf0e10cSrcweir         if ((np = lookup(trp->tp, 0)) == NULL)
163*cdf0e10cSrcweir             return;
164*cdf0e10cSrcweir         np->flag &= ~ISDEFINED;
165*cdf0e10cSrcweir         return;
166*cdf0e10cSrcweir     }
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir     if (type == 'A')
169*cdf0e10cSrcweir     {
170*cdf0e10cSrcweir         if (trp->tp >= trp->lp || trp->tp->type != NAME)
171*cdf0e10cSrcweir             goto syntax;
172*cdf0e10cSrcweir         trp->tp->type = ARCHITECTURE;
173*cdf0e10cSrcweir         np = lookup(trp->tp, 1);
174*cdf0e10cSrcweir         np->flag |= ISARCHITECTURE;
175*cdf0e10cSrcweir         trp->tp += 1;
176*cdf0e10cSrcweir         if (trp->tp >= trp->lp || trp->tp->type == END)
177*cdf0e10cSrcweir         {
178*cdf0e10cSrcweir             np->vp = &onetr;
179*cdf0e10cSrcweir             return;
180*cdf0e10cSrcweir         }
181*cdf0e10cSrcweir         else
182*cdf0e10cSrcweir             error(FATAL, "Illegal -A argument %r", trp);
183*cdf0e10cSrcweir     }
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir     if (trp->tp >= trp->lp || trp->tp->type != NAME)
186*cdf0e10cSrcweir         goto syntax;
187*cdf0e10cSrcweir     np = lookup(trp->tp, 1);
188*cdf0e10cSrcweir     np->flag |= ISDEFINED;
189*cdf0e10cSrcweir     trp->tp += 1;
190*cdf0e10cSrcweir     if (trp->tp >= trp->lp || trp->tp->type == END)
191*cdf0e10cSrcweir     {
192*cdf0e10cSrcweir         np->vp = &onetr;
193*cdf0e10cSrcweir         return;
194*cdf0e10cSrcweir 	}
195*cdf0e10cSrcweir 	if (trp->tp->type != ASGN)
196*cdf0e10cSrcweir 		goto syntax;
197*cdf0e10cSrcweir 	trp->tp += 1;
198*cdf0e10cSrcweir 	if ((trp->lp - 1)->type == END)
199*cdf0e10cSrcweir 		trp->lp -= 1;
200*cdf0e10cSrcweir 	np->vp = normtokenrow(trp);
201*cdf0e10cSrcweir 	return;
202*cdf0e10cSrcweir syntax:
203*cdf0e10cSrcweir 	error(FATAL, "Illegal -D or -U argument %r", trp);
204*cdf0e10cSrcweir }
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir /*
209*cdf0e10cSrcweir  * Do macro expansion in a row of tokens.
210*cdf0e10cSrcweir  * Flag is NULL if more input can be gathered.
211*cdf0e10cSrcweir  */
212*cdf0e10cSrcweir void
213*cdf0e10cSrcweir 	expandrow(Tokenrow * trp, char *flag)
214*cdf0e10cSrcweir {
215*cdf0e10cSrcweir 	Token *	tp;
216*cdf0e10cSrcweir 	Nlist *	np;
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir 	MacroValidatorList 	validators;
219*cdf0e10cSrcweir 	mvl_init(&validators);
220*cdf0e10cSrcweir     /* Sets all token-identifiers to 0 because tokens may not be initialised (never use C!) */
221*cdf0e10cSrcweir 	tokenrow_zeroTokenIdentifiers(trp);
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir 	if (flag)
224*cdf0e10cSrcweir 		setsource(flag, -1, -1, "", 0);
225*cdf0e10cSrcweir 	for (tp = trp->tp; tp < trp->lp;)
226*cdf0e10cSrcweir 	{
227*cdf0e10cSrcweir 		mvl_check(&validators, tp);
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir 		if (tp->type != NAME
230*cdf0e10cSrcweir 			|| quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0
231*cdf0e10cSrcweir 			|| (np = lookup(tp, 0)) == NULL
232*cdf0e10cSrcweir 			|| (np->flag & (ISDEFINED | ISMAC)) == 0
233*cdf0e10cSrcweir 			|| (np->flag & ISACTIVE) != 0)
234*cdf0e10cSrcweir 		{
235*cdf0e10cSrcweir 			tp++;
236*cdf0e10cSrcweir 			continue;
237*cdf0e10cSrcweir 		}
238*cdf0e10cSrcweir 		trp->tp = tp;
239*cdf0e10cSrcweir 		if (np->val == KDEFINED)
240*cdf0e10cSrcweir 		{
241*cdf0e10cSrcweir 			tp->type = DEFINED;
242*cdf0e10cSrcweir 			if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
243*cdf0e10cSrcweir 				(tp + 1)->type = NAME1;
244*cdf0e10cSrcweir 			else
245*cdf0e10cSrcweir 				if ((tp + 3) < trp->lp && (tp + 1)->type == LP
246*cdf0e10cSrcweir 					&& (tp + 2)->type == NAME && (tp + 3)->type == RP)
247*cdf0e10cSrcweir 					(tp + 2)->type = NAME1;
248*cdf0e10cSrcweir 				else
249*cdf0e10cSrcweir 					error(ERROR, "Incorrect syntax for `defined'");
250*cdf0e10cSrcweir 			tp++;
251*cdf0e10cSrcweir 			continue;
252*cdf0e10cSrcweir 		}
253*cdf0e10cSrcweir 		else
254*cdf0e10cSrcweir 			if (np->val == KMACHINE)
255*cdf0e10cSrcweir 			{
256*cdf0e10cSrcweir 				if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP))
257*cdf0e10cSrcweir 				{
258*cdf0e10cSrcweir 					tp->type = ARCHITECTURE;
259*cdf0e10cSrcweir 					if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
260*cdf0e10cSrcweir 						(tp + 1)->type = NAME2;
261*cdf0e10cSrcweir 					else
262*cdf0e10cSrcweir 						if ((tp + 3) < trp->lp && (tp + 1)->type == LP
263*cdf0e10cSrcweir 							&& (tp + 2)->type == NAME && (tp + 3)->type == RP)
264*cdf0e10cSrcweir 							(tp + 2)->type = NAME2;
265*cdf0e10cSrcweir 						else
266*cdf0e10cSrcweir 							error(ERROR, "Incorrect syntax for `#machine'");
267*cdf0e10cSrcweir 				}
268*cdf0e10cSrcweir 				tp++;
269*cdf0e10cSrcweir 				continue;
270*cdf0e10cSrcweir 			}
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir 		if (np->flag & ISMAC)
273*cdf0e10cSrcweir 			builtin(trp, np->val);
274*cdf0e10cSrcweir 		else
275*cdf0e10cSrcweir 			expand(trp, np, &validators);
276*cdf0e10cSrcweir 		tp = trp->tp;
277*cdf0e10cSrcweir 	}	// end for
278*cdf0e10cSrcweir 	if (flag)
279*cdf0e10cSrcweir 		unsetsource();
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir 	mvl_destruct(&validators);
282*cdf0e10cSrcweir }
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir /*
285*cdf0e10cSrcweir  * Expand the macro whose name is np, at token trp->tp, in the tokenrow.
286*cdf0e10cSrcweir  * Return trp->tp at the first token next to be expanded
287*cdf0e10cSrcweir  * (ordinarily the beginning of the expansion)
288*cdf0e10cSrcweir  * I.e.: the same position as before!
289*cdf0e10cSrcweir  * Only one expansion is performed, then we return to the expandrow()
290*cdf0e10cSrcweir  * loop and start at same position.
291*cdf0e10cSrcweir  */
292*cdf0e10cSrcweir void
293*cdf0e10cSrcweir 	expand(Tokenrow * trp, Nlist * np, MacroValidatorList *	pValidators)
294*cdf0e10cSrcweir {
295*cdf0e10cSrcweir //	Token * pOldNextTp;
296*cdf0e10cSrcweir 	Tokenrow ntr;
297*cdf0e10cSrcweir 	int ntokc, narg, i;
298*cdf0e10cSrcweir 	Tokenrow *atr[NARG + 1];
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir 	if (Mflag == 2)
301*cdf0e10cSrcweir 	{
302*cdf0e10cSrcweir 		if (np->ap)
303*cdf0e10cSrcweir 			error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap);
304*cdf0e10cSrcweir 		else
305*cdf0e10cSrcweir 			error(INFO, "Macro expansion of %t with %s", trp->tp, np->name);
306*cdf0e10cSrcweir 	}
307*cdf0e10cSrcweir 
308*cdf0e10cSrcweir 	copytokenrow(&ntr, np->vp);         /* copy macro value */
309*cdf0e10cSrcweir 	if (np->ap == NULL)                 /* parameterless */
310*cdf0e10cSrcweir 		ntokc = 1;
311*cdf0e10cSrcweir 	else
312*cdf0e10cSrcweir 	{
313*cdf0e10cSrcweir 		ntokc = gatherargs(trp, atr, &narg);
314*cdf0e10cSrcweir 		if (narg < 0)
315*cdf0e10cSrcweir 		{                               /* not actually a call (no '(') */
316*cdf0e10cSrcweir 			trp->tp++;
317*cdf0e10cSrcweir 			return;
318*cdf0e10cSrcweir 		}
319*cdf0e10cSrcweir 		if (narg != rowlen(np->ap))
320*cdf0e10cSrcweir 		{
321*cdf0e10cSrcweir 			error(ERROR, "Disagreement in number of macro arguments");
322*cdf0e10cSrcweir 			trp->tp += ntokc;
323*cdf0e10cSrcweir 			return;
324*cdf0e10cSrcweir 		}
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir 		/** If gatherargs passed a macro validating token, this token
327*cdf0e10cSrcweir 			must become valid here.
328*cdf0e10cSrcweir 			trp->tp+0 was checked in expandrow(), so we dont need to do it
329*cdf0e10cSrcweir 			again here:
330*cdf0e10cSrcweir 		*/
331*cdf0e10cSrcweir 		for (i = 1; i < ntokc; i++)
332*cdf0e10cSrcweir 		{
333*cdf0e10cSrcweir 			mvl_check(pValidators,trp->tp+i);
334*cdf0e10cSrcweir 		}
335*cdf0e10cSrcweir 
336*cdf0e10cSrcweir 		substargs(np, &ntr, atr);		/* put args into replacement */
337*cdf0e10cSrcweir 		for (i = 0; i < narg; i++)
338*cdf0e10cSrcweir 		{
339*cdf0e10cSrcweir 			dofree(atr[i]->bp);
340*cdf0e10cSrcweir 			dofree(atr[i]);
341*cdf0e10cSrcweir 		}
342*cdf0e10cSrcweir 	}
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir /* old
345*cdf0e10cSrcweir 	np->flag |= ISACTIVE;
346*cdf0e10cSrcweir */
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir /* rh
349*cdf0e10cSrcweir */
350*cdf0e10cSrcweir 	doconcat(&ntr);                     /* execute ## operators */
351*cdf0e10cSrcweir 	ntr.tp = ntr.bp;
352*cdf0e10cSrcweir 	makespace(&ntr, trp->tp);
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir /* old
355*cdf0e10cSrcweir //	expandrow(&ntr, "<expand>");
356*cdf0e10cSrcweir //	insertrow(trp, ntokc, &ntr);
357*cdf0e10cSrcweir //	dofree(ntr.bp);
358*cdf0e10cSrcweir //	np->flag &= ~ISACTIVE;
359*cdf0e10cSrcweir */
360*cdf0e10cSrcweir 
361*cdf0e10cSrcweir /* NP
362*cdf0e10cSrcweir 		// Replace macro by its value:
363*cdf0e10cSrcweir */
364*cdf0e10cSrcweir //	pOldNextTp = trp->tp+ntokc;
365*cdf0e10cSrcweir 	tokenrow_zeroTokenIdentifiers(&ntr);
366*cdf0e10cSrcweir 	insertrow(trp, ntokc, &ntr);
367*cdf0e10cSrcweir 		/* Reassign old macro validators:
368*cdf0e10cSrcweir 		*/
369*cdf0e10cSrcweir //	mvl_move(pValidators, trp->tp - pOldNextTp);
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir 		/* add validator for just invalidated macro:
372*cdf0e10cSrcweir 		*/
373*cdf0e10cSrcweir 	np->flag |= ISACTIVE;
374*cdf0e10cSrcweir 	if (trp->tp != trp->lp)
375*cdf0e10cSrcweir 	{  	/* tp is a valid pointer: */
376*cdf0e10cSrcweir 		mvl_add(pValidators,np,trp->tp);
377*cdf0e10cSrcweir 	}
378*cdf0e10cSrcweir 	else
379*cdf0e10cSrcweir 	{	/* tp is == lp, therefore does not point to valid memory: */
380*cdf0e10cSrcweir 		mvl_add(pValidators,np,0);
381*cdf0e10cSrcweir 	}
382*cdf0e10cSrcweir 		/* reset trp->tp to original position:
383*cdf0e10cSrcweir 		*/
384*cdf0e10cSrcweir 	trp->tp -= ntr.lp - ntr.bp;			/* so the result will be tested for macros from the same position again */
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir 	dofree(ntr.bp);
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir 	return;
389*cdf0e10cSrcweir }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir /*
392*cdf0e10cSrcweir  * Gather an arglist, starting in trp with tp pointing at the macro name.
393*cdf0e10cSrcweir  * Return total number of tokens passed, stash number of args found.
394*cdf0e10cSrcweir  * trp->tp is not changed relative to the tokenrow.
395*cdf0e10cSrcweir  */
396*cdf0e10cSrcweir int
397*cdf0e10cSrcweir 	gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg)
398*cdf0e10cSrcweir {
399*cdf0e10cSrcweir 	int parens = 1;
400*cdf0e10cSrcweir 	int ntok = 0;
401*cdf0e10cSrcweir 	Token *bp, *lp;
402*cdf0e10cSrcweir 	Tokenrow ttr;
403*cdf0e10cSrcweir 	int ntokp;
404*cdf0e10cSrcweir 	int needspace;
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir 	*narg = -1;                         /* means that there is no macro
407*cdf0e10cSrcweir 										 * call */
408*cdf0e10cSrcweir 	/* look for the ( */
409*cdf0e10cSrcweir 	for (;;)
410*cdf0e10cSrcweir 	{
411*cdf0e10cSrcweir 		trp->tp++;
412*cdf0e10cSrcweir 		ntok++;
413*cdf0e10cSrcweir 		if (trp->tp >= trp->lp)
414*cdf0e10cSrcweir 		{
415*cdf0e10cSrcweir 			gettokens(trp, 0);
416*cdf0e10cSrcweir 			if ((trp->lp - 1)->type == END)
417*cdf0e10cSrcweir 			{
418*cdf0e10cSrcweir 				trp->lp -= 1;
419*cdf0e10cSrcweir 				trp->tp -= ntok;
420*cdf0e10cSrcweir 				return ntok;
421*cdf0e10cSrcweir 			}
422*cdf0e10cSrcweir 		}
423*cdf0e10cSrcweir 		if (trp->tp->type == LP)
424*cdf0e10cSrcweir 			break;
425*cdf0e10cSrcweir 		if (trp->tp->type != NL)
426*cdf0e10cSrcweir 			return ntok;
427*cdf0e10cSrcweir 	}
428*cdf0e10cSrcweir 	*narg = 0;
429*cdf0e10cSrcweir 	ntok++;
430*cdf0e10cSrcweir 	ntokp = ntok;
431*cdf0e10cSrcweir 	trp->tp++;
432*cdf0e10cSrcweir 	/* search for the terminating ), possibly extending the row */
433*cdf0e10cSrcweir 	needspace = 0;
434*cdf0e10cSrcweir 	while (parens > 0)
435*cdf0e10cSrcweir 	{
436*cdf0e10cSrcweir 		if (trp->tp >= trp->lp)
437*cdf0e10cSrcweir 			gettokens(trp, 0);
438*cdf0e10cSrcweir 		if (needspace)
439*cdf0e10cSrcweir 		{
440*cdf0e10cSrcweir 			needspace = 0;
441*cdf0e10cSrcweir 			/* makespace(trp); [rh] */
442*cdf0e10cSrcweir 		}
443*cdf0e10cSrcweir 		if (trp->tp->type == END)
444*cdf0e10cSrcweir 		{
445*cdf0e10cSrcweir 			trp->lp -= 1;
446*cdf0e10cSrcweir 			trp->tp -= ntok;
447*cdf0e10cSrcweir 			error(ERROR, "EOF in macro arglist");
448*cdf0e10cSrcweir 			return ntok;
449*cdf0e10cSrcweir 		}
450*cdf0e10cSrcweir 		if (trp->tp->type == NL)
451*cdf0e10cSrcweir 		{
452*cdf0e10cSrcweir 			trp->tp += 1;
453*cdf0e10cSrcweir 			adjustrow(trp, -1);
454*cdf0e10cSrcweir 			trp->tp -= 1;
455*cdf0e10cSrcweir 			/* makespace(trp); [rh] */
456*cdf0e10cSrcweir 			needspace = 1;
457*cdf0e10cSrcweir 			continue;
458*cdf0e10cSrcweir 		}
459*cdf0e10cSrcweir 		if (trp->tp->type == LP)
460*cdf0e10cSrcweir 			parens++;
461*cdf0e10cSrcweir 		else
462*cdf0e10cSrcweir 			if (trp->tp->type == RP)
463*cdf0e10cSrcweir 				parens--;
464*cdf0e10cSrcweir 		trp->tp++;
465*cdf0e10cSrcweir 		ntok++;
466*cdf0e10cSrcweir 	}
467*cdf0e10cSrcweir 	trp->tp -= ntok;
468*cdf0e10cSrcweir 	/* Now trp->tp won't move underneath us */
469*cdf0e10cSrcweir 	lp = bp = trp->tp + ntokp;
470*cdf0e10cSrcweir 	for (; parens >= 0; lp++)
471*cdf0e10cSrcweir 	{
472*cdf0e10cSrcweir 		if (lp->type == LP)
473*cdf0e10cSrcweir 		{
474*cdf0e10cSrcweir             parens++;
475*cdf0e10cSrcweir             continue;
476*cdf0e10cSrcweir         }
477*cdf0e10cSrcweir         if (lp->type == RP)
478*cdf0e10cSrcweir             parens--;
479*cdf0e10cSrcweir         if (lp->type == DSHARP)
480*cdf0e10cSrcweir 			lp->type = DSHARP1;         /* ## not special in arg */
481*cdf0e10cSrcweir         if ((lp->type == COMMA && parens == 0) ||
482*cdf0e10cSrcweir 				( parens < 0 && ((lp - 1)->type != LP)))
483*cdf0e10cSrcweir         {
484*cdf0e10cSrcweir             if (*narg >= NARG - 1)
485*cdf0e10cSrcweir 				error(FATAL, "Sorry, too many macro arguments");
486*cdf0e10cSrcweir             ttr.bp = ttr.tp = bp;
487*cdf0e10cSrcweir             ttr.lp = lp;
488*cdf0e10cSrcweir             atr[(*narg)++] = normtokenrow(&ttr);
489*cdf0e10cSrcweir             bp = lp + 1;
490*cdf0e10cSrcweir         }
491*cdf0e10cSrcweir     }
492*cdf0e10cSrcweir     return ntok;
493*cdf0e10cSrcweir }
494*cdf0e10cSrcweir 
495*cdf0e10cSrcweir /*
496*cdf0e10cSrcweir  * substitute the argument list into the replacement string
497*cdf0e10cSrcweir  *  This would be simple except for ## and #
498*cdf0e10cSrcweir  */
499*cdf0e10cSrcweir void
500*cdf0e10cSrcweir 	substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr)
501*cdf0e10cSrcweir {
502*cdf0e10cSrcweir 	Tokenrow tatr;
503*cdf0e10cSrcweir 	Token *tp;
504*cdf0e10cSrcweir 	int ntok, argno;
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir 	for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;)
507*cdf0e10cSrcweir 	{
508*cdf0e10cSrcweir 		if (rtr->tp->type == SHARP)
509*cdf0e10cSrcweir 		{                               /* string operator */
510*cdf0e10cSrcweir 			tp = rtr->tp;
511*cdf0e10cSrcweir 			rtr->tp += 1;
512*cdf0e10cSrcweir 			if ((argno = lookuparg(np, rtr->tp)) < 0)
513*cdf0e10cSrcweir 			{
514*cdf0e10cSrcweir 				error(ERROR, "# not followed by macro parameter");
515*cdf0e10cSrcweir 				continue;
516*cdf0e10cSrcweir 			}
517*cdf0e10cSrcweir 			ntok = 1 + (rtr->tp - tp);
518*cdf0e10cSrcweir 			rtr->tp = tp;
519*cdf0e10cSrcweir 			insertrow(rtr, ntok, stringify(atr[argno]));
520*cdf0e10cSrcweir 			continue;
521*cdf0e10cSrcweir 		}
522*cdf0e10cSrcweir 		if (rtr->tp->type == NAME
523*cdf0e10cSrcweir 			&& (argno = lookuparg(np, rtr->tp)) >= 0)
524*cdf0e10cSrcweir 		{
525*cdf0e10cSrcweir 			if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP)
526*cdf0e10cSrcweir 				|| (rtr->tp != rtr->bp  && (rtr->tp - 1)->type == DSHARP))
527*cdf0e10cSrcweir 			{
528*cdf0e10cSrcweir 				copytokenrow(&tatr, atr[argno]);
529*cdf0e10cSrcweir 				makespace(&tatr, rtr->tp);
530*cdf0e10cSrcweir 				insertrow(rtr, 1, &tatr);
531*cdf0e10cSrcweir 				dofree(tatr.bp);
532*cdf0e10cSrcweir 			}
533*cdf0e10cSrcweir             else
534*cdf0e10cSrcweir             {
535*cdf0e10cSrcweir                 copytokenrow(&tatr, atr[argno]);
536*cdf0e10cSrcweir 				makespace(&tatr, rtr->tp);
537*cdf0e10cSrcweir                 expandrow(&tatr, "<macro>");
538*cdf0e10cSrcweir                 insertrow(rtr, 1, &tatr);
539*cdf0e10cSrcweir                 dofree(tatr.bp);
540*cdf0e10cSrcweir             }
541*cdf0e10cSrcweir             continue;
542*cdf0e10cSrcweir         }
543*cdf0e10cSrcweir         rtr->tp++;
544*cdf0e10cSrcweir     }
545*cdf0e10cSrcweir }
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir /*
548*cdf0e10cSrcweir  * Evaluate the ## operators in a tokenrow
549*cdf0e10cSrcweir  */
550*cdf0e10cSrcweir void
551*cdf0e10cSrcweir     doconcat(Tokenrow * trp)
552*cdf0e10cSrcweir {
553*cdf0e10cSrcweir     Token *ltp, *ntp;
554*cdf0e10cSrcweir     Tokenrow ntr;
555*cdf0e10cSrcweir     int len;
556*cdf0e10cSrcweir 
557*cdf0e10cSrcweir     for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++)
558*cdf0e10cSrcweir     {
559*cdf0e10cSrcweir         if (trp->tp->type == DSHARP1)
560*cdf0e10cSrcweir             trp->tp->type = DSHARP;
561*cdf0e10cSrcweir         else
562*cdf0e10cSrcweir             if (trp->tp->type == DSHARP)
563*cdf0e10cSrcweir             {
564*cdf0e10cSrcweir 				int  i;
565*cdf0e10cSrcweir                 char tt[NCONCAT];
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir                 ltp = trp->tp - 1;
568*cdf0e10cSrcweir 				ntp = trp->tp + 1;
569*cdf0e10cSrcweir 
570*cdf0e10cSrcweir 				if (ltp < trp->bp || ntp >= trp->lp)
571*cdf0e10cSrcweir                 {
572*cdf0e10cSrcweir                     error(ERROR, "## occurs at border of replacement");
573*cdf0e10cSrcweir                     continue;
574*cdf0e10cSrcweir 				}
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir 				ntp = ltp;
577*cdf0e10cSrcweir 				i   = 1;
578*cdf0e10cSrcweir 				len = 0;
579*cdf0e10cSrcweir 
580*cdf0e10cSrcweir 				do
581*cdf0e10cSrcweir 				{
582*cdf0e10cSrcweir 					if (len + ntp->len + ntp->wslen > sizeof(tt))
583*cdf0e10cSrcweir 					{
584*cdf0e10cSrcweir 						error(ERROR, "## string concatination buffer overrun");
585*cdf0e10cSrcweir 						break;
586*cdf0e10cSrcweir 					}
587*cdf0e10cSrcweir 
588*cdf0e10cSrcweir 					if (ntp != trp->tp + 1)
589*cdf0e10cSrcweir 					{
590*cdf0e10cSrcweir 						strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen,
591*cdf0e10cSrcweir 							    ntp->len + ntp->wslen);
592*cdf0e10cSrcweir 						len += ntp->len + ntp->wslen;
593*cdf0e10cSrcweir 					}
594*cdf0e10cSrcweir 					else	// Leerzeichen um ## herum entfernen:
595*cdf0e10cSrcweir 					{
596*cdf0e10cSrcweir 						strncpy((char *) tt + len, (char *) ntp->t, ntp->len);
597*cdf0e10cSrcweir 						len += ntp->len;
598*cdf0e10cSrcweir 					}
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir 					ntp = trp->tp + i;
601*cdf0e10cSrcweir 					i++;
602*cdf0e10cSrcweir 				}
603*cdf0e10cSrcweir 				while (ntp < trp->lp);
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir                 tt[len] = '\0';
606*cdf0e10cSrcweir 				setsource("<##>", -1, -1, tt, 0);
607*cdf0e10cSrcweir                 maketokenrow(3, &ntr);
608*cdf0e10cSrcweir                 gettokens(&ntr, 1);
609*cdf0e10cSrcweir                 unsetsource();
610*cdf0e10cSrcweir 				if (ntr.bp->type == UNCLASS)
611*cdf0e10cSrcweir 					error(WARNING, "Bad token %r produced by ##", &ntr);
612*cdf0e10cSrcweir 				while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp)
613*cdf0e10cSrcweir 					ntr.lp--;
614*cdf0e10cSrcweir 
615*cdf0e10cSrcweir 			    doconcat(&ntr);
616*cdf0e10cSrcweir                 trp->tp = ltp;
617*cdf0e10cSrcweir 				makespace(&ntr, ltp);
618*cdf0e10cSrcweir                 insertrow(trp, ntp - ltp, &ntr);
619*cdf0e10cSrcweir                 dofree(ntr.bp);
620*cdf0e10cSrcweir                 trp->tp--;
621*cdf0e10cSrcweir             }
622*cdf0e10cSrcweir     }
623*cdf0e10cSrcweir }
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir /*
626*cdf0e10cSrcweir  * tp is a potential parameter name of macro mac;
627*cdf0e10cSrcweir  * look it up in mac's arglist, and if found, return the
628*cdf0e10cSrcweir  * corresponding index in the argname array.  Return -1 if not found.
629*cdf0e10cSrcweir  */
630*cdf0e10cSrcweir int
631*cdf0e10cSrcweir     lookuparg(Nlist * mac, Token * tp)
632*cdf0e10cSrcweir {
633*cdf0e10cSrcweir     Token *ap;
634*cdf0e10cSrcweir 
635*cdf0e10cSrcweir     if (tp->type != NAME || mac->ap == NULL)
636*cdf0e10cSrcweir         return -1;
637*cdf0e10cSrcweir     for (ap = mac->ap->bp; ap < mac->ap->lp; ap++)
638*cdf0e10cSrcweir     {
639*cdf0e10cSrcweir         if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0)
640*cdf0e10cSrcweir             return ap - mac->ap->bp;
641*cdf0e10cSrcweir     }
642*cdf0e10cSrcweir     return -1;
643*cdf0e10cSrcweir }
644*cdf0e10cSrcweir 
645*cdf0e10cSrcweir /*
646*cdf0e10cSrcweir  * Return a quoted version of the tokenrow (from # arg)
647*cdf0e10cSrcweir  */
648*cdf0e10cSrcweir #define	STRLEN	512
649*cdf0e10cSrcweir Tokenrow *
650*cdf0e10cSrcweir     stringify(Tokenrow * vp)
651*cdf0e10cSrcweir {
652*cdf0e10cSrcweir     static Token t = {STRING, 0, 0, 0, NULL, 0};
653*cdf0e10cSrcweir 	static Tokenrow tr = {&t, &t, &t + 1, 1};
654*cdf0e10cSrcweir     Token *tp;
655*cdf0e10cSrcweir     uchar s[STRLEN];
656*cdf0e10cSrcweir     uchar *sp = s, *cp;
657*cdf0e10cSrcweir     int i, instring;
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir     *sp++ = '"';
660*cdf0e10cSrcweir     for (tp = vp->bp; tp < vp->lp; tp++)
661*cdf0e10cSrcweir     {
662*cdf0e10cSrcweir         instring = tp->type == STRING || tp->type == CCON;
663*cdf0e10cSrcweir         if (sp + 2 * tp->len + tp->wslen  >= &s[STRLEN - 10])
664*cdf0e10cSrcweir         {
665*cdf0e10cSrcweir             error(ERROR, "Stringified macro arg is too long");
666*cdf0e10cSrcweir             break;
667*cdf0e10cSrcweir         }
668*cdf0e10cSrcweir 
669*cdf0e10cSrcweir         // Change by np 31.10.2001, #93725 - begin
670*cdf0e10cSrcweir         if ( tp->wslen > 0 )
671*cdf0e10cSrcweir         *sp++ = ' ';
672*cdf0e10cSrcweir         // change end.
673*cdf0e10cSrcweir 
674*cdf0e10cSrcweir         for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++)
675*cdf0e10cSrcweir         {
676*cdf0e10cSrcweir             if (instring && (*cp == '"' || *cp == '\\'))
677*cdf0e10cSrcweir                 *sp++ = '\\';
678*cdf0e10cSrcweir             *sp++ = *cp++;
679*cdf0e10cSrcweir         }
680*cdf0e10cSrcweir     }
681*cdf0e10cSrcweir     *sp++ = '"';
682*cdf0e10cSrcweir     *sp = '\0';
683*cdf0e10cSrcweir 	sp = s;
684*cdf0e10cSrcweir     t.len = strlen((char *) sp);
685*cdf0e10cSrcweir     t.t = newstring(sp, t.len, 0);
686*cdf0e10cSrcweir     return &tr;
687*cdf0e10cSrcweir }
688*cdf0e10cSrcweir 
689*cdf0e10cSrcweir /*
690*cdf0e10cSrcweir  * expand a builtin name
691*cdf0e10cSrcweir  */
692*cdf0e10cSrcweir void
693*cdf0e10cSrcweir     builtin(Tokenrow * trp, int biname)
694*cdf0e10cSrcweir {
695*cdf0e10cSrcweir     char *op;
696*cdf0e10cSrcweir     Token *tp;
697*cdf0e10cSrcweir     Source *s;
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir     tp = trp->tp;
700*cdf0e10cSrcweir     trp->tp++;
701*cdf0e10cSrcweir     /* need to find the real source */
702*cdf0e10cSrcweir     s = cursource;
703*cdf0e10cSrcweir     while (s && s->fd == -1)
704*cdf0e10cSrcweir         s = s->next;
705*cdf0e10cSrcweir     if (s == NULL)
706*cdf0e10cSrcweir         s = cursource;
707*cdf0e10cSrcweir 	/* most are strings */
708*cdf0e10cSrcweir     tp->type = STRING;
709*cdf0e10cSrcweir     if (tp->wslen)
710*cdf0e10cSrcweir     {
711*cdf0e10cSrcweir         *outptr++ = ' ';
712*cdf0e10cSrcweir         tp->wslen = 1;
713*cdf0e10cSrcweir     }
714*cdf0e10cSrcweir     op = outptr;
715*cdf0e10cSrcweir     *op++ = '"';
716*cdf0e10cSrcweir     switch (biname)
717*cdf0e10cSrcweir     {
718*cdf0e10cSrcweir 
719*cdf0e10cSrcweir         case KLINENO:
720*cdf0e10cSrcweir             tp->type = NUMBER;
721*cdf0e10cSrcweir             op = outnum(op - 1, s->line);
722*cdf0e10cSrcweir             break;
723*cdf0e10cSrcweir 
724*cdf0e10cSrcweir         case KFILE:
725*cdf0e10cSrcweir             {
726*cdf0e10cSrcweir                 char *src = s->filename;
727*cdf0e10cSrcweir 
728*cdf0e10cSrcweir                 while ((*op++ = *src++) != 0)
729*cdf0e10cSrcweir                     if (src[-1] == '\\')
730*cdf0e10cSrcweir                         *op++ = '\\';
731*cdf0e10cSrcweir                 op--;
732*cdf0e10cSrcweir                 break;
733*cdf0e10cSrcweir             }
734*cdf0e10cSrcweir 
735*cdf0e10cSrcweir         case KDATE:
736*cdf0e10cSrcweir             strncpy(op, curtime + 4, 7);
737*cdf0e10cSrcweir             strncpy(op + 7, curtime + 20, 4);
738*cdf0e10cSrcweir             op += 11;
739*cdf0e10cSrcweir             break;
740*cdf0e10cSrcweir 
741*cdf0e10cSrcweir         case KTIME:
742*cdf0e10cSrcweir             strncpy(op, curtime + 11, 8);
743*cdf0e10cSrcweir             op += 8;
744*cdf0e10cSrcweir             break;
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir         default:
747*cdf0e10cSrcweir             error(ERROR, "cpp botch: unknown internal macro");
748*cdf0e10cSrcweir             return;
749*cdf0e10cSrcweir     }
750*cdf0e10cSrcweir     if (tp->type == STRING)
751*cdf0e10cSrcweir         *op++ = '"';
752*cdf0e10cSrcweir     tp->t = (uchar *) outptr;
753*cdf0e10cSrcweir     tp->len = op - outptr;
754*cdf0e10cSrcweir     outptr = op;
755*cdf0e10cSrcweir }
756*cdf0e10cSrcweir 
757