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  * preprocessor library private definitions
26  */
27 
28 #ifndef _PPLIB_H
29 #define _PPLIB_H
30 
31 /*
32  * the first definitions control optional code -- 0 disables
33  */
34 
35 #ifndef ARCHIVE
36 #define ARCHIVE		1	/* -I can specify header archives	*/
37 #endif
38 #ifndef CATSTRINGS
39 #define CATSTRINGS	1	/* concatenate adjacent strings		*/
40 #endif
41 #ifndef CHECKPOINT
42 #define CHECKPOINT	1	/* checkpoint preprocessed files	*/
43 #endif
44 #ifndef COMPATIBLE
45 #define COMPATIBLE	1	/* enable COMPATIBILITY related code	*/
46 #endif
47 #ifndef MACKEYARGS
48 #define MACKEYARGS 	_BLD_DEBUG /* name=value macro formals and actuals */
49 #endif
50 #ifndef POOL
51 #define POOL		1	/* enable loop on input,output,error	*/
52 #endif
53 #ifndef PROTOTYPE
54 #define PROTOTYPE	1	/* enable ppproto code			*/
55 #endif
56 
57 #define TRUNCLENGTH	8	/* default TRUNCATE length		*/
58 
59 #if _BLD_DEBUG
60 #undef	DEBUG
61 #define DEBUG		(TRACE_message|TRACE_count|TRACE_debug)
62 #else
63 #ifndef DEBUG
64 #define DEBUG		(TRACE_message)
65 #endif
66 #endif
67 
68 /*
69  * the lower tests are transient
70  */
71 
72 #define TEST_count		(1L<<24)
73 #define TEST_hashcount		(1L<<25)
74 #define TEST_hashdump		(1L<<26)
75 #define TEST_hit		(1L<<27)
76 #define TEST_noinit		(1L<<28)
77 #define TEST_nonoise		(1L<<29)
78 #define TEST_noproto		(1L<<30)
79 
80 #define TEST_INVERT		(1L<<31)
81 
82 #define PROTO_CLASSIC		(1<<0)	/* classic to prototyped	*/
83 #define PROTO_DISABLE		(1<<1)	/* disable conversion		*/
84 #define PROTO_EXTERNALIZE	(1<<2)	/* static fun() => extern fun()	*/
85 #define PROTO_FORCE		(1<<3)	/* force even if no magic	*/
86 #define PROTO_HEADER		(1<<4)	/* header defines too		*/
87 #define PROTO_INCLUDE		(1<<5)	/* <prototyped.h> instead	*/
88 #define PROTO_INITIALIZED	(1<<6)	/* internal initialization	*/
89 #define PROTO_LINESYNC		(1<<7)	/* force standalone line syncs	*/
90 #define PROTO_NOPRAGMA		(1<<8)	/* delete pragma prototyped	*/
91 #define PROTO_PASS		(1<<9)	/* pass blocks if no magic	*/
92 #define PROTO_PLUSPLUS		(1<<10)	/* extern () -> extern (...)	*/
93 #define PROTO_RETAIN		(1<<11)	/* defines retained after close	*/
94 #define PROTO_TEST		(1<<12)	/* enable test code		*/
95 
96 #define PROTO_USER		(1<<13)	/* first user flag		*/
97 
98 #define SEARCH_EXISTS		0	/* ppsearch for existence	*/
99 #define SEARCH_HOSTED		(1<<0)	/* search hosted dirs only	*/
100 #define SEARCH_IGNORE		(1<<1)	/* ignore if not found		*/
101 #define SEARCH_INCLUDE		(1<<2)	/* ppsearch for include		*/
102 #define SEARCH_VENDOR		(1<<3)	/* search vendor dirs only	*/
103 #define SEARCH_USER		(1<<4)	/* first user flag		*/
104 
105 #define STYLE_gnu		(1<<0)	/* gnu style args		*/
106 
107 #define IN_c			(1<<0)	/* C language file		*/
108 #define IN_defguard		(1<<1)	/* did multiple include check	*/
109 #define IN_disable		(1<<2)	/* saved state&DISABLE		*/
110 #define IN_endguard		(1<<3)	/* did multiple include check	*/
111 #define IN_eof			(1<<4)	/* reached EOF			*/
112 #define IN_expand		(1<<5)	/* ppexpand buffer		*/
113 #define IN_flush		(1<<6)	/* flush stdout on file_refill()*/
114 #define IN_hosted		(1<<7)	/* saved mode&HOSTED		*/
115 #define IN_ignoreline		(1<<8)	/* ignore #line until file	*/
116 #define IN_newline		(1<<9)	/* newline at end of last fill	*/
117 #define IN_noguard		(1<<10)	/* no multiple include guard	*/
118 #define IN_prototype		(1<<11)	/* ppproto() input		*/
119 #define IN_regular		(1<<12)	/* regular input file		*/
120 #define IN_static		(1<<13)	/* static buffer - don't free	*/
121 #define IN_sync			(1<<14)	/* line sync required on pop	*/
122 #define IN_tokens		(1L<<15)/* non-space tokens encountered	*/
123 
124 #define OPT_GLOBAL		(1<<0)	/* pp: pass optional		*/
125 #define OPT_PASS		(1<<1)	/* pass on			*/
126 
127 struct ppsymbol;
128 struct ppindex;
129 
130 typedef char*	(*PPBUILTIN)(char*, const char*, const char*);
131 typedef void	(*PPCOMMENT)(const char*, const char*, const char*, int);
132 typedef void	(*PPINCREF)(const char*, const char*, int, int);
133 typedef void	(*PPLINESYNC)(int, const char*);
134 typedef void	(*PPMACREF)(struct ppsymbol*, const char*, int, int, unsigned long);
135 typedef int	(*PPOPTARG)(int, int, const char*);
136 typedef void	(*PPPRAGMA)(const char*, const char*, const char*, const char*, int);
137 
138 struct ppinstk				/* input stream stack frame	*/
139 {
140 	char*		nextchr;	/* next input char (first elt)	*/
141 	struct ppinstk*	next;		/* next frame (for allocation)	*/
142 	struct ppinstk*	prev;		/* previous frame		*/
143 	long*		control;	/* control block level		*/
144 	char*		buffer;		/* buffer base pointer		*/
145 	char*		file;		/* saved file name		*/
146 	char*		prefix;		/* directory prefix		*/
147 	struct ppsymbol* symbol;	/* macro info			*/
148 #if CHECKPOINT
149 	struct ppindex*	index;		/* checkpoint include index	*/
150 	int		buflen;		/* buffer count			*/
151 #endif
152 	int		line;		/* saved line number		*/
153 	int		vendor;		/* saved pp.vendor		*/
154 	short		fd;		/* file descriptor		*/
155 	short		hide;		/* hide index (from pp.hide)	*/
156 	short		flags;		/* IN_[a-z]* flags		*/
157 	char		type;		/* input type			*/
158 };
159 
160 #if MACKEYARGS
161 struct ppkeyarg				/* pp macro keyword arg info	*/
162 {
163 	char*		name;		/* keyword arg name		*/
164 	char*		value;		/* keyword arg value		*/
165 };
166 #endif
167 
168 struct pplist				/* string list			*/
169 {
170 	char*		value;		/* string value			*/
171 	struct pplist*	next;		/* next in list			*/
172 };
173 
174 struct oplist				/* queue op until PP_INIT	*/
175 {
176 	int		op;		/* PP_* op			*/
177 	char*		value;		/* op value			*/
178 	struct oplist*	next;		/* next op			*/
179 };
180 
181 struct pphide				/* hidden symbol info		*/
182 {
183 	struct ppmacro*	macro;		/* saved macro info		*/
184 	unsigned long	flags;		/* saved symbol flags if macro	*/
185 	int		level;		/* nesting level		*/
186 };
187 
188 struct ppmacstk				/* macro invocation stack frame	*/
189 {
190 	struct ppmacstk* next;		/* next frame (for allocation)	*/
191 	struct ppmacstk* prev;		/* previous frame		*/
192 	int		line;		/* line number of first arg	*/
193 	char*		arg[1];		/* arg text pointers		*/
194 };
195 
196 struct ppmember				/* archive member pun on ppfile	*/
197 {
198 	struct ppdirs*	archive;	/* archive holding file		*/
199 	unsigned long	offset;		/* data offset			*/
200 	unsigned long	size;		/* data size			*/
201 };
202 
203 struct counter				/* monitoring counters		*/
204 {
205 	int		candidate;	/* macro candidates		*/
206 	int		function;	/* function macros		*/
207 	int		macro;		/* macro hits			*/
208 	int		pplex;		/* pplex() calls		*/
209 	int		push;		/* input stream pushes		*/
210 	int		terminal;	/* terminal states		*/
211 	int		token;		/* emitted tokens		*/
212 };
213 
214 struct pptuple				/* tuple macro			*/
215 {
216 	struct pptuple*	nomatch;	/* nomatch tuple		*/
217 	struct pptuple*	match;		/* match tuple			*/
218 	char		token[1];	/* matching token		*/
219 };
220 
221 struct ppfileid				/* physical file id		*/
222 {
223 	unsigned long	st_dev;		/* dev				*/
224 	unsigned long	st_ino;		/* ino				*/
225 };
226 
227 struct pathid				/* physical file name and id	*/
228 {
229 	char*		path;		/* file path			*/
230 	struct ppfileid	id;		/* file id			*/
231 };
232 
233 #define SAMEID(a,b)	((a)->st_ino==(unsigned long)(b)->st_ino&&(a)->st_dev==(unsigned long)(b)->st_dev)
234 #define SAVEID(a,b)	((a)->st_ino=(unsigned long)(b)->st_ino,(a)->st_dev=(unsigned long)(b)->st_dev)
235 
236 #define _PP_CONTEXT_PRIVATE_		/* ppglobals private context	*/ \
237 	struct ppcontext* context;	/* current context		*/ \
238 	long		state;		/* pp state flags		*/ \
239 	long		mode;		/* uncoupled pp state flags	*/ \
240 	long		option;		/* option flags			*/ \
241 	long		test;		/* implementation tests		*/ \
242 	struct								   \
243 	{								   \
244 	Sfio_t*		sp;		/* FILEDEPS output stream	*/ \
245 	long		flags;		/* PP_FILEDEPS flags		*/ \
246 	}		filedeps;	/* FILEDEPS info		*/ \
247 	struct ppdirs*	firstdir;	/* first include dir		*/ \
248 	struct ppdirs*	lastdir;	/* last include dir		*/ \
249 	int		hide;		/* current include hide index	*/ \
250 	int		column;		/* FILEDEPS column		*/ \
251 	int		pending;	/* ppline() pending output	*/ \
252 	char*		firstfile;	/* ppline() first file		*/ \
253 	char*		lastfile;	/* ppline() most recent file	*/ \
254 	char*		ignore;		/* include ignore list file	*/ \
255 	char*		probe;		/* ppdefault probe key		*/ \
256 	Hash_table_t*	filtab;		/* file name hash table		*/ \
257 	Hash_table_t*	prdtab;		/* predicate hash table		*/ \
258 	char*		date;		/* start date string		*/ \
259 	char*		time;		/* start time string		*/ \
260 	char*		maps;		/* directive maps		*/ \
261 	long		ro_state;	/* readonly state		*/ \
262 	long		ro_mode;	/* readonly mode		*/ \
263 	long		ro_option;	/* readonly option		*/ \
264 	long		ro_op[2];	/* readonly op			*/ \
265 	struct pathid	cdir;		/* arg C dir			*/ \
266 	struct pathid	hostdir;	/* arg host dir			*/ \
267 	char*		ppdefault;	/* arg default info file	*/ \
268 	struct ppindex*	firstindex;	/* first include index entry	*/ \
269 	struct ppindex*	lastindex;	/* last include index entry	*/ \
270 	struct oplist*	firstop;	/* first arg op			*/ \
271 	struct oplist*	lastop;		/* last arg op			*/ \
272 	struct oplist*	firsttx;	/* first text file		*/ \
273 	struct oplist*	lasttx;		/* last text file		*/ \
274 	unsigned char	arg_file;	/* arg file index		*/ \
275 	unsigned char	arg_mode;	/* arg mode			*/ \
276 	unsigned char	arg_style;	/* arg style			*/ \
277 	unsigned char	c;		/* arg C state			*/ \
278 	unsigned char	hosted;		/* arg hosted state		*/ \
279 	unsigned char	ignoresrc;	/* arg ignore source state	*/ \
280 	unsigned char	initialized;	/* arg initialized state	*/ \
281 	unsigned char	standalone;	/* arg standalone state		*/ \
282 	unsigned char	spare_1;	/* padding spare		*/
283 
284 #define _PP_GLOBALS_PRIVATE_		/* ppglobals private additions	*/ \
285 	char*		checkpoint;	/* checkpoint version		*/ \
286 	int		constack;	/* pp.control size		*/ \
287 	struct ppinstk*	in;		/* input stream stack pointer	*/ \
288 	char*		addp;	    	/* addbuf pointer		*/ \
289 	char*		args;		/* predicate args		*/ \
290 	char*		addbuf;		/* ADD buffer			*/ \
291 	char*		catbuf;		/* catenation buffer		*/ \
292 	char*		hdrbuf;		/* HEADEREXPAND buffer		*/ \
293 	char*		hidebuf;	/* pp:hide buffer		*/ \
294 	char*		path;		/* full path of last #include	*/ \
295 	char*		tmpbuf;		/* very temporary buffer	*/ \
296 	char*		valbuf;		/* builtin macro value buffer	*/ \
297 	char*		optflags;	/* OPT_* flags indexed by X_*	*/ \
298 	int		lastout;	/* last output char		*/ \
299 		/* the rest are implicitly initialized */ \
300 	char*		include;	/* saved path of last #include	*/ \
301 	char*		prefix;		/* current directory prefix	*/ \
302 	struct ppmember* member;	/* include archive member data	*/ \
303 	int		hidden;		/* hidden newline count		*/ \
304 	int		hiding;		/* number of symbols in hiding	*/ \
305 	int		level;		/* pplex() recursion level	*/ \
306 	struct								   \
307 	{								   \
308 	int		input;		/* pool input			*/ \
309 	int		output;		/* pool output			*/ \
310 	}		pool;		/* loop on input,output,error	*/ \
311 	struct								   \
312 	{								   \
313 	long		ro_state;	/* original pp.ro_state		*/ \
314 	long		ro_mode;	/* original pp.ro_mode		*/ \
315 	long		ro_option;	/* original pp.ro_option	*/ \
316 	long		ro_op[2];	/* original pp.ro_op[]		*/ \
317 	int		on;		/* PP_RESET enabled		*/ \
318 	Hash_table_t*	symtab;		/* original pp.symtab scope	*/ \
319 	}		reset;		/* PP_RESET state		*/ \
320 	int		truncate;	/* identifier truncation length	*/ \
321 	struct ppmacstk* macp;		/* top of macro actual stack	*/ \
322 	char*		maxmac;		/* maximum size of macro stack	*/ \
323 	char*		mactop;		/* top of current macro frame	*/ \
324 	char*		toknxt;		/* '\0' of pp.token		*/ \
325 	long*		control;	/* control block flags pointer	*/ \
326 	long*		maxcon;		/* max control block frame	*/ \
327 	struct oplist*	chop;		/* include prefix chop list	*/ \
328 	struct ppfile*	insert;		/* inserted line sync file	*/ \
329 	struct ppfile*	original;	/* original include name	*/ \
330 	struct ppdirs*	found;		/* last successful ppsearch dir	*/ \
331 	int		vendor;		/* vendor includes only		*/ \
332 	Hash_table_t*	dirtab;		/* directive hash table		*/ \
333 	Hash_table_t*	strtab;		/* string hash table		*/ \
334 	PPBUILTIN	builtin;	/* builtin macro handler	*/ \
335 	PPCOMMENT	comment;	/* pass along comments		*/ \
336 	PPINCREF	incref;		/* include file push/return	*/ \
337 	PPLINESYNC	linesync;	/* pass along line sync info	*/ \
338 	PPLINESYNC	olinesync;	/* original linesync value	*/ \
339 	PPMACREF	macref;		/* called on macro def/ref	*/ \
340 	PPOPTARG	optarg;		/* unknown option arg handler	*/ \
341 	PPPRAGMA	pragma;		/* pass along unknown pragmas	*/ \
342 	struct counter	counter;	/* monitoring counters		*/ \
343 	char		funbuf[256];	/* last __FUNCTION__		*/
344 
345 #define _PP_SYMBOL_PRIVATE_		/* ppsymbol private additions	*/ \
346 	struct pphide*	hidden;		/* hidden symbol info		*/
347 
348 #if MACKEYARGS
349 #define _PP_MACRO_PRIVATE_		/* ppmacro private additions	*/ \
350 	struct pptuple*	tuple;		/* tuple macro			*/ \
351 	union								   \
352 	{								   \
353 	char*		formal;		/* normal formals list		*/ \
354 	struct ppkeyarg* key;		/* keyword formals table	*/ \
355 	}		args;		/* macro args info		*/ \
356 	int		size;		/* body size			*/
357 #define formals		args.formal	/* formal argument list		*/
358 #define formkeys	args.key	/* formal keyword argument list	*/
359 #else
360 #define _PP_MACRO_PRIVATE_		/* ppmacro private additions	*/ \
361 	struct pptuple*	tuple;		/* tuple macro			*/ \
362 	char*		formals;	/* formal argument list		*/ \
363 	int		size;		/* body size			*/
364 #endif
365 
366 #define _PP_DIRS_PRIVATE_		/* ppdirs private additions	*/ \
367 	unsigned char	c;		/* files here are C language	*/ \
368 	unsigned char	index;		/* prefix,local,standard index	*/ \
369 	unsigned char	type;		/* dir type			*/ \
370 	union								   \
371 	{								   \
372 	char*		buffer;		/* TYPE_BUFFER buffer		*/ \
373 	Sfio_t*		sp;		/* archive stream		*/ \
374 	struct ppdirs*	subdir;		/* subdir list			*/ \
375 	}		info;		/* type info			*/ \
376 	struct ppfileid	id;		/* directory id			*/ \
377 
378 #if !PROTOMAIN
379 #include <ast.h>
380 #include <error.h>
381 #endif
382 
383 #undef	newof
384 #define newof(p,t,n,x)	((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
385 
386 #include "pp.h"
387 #include "ppdef.h"
388 #include "ppkey.h"
389 
390 #undef	setstate			/* random clash!		*/
391 
392 /*
393  * DEBUG is encoded with the following bits
394  */
395 
396 #define TRACE_message		01
397 #define TRACE_count		02
398 #define TRACE_debug		04
399 
400 #if DEBUG && !lint
401 #define	PANIC		(ERROR_PANIC|ERROR_SOURCE|ERROR_SYSTEM),__FILE__,__LINE__
402 #else
403 #define	PANIC		ERROR_PANIC
404 #endif
405 
406 #if DEBUG & TRACE_count
407 #define count(x)	pp.counter.x++
408 #else
409 #define count(x)
410 #endif
411 
412 #if DEBUG & TRACE_message
413 #define message(x)	do { if (tracing) error x; } while (0)
414 #else
415 #define message(x)
416 #endif
417 
418 #if DEBUG & TRACE_debug
419 #define debug(x)	do { if (tracing) error x; } while (0)
420 #else
421 #define debug(x)
422 #endif
423 
424 /*
425  * note that MEMCPY advances the associated pointers
426  */
427 
428 #define MEMCPY(to,fr,n) \
429 	{ memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; }
430 
431 #define NEWDIRECTIVE	(-1)
432 
433 #undef	dirname
434 #undef	error
435 
436 #define dirname(x)	ppkeyname(x,1)
437 #define error		pperror
438 #define keyname(x)	ppkeyname(x,0)
439 #define nextframe(m,p)	(m->next=m+(p-(char*)m+sizeof(struct ppmacstk)-1)/sizeof(struct ppmacstk)+1)
440 #define popframe(m)	(m=m->prev)
441 #define pptokchr(c)	pptokstr(NiL,(c))
442 #define pushcontrol()	do { if (pp.control++ >= pp.maxcon) ppnest(); } while (0)
443 #define pushframe(m)	(m->next->prev=m,m=m->next)
444 #define setmode(m,v)	ppset(&pp.mode,m,v)
445 #define setoption(m,v)	ppset(&pp.option,m,v)
446 #define setstate(m,v)	ppset(&pp.state,m,v)
447 #define tracing		(error_info.trace<0)
448 
449 #define ppgetfile(x)	((struct ppfile*)hashlook(pp.filtab,x,HASH_LOOKUP,NiL))
450 #define ppsetfile(x)	((struct ppfile*)hashlook(pp.filtab,x,HASH_CREATE|HASH_SIZE(sizeof(struct ppfile)),NiL))
451 
452 #define ppkeyget(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_LOOKUP,NiL)
453 #define ppkeyref(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_LOOKUP|HASH_INTERNAL,NiL)
454 #define ppkeyset(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_CREATE|HASH_SIZE(sizeof(struct ppsymkey)),NiL)
455 
456 #define MARK		'@'		/* internal mark		*/
457 #define ARGOFFSET	'1'		/* macro arg mark offset	*/
458 
459 #define STRAPP(p,v,r)	do{r=(v);while((*p++)=(*r++));}while(0)
460 #define STRCOPY(p,v,r)	do{r=(v);while((*p++)=(*r++));p--;}while(0)
461 #define STRCOPY2(p,r)	do{while((*p++)=(*r++));p--;}while(0)
462 
463 #define SETFILE(p,v)	(p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'F',(long)v,MARK))
464 #define SETLINE(p,v)	(p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'L',(long)v,MARK))
465 
466 #define peekchr()	(*pp.in->nextchr)
467 #define ungetchr(c)	(*--pp.in->nextchr=(c))
468 
469 #define MAXID		255		/* maximum identifier size	*/
470 #define MAXTOKEN	PPTOKSIZ	/* maximum token size		*/
471 #define MAXFORMALS	64		/* maximum number macro formals	*/
472 #define MAXHIDDEN	8		/* ppline if hidden>=MAXHIDDEN	*/
473 #define DEFMACSTACK	(MAXFORMALS*32*32)/* default macstack size	*/
474 
475 #define FSM_COMPATIBILITY	1	/* compatibility mode		*/
476 #define FSM_IDADD	2		/* add to identifer set		*/
477 #define FSM_IDDEL	3		/* delete from identifer set	*/
478 #define FSM_INIT	4		/* initilize			*/
479 #define FSM_MACRO	5		/* add new macro		*/
480 #define FSM_OPSPACE	6		/* handle <binop><space>=	*/
481 #define FSM_PLUSPLUS	7		/* C++ lexical analysis		*/
482 #define FSM_QUOTADD	8		/* add to quote set		*/
483 #define FSM_QUOTDEL	9		/* delete from quote set	*/
484 
485 #define IN_TOP		01		/* top level -- directives ok	*/
486 
487 #define IN_BUFFER	(2|IN_TOP)	/* buffer of lines		*/
488 #define IN_COPY		2		/* macro arg (copied)		*/
489 #define IN_EXPAND	4		/* macro arg (expanded)		*/
490 #define IN_FILE		(4|IN_TOP)	/* file				*/
491 #define IN_INIT		(6|IN_TOP)	/* initialization IN_BUFFER	*/
492 #define IN_MACRO	8		/* macro text			*/
493 #define IN_MULTILINE	(8|IN_TOP)	/* multi-line macro text	*/
494 #define IN_QUOTE	10		/* "..." macro arg (copied)	*/
495 #define IN_RESCAN	(10|IN_TOP)	/* directive rescan buffer	*/
496 #define IN_SQUOTE	12		/* '...' macro arg (copied)	*/
497 #define IN_STRING	14		/* string			*/
498 
499 #define INC_CLEAR	((struct ppsymbol*)0)
500 #define INC_IGNORE	((struct ppsymbol*)pp.addbuf)
501 #define INC_TEST	((struct ppsymbol*)pp.catbuf)
502 
503 #define INC_BOUND(n)	(1<<(n))
504 #define INC_MEMBER(n)	(1<<((n)+INC_MAX))
505 #define INC_PREFIX	0
506 #define INC_LOCAL	1
507 #define INC_STANDARD	2
508 #define INC_VENDOR	3
509 #define INC_MAX		4
510 #define INC_SELF	(1<<(2*INC_MAX+0))
511 #define INC_EXISTS	(1<<(2*INC_MAX+1))
512 #define INC_LISTED	(1<<(2*INC_MAX+2))
513 #define INC_MAPALL	(1<<(2*INC_MAX+3))
514 #define INC_MAPHOSTED	(1<<(2*INC_MAX+4))
515 #define INC_MAPNOHOSTED	(1<<(2*INC_MAX+5))
516 #define INC_MAPNOLOCAL	(1<<(2*INC_MAX+6))
517 #define INC_HOSTED	(1<<(2*INC_MAX+7))
518 
519 #define TYPE_ARCHIVE	(1<<0)
520 #define TYPE_BUFFER	(1<<1)
521 #define TYPE_CHECKPOINT	(1<<2)
522 #define TYPE_DIRECTORY	(1<<3)
523 #define TYPE_HOSTED	(1<<4)
524 #define TYPE_INCLUDE	(1<<5)
525 #define TYPE_VENDOR	(1<<6)
526 
527 #define TOK_BUILTIN	(1<<0)		/* last token was #(		*/
528 #define TOK_FORMAL	(1<<1)		/* last token was arg formal id	*/
529 #define TOK_ID		(1<<2)		/* last token was identifier	*/
530 #define TOK_TOKCAT	(1<<3)		/* last token was ##		*/
531 
532 #define HADELSE		(1<<0)		/* already had else part	*/
533 #define KEPT		(1<<1)		/* already kept part of block	*/
534 #define SKIP		(1<<2)		/* skip this block		*/
535 #define BLOCKBITS	3		/* block flag bits		*/
536 
537 #define SETIFBLOCK(p)	(*(p)=(*((p)-1)&SKIP)|((long)error_info.line<<BLOCKBITS))
538 #define GETIFLINE(p)	((*(p)>>BLOCKBITS)&((1L<<(sizeof(long)*CHAR_BIT-BLOCKBITS))-1))
539 
540 #define PUSH(t,p)		\
541 	do \
542 	{ \
543 		count(push); \
544 		if (!pp.in->next) \
545 		{ \
546 			pp.in->next = newof(0, struct ppinstk, 1, 0); \
547 			pp.in->next->prev = pp.in; \
548 		} \
549 		p = pp.in = pp.in->next; \
550 		p->type = t; \
551 		p->flags = 0; \
552 	} while (0)
553 
554 #define PUSH_BUFFER(f,p,n)		\
555 	pppush(IN_BUFFER,f,p,n)
556 
557 #define PUSH_COPY(p,n)		\
558 	do \
559 	{ \
560 		register struct ppinstk*	cur; \
561 		PUSH(IN_COPY, cur); \
562 		cur->line = error_info.line; \
563 		error_info.line = n; \
564 		cur->nextchr = p; \
565 		cur->prev->symbol->flags &= ~SYM_DISABLED; \
566 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
567 	} while (0)
568 
569 #define PUSH_EXPAND(p,n)	\
570 	do \
571 	{ \
572 		register struct ppinstk*	cur; \
573 		PUSH(IN_EXPAND, cur); \
574 		cur->line = error_info.line; \
575 		error_info.line = n; \
576 		cur->prev->symbol->flags &= ~SYM_DISABLED; \
577 		cur->buffer = cur->nextchr = ppexpand(p); \
578 		if (!(cur->prev->symbol->flags & SYM_MULTILINE)) \
579 			cur->prev->symbol->flags |= SYM_DISABLED; \
580 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
581 	} while (0)
582 
583 #define PUSH_FILE(f,d)	\
584 	pppush(IN_FILE,f,NiL,d)
585 
586 #define PUSH_INIT(f,p)	\
587 	pppush(IN_INIT,f,p,1)
588 
589 #define PUSH_MACRO(p)		\
590 	do \
591 	{ \
592 		register struct ppinstk*	cur; \
593 		PUSH(IN_MACRO, cur); \
594 		cur->symbol = p; \
595 		cur->nextchr = p->macro->value; \
596 		p->flags |= SYM_DISABLED; \
597 		if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
598 		pp.state &= ~NEWLINE; \
599 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
600 	} while (0)
601 
602 #define PUSH_TUPLE(p,v)		\
603 	do \
604 	{ \
605 		register struct ppinstk*	cur; \
606 		PUSH(IN_MACRO, cur); \
607 		cur->symbol = p; \
608 		cur->nextchr = v; \
609 		p->flags |= SYM_DISABLED; \
610 		pp.state &= ~NEWLINE; \
611 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
612 	} while (0)
613 
614 #define PUSH_MULTILINE(p)		\
615 	do \
616 	{ \
617 		register struct ppinstk*	cur; \
618 		register int			n; \
619 		PUSH(IN_MULTILINE, cur); \
620 		cur->symbol = p; \
621 		cur->flags |= IN_defguard|IN_endguard|IN_noguard; \
622 		pushcontrol(); \
623 		cur->control = pp.control; \
624 		*pp.control = 0; \
625 		cur->file = error_info.file; \
626 		n = strlen(error_info.file) + strlen(((struct ppsymbol*)p)->name) + 24; \
627 		error_info.file = cur->buffer = newof(0, char, n, 0); \
628 		sfsprintf(error_info.file, n, "%s:%s,%d", cur->file, p->name, error_info.line); \
629 		cur->line = error_info.line; \
630 		error_info.line = 1; \
631 		cur->nextchr = p->macro->value; \
632 		if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
633 		pp.state &= ~NEWLINE; \
634 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
635 	} while (0)
636 
637 #define PUSH_QUOTE(p,n)		\
638 	do \
639 	{ \
640 		register struct ppinstk*	cur; \
641 		PUSH(IN_QUOTE, cur); \
642 		cur->nextchr = p; \
643 		pp.state |= QUOTE; \
644 		cur->line = error_info.line; \
645 		error_info.line = n; \
646 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
647 	} while (0)
648 
649 #define PUSH_RESCAN(p)	\
650 	pppush(IN_RESCAN,NiL,p,0)
651 
652 #define PUSH_SQUOTE(p,n)	\
653 	do \
654 	{ \
655 		register struct ppinstk*	cur; \
656 		PUSH(IN_SQUOTE, cur); \
657 		cur->nextchr = p; \
658 		pp.state |= SQUOTE; \
659 		cur->line = error_info.line; \
660 		error_info.line = n; \
661 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
662 	} while (0)
663 
664 #define PUSH_STRING(p)		\
665 	do \
666 	{ \
667 		register struct ppinstk*	cur; \
668 		PUSH(IN_STRING, cur); \
669 		cur->nextchr = p; \
670 		if (pp.state & DISABLE) cur->flags |= IN_disable; \
671 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
672 	} while (0)
673 
674 #define PUSH_LINE(p)		\
675 	do \
676 	{ \
677 		register struct ppinstk*	cur; \
678 		PUSH(IN_STRING, cur); \
679 		cur->nextchr = p; \
680 		pp.state |= DISABLE|NOSPACE|PASSEOF|STRIP; \
681 		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
682 	} while (0)
683 
684 #define POP_LINE()		\
685 	do \
686 	{ \
687 		debug((-7, "POP  in=%s", ppinstr(pp.in))); \
688 		pp.in = pp.in->prev; \
689 		pp.state &= ~(DISABLE|NOSPACE|PASSEOF|STRIP); \
690 	} while (0)
691 
692 struct ppcontext			/* pp context			*/
693 {
694 	_PP_CONTEXT_PUBLIC_
695 	_PP_CONTEXT_PRIVATE_
696 };
697 
698 struct ppfile				/* include file info		*/
699 {
700 	HASH_HEADER;			/* this is a hash bucket too	*/
701 	struct ppsymbol* guard;		/* guard symbol			*/
702 	struct ppfile*	bound[INC_MAX];	/* include bindings		*/
703 	int		flags;		/* INC_* flags			*/
704 };
705 
706 #if CHECKPOINT
707 
708 struct ppindex				/* checkpoint include index	*/
709 {
710 	struct ppindex*	next;		/* next in list			*/
711 	struct ppfile*	file;		/* include file			*/
712 	unsigned long	begin;		/* beginning output offset	*/
713 	unsigned long	end;		/* ending output offset		*/
714 };
715 
716 #endif
717 
718 struct ppsymkey				/* pun for SYM_KEYWORD lex val	*/
719 {
720 	struct ppsymbol	sym;		/* symbol as usual		*/
721 	int		lex;		/* lex value for SYM_KEYWORD	*/
722 };
723 
724 #if PROTOMAIN && PROTO_STANDALONE
725 
726 #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
727 #define NiL		0
728 #define NoP(x)		(&x,1)
729 #else
730 #define NiL		((char*)0)
731 #define NoP(x)
732 #endif
733 
734 #define newof(p,t,n,x)	((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
735 
736 #define _PP_DELAY_	#
737 
738 _PP_DELAY_ ifdef __STDC__
739 
740 _PP_DELAY_ include <stdlib.h>
741 _PP_DELAY_ include <unistd.h>
742 _PP_DELAY_ include <time.h>
743 _PP_DELAY_ include <string.h>
744 
745 _PP_DELAY_ else
746 
747 _PP_DELAY_ define size_t		int
748 
749 extern void*		realloc(void*, size_t);
750 extern void*		calloc(size_t, size_t);
751 extern char*		ctime(time_t*);
752 extern void		free(void*);
753 
754 _PP_DELAY_ ifndef O_RDONLY
755 
756 extern int		access(const char*, int);
757 extern int		close(int);
758 extern int		creat(const char*, int);
759 extern void		exit(int);
760 extern int		link(const char*, const char*);
761 extern int		open(const char*, int, ...);
762 extern int		read(int, void*, int);
763 extern time_t		time(time_t*);
764 extern int		unlink(const char*);
765 extern int		write(int, const void*, int);
766 
767 _PP_DELAY_ endif
768 
769 _PP_DELAY_ endif
770 
771 #else
772 
773 /*
774  * library implementation globals
775  */
776 
777 #define ppassert	_pp_assert
778 #define ppbuiltin	_pp_builtin
779 #define ppcall		_pp_call
780 #define ppcontrol	_pp_control
781 #define ppdump		_pp_dump
782 #define ppexpand	_pp_expand
783 #define ppexpr		_pp_expr
784 #define ppfsm		_pp_fsm
785 #define ppinmap		_pp_inmap
786 #define ppinstr		_pp_instr
787 #define ppkeyname	_pp_keyname
788 #define pplexmap	_pp_lexmap
789 #define pplexstr	_pp_lexstr
790 #define ppload		_pp_load
791 #define ppmodestr	_pp_modestr
792 #define ppmultiple	_pp_multiple
793 #define ppnest		_pp_nest
794 #define ppoption	_pp_option
795 #define ppoptionstr	_pp_optionstr
796 #define pppclose	_pp_pclose
797 #define pppdrop		_pp_pdrop
798 #define pppopen		_pp_popen
799 #define pppread		_pp_pread
800 #define pppredargs	_pp_predargs
801 #define pppush		_pp_push
802 #define pprefmac	_pp_refmac
803 #define ppsearch	_pp_search
804 #define ppset		_pp_set
805 #define ppstatestr	_pp_statestr
806 #define pptokstr	_pp_tokstr
807 #define pptrace		_pp_trace
808 
809 #endif
810 
811 extern void		ppassert(int, char*, char*);
812 extern void		ppbuiltin(void);
813 extern int		ppcall(struct ppsymbol*, int);
814 extern int		ppcontrol(void);
815 extern void		ppdump(void);
816 extern char*		ppexpand(char*);
817 extern long		ppexpr(int*);
818 extern void		ppfsm(int, char*);
819 extern char*		ppinstr(struct ppinstk*);
820 extern char*		ppkeyname(int, int);
821 extern char*		pplexstr(int);
822 extern void		ppload(char*);
823 extern void		ppmapinclude(char*, char*);
824 extern char*		ppmodestr(long);
825 extern int		ppmultiple(struct ppfile*, struct ppsymbol*);
826 extern void		ppnest(void);
827 extern int		ppoption(char*);
828 extern char*		ppoptionstr(long);
829 extern void		pppclose(char*);
830 extern int		pppdrop(char*);
831 extern char*		pppopen(char*, int, char*, char*, char*, char*, int);
832 extern int		pppread(char*);
833 extern int		pppredargs(void);
834 extern void		pppush(int, char*, char*, int);
835 extern struct ppsymbol*	pprefmac(char*, int);
836 extern int		ppsearch(char*, int, int);
837 extern int		ppset(long*, long, int);
838 extern char*		ppstatestr(long);
839 extern char*		pptokstr(char*, int);
840 extern void		pptrace(int);
841 
842 #if _std_malloc
843 
844 #include <vmalloc.h>
845 
846 #undef	free
847 #define free(p)	 	vmfree(Vmregion,(void*)p)
848 #undef	newof
849 #define newof(p,t,n,x)	vmnewof(Vmregion,p,t,n,x)
850 #undef	oldof
851 #define oldof(p,t,n,x)	vmoldof(Vmregion,p,t,n,x)
852 #undef	strdup
853 #define strdup(s)	vmstrdup(Vmregion,s)
854 
855 #endif
856 
857 #endif
858