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