1da2e3ebchin/***********************************************************************
2da2e3ebchin*                                                                      *
3da2e3ebchin*               This software is part of the ast package               *
434f9b3eRoland Mainz*          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebchin*                      and is licensed under the                       *
6da2e3ebchin*                  Common Public License, Version 1.0                  *
77c2fbfbApril Chin*                    by AT&T Intellectual Property                     *
8da2e3ebchin*                                                                      *
9da2e3ebchin*                A copy of the License is available at                 *
10da2e3ebchin*            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebchin*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebchin*                                                                      *
13da2e3ebchin*              Information and Software Systems Research               *
14da2e3ebchin*                            AT&T Research                             *
15da2e3ebchin*                           Florham Park NJ                            *
16da2e3ebchin*                                                                      *
17da2e3ebchin*                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebchin*                                                                      *
19da2e3ebchin***********************************************************************/
20da2e3ebchin#pragma prototyped
21da2e3ebchin/*
22da2e3ebchin * Glenn Fowler
23da2e3ebchin * AT&T Research
24da2e3ebchin *
25da2e3ebchin * preprocessor library private definitions
26da2e3ebchin */
27da2e3ebchin
28da2e3ebchin#ifndef _PPLIB_H
29da2e3ebchin#define _PPLIB_H
30da2e3ebchin
31da2e3ebchin/*
32da2e3ebchin * the first definitions control optional code -- 0 disables
33da2e3ebchin */
34da2e3ebchin
35da2e3ebchin#ifndef ARCHIVE
36da2e3ebchin#define ARCHIVE		1	/* -I can specify header archives	*/
37da2e3ebchin#endif
38da2e3ebchin#ifndef CATSTRINGS
39da2e3ebchin#define CATSTRINGS	1	/* concatenate adjacent strings		*/
40da2e3ebchin#endif
41da2e3ebchin#ifndef CHECKPOINT
42da2e3ebchin#define CHECKPOINT	1	/* checkpoint preprocessed files	*/
43da2e3ebchin#endif
44da2e3ebchin#ifndef COMPATIBLE
45da2e3ebchin#define COMPATIBLE	1	/* enable COMPATIBILITY related code	*/
46da2e3ebchin#endif
47da2e3ebchin#ifndef MACKEYARGS
48da2e3ebchin#define MACKEYARGS 	_BLD_DEBUG /* name=value macro formals and actuals */
49da2e3ebchin#endif
50da2e3ebchin#ifndef POOL
51da2e3ebchin#define POOL		1	/* enable loop on input,output,error	*/
52da2e3ebchin#endif
53da2e3ebchin#ifndef PROTOTYPE
54da2e3ebchin#define PROTOTYPE	1	/* enable ppproto code			*/
55da2e3ebchin#endif
56da2e3ebchin
57da2e3ebchin#define TRUNCLENGTH	8	/* default TRUNCATE length		*/
58da2e3ebchin
59da2e3ebchin#if _BLD_DEBUG
60da2e3ebchin#undef	DEBUG
61da2e3ebchin#define DEBUG		(TRACE_message|TRACE_count|TRACE_debug)
62da2e3ebchin#else
63da2e3ebchin#ifndef DEBUG
64da2e3ebchin#define DEBUG		(TRACE_message)
65da2e3ebchin#endif
66da2e3ebchin#endif
67da2e3ebchin
68da2e3ebchin/*
69da2e3ebchin * the lower tests are transient
70da2e3ebchin */
71da2e3ebchin
72da2e3ebchin#define TEST_count		(1L<<24)
73da2e3ebchin#define TEST_hashcount		(1L<<25)
74da2e3ebchin#define TEST_hashdump		(1L<<26)
75da2e3ebchin#define TEST_hit		(1L<<27)
76da2e3ebchin#define TEST_noinit		(1L<<28)
77da2e3ebchin#define TEST_nonoise		(1L<<29)
78da2e3ebchin#define TEST_noproto		(1L<<30)
79da2e3ebchin
80da2e3ebchin#define TEST_INVERT		(1L<<31)
81da2e3ebchin
82da2e3ebchin#define PROTO_CLASSIC		(1<<0)	/* classic to prototyped	*/
83da2e3ebchin#define PROTO_DISABLE		(1<<1)	/* disable conversion		*/
84da2e3ebchin#define PROTO_EXTERNALIZE	(1<<2)	/* static fun() => extern fun()	*/
85da2e3ebchin#define PROTO_FORCE		(1<<3)	/* force even if no magic	*/
86da2e3ebchin#define PROTO_HEADER		(1<<4)	/* header defines too		*/
87da2e3ebchin#define PROTO_INCLUDE		(1<<5)	/* <prototyped.h> instead	*/
88da2e3ebchin#define PROTO_INITIALIZED	(1<<6)	/* internal initialization	*/
89da2e3ebchin#define PROTO_LINESYNC		(1<<7)	/* force standalone line syncs	*/
90da2e3ebchin#define PROTO_NOPRAGMA		(1<<8)	/* delete pragma prototyped	*/
91da2e3ebchin#define PROTO_PASS		(1<<9)	/* pass blocks if no magic	*/
92da2e3ebchin#define PROTO_PLUSPLUS		(1<<10)	/* extern () -> extern (...)	*/
93da2e3ebchin#define PROTO_RETAIN		(1<<11)	/* defines retained after close	*/
94da2e3ebchin#define PROTO_TEST		(1<<12)	/* enable test code		*/
95da2e3ebchin
96da2e3ebchin#define PROTO_USER		(1<<13)	/* first user flag		*/
97da2e3ebchin
98da2e3ebchin#define SEARCH_EXISTS		0	/* ppsearch for existence	*/
99da2e3ebchin#define SEARCH_HOSTED		(1<<0)	/* search hosted dirs only	*/
100da2e3ebchin#define SEARCH_IGNORE		(1<<1)	/* ignore if not found		*/
101da2e3ebchin#define SEARCH_INCLUDE		(1<<2)	/* ppsearch for include		*/
102da2e3ebchin#define SEARCH_VENDOR		(1<<3)	/* search vendor dirs only	*/
103da2e3ebchin#define SEARCH_USER		(1<<4)	/* first user flag		*/
104da2e3ebchin
105da2e3ebchin#define STYLE_gnu		(1<<0)	/* gnu style args		*/
106da2e3ebchin
107da2e3ebchin#define IN_c			(1<<0)	/* C language file		*/
108da2e3ebchin#define IN_defguard		(1<<1)	/* did multiple include check	*/
109da2e3ebchin#define IN_disable		(1<<2)	/* saved state&DISABLE		*/
110da2e3ebchin#define IN_endguard		(1<<3)	/* did multiple include check	*/
111da2e3ebchin#define IN_eof			(1<<4)	/* reached EOF			*/
112da2e3ebchin#define IN_expand		(1<<5)	/* ppexpand buffer		*/
113da2e3ebchin#define IN_flush		(1<<6)	/* flush stdout on file_refill()*/
114da2e3ebchin#define IN_hosted		(1<<7)	/* saved mode&HOSTED		*/
115da2e3ebchin#define IN_ignoreline		(1<<8)	/* ignore #line until file	*/
116da2e3ebchin#define IN_newline		(1<<9)	/* newline at end of last fill	*/
117da2e3ebchin#define IN_noguard		(1<<10)	/* no multiple include guard	*/
118da2e3ebchin#define IN_prototype		(1<<11)	/* ppproto() input		*/
119da2e3ebchin#define IN_regular		(1<<12)	/* regular input file		*/
120da2e3ebchin#define IN_static		(1<<13)	/* static buffer - don't free	*/
121da2e3ebchin#define IN_sync			(1<<14)	/* line sync required on pop	*/
122da2e3ebchin#define IN_tokens		(1L<<15)/* non-space tokens encountered	*/
123da2e3ebchin
124da2e3ebchin#define OPT_GLOBAL		(1<<0)	/* pp: pass optional		*/
125da2e3ebchin#define OPT_PASS		(1<<1)	/* pass on			*/
126da2e3ebchin
127da2e3ebchinstruct ppsymbol;
128da2e3ebchinstruct ppindex;
129da2e3ebchin
130da2e3ebchintypedef char*	(*PPBUILTIN)(char*, const char*, const char*);
131da2e3ebchintypedef void	(*PPCOMMENT)(const char*, const char*, const char*, int);
132da2e3ebchintypedef void	(*PPINCREF)(const char*, const char*, int, int);
133da2e3ebchintypedef void	(*PPLINESYNC)(int, const char*);
134da2e3ebchintypedef void	(*PPMACREF)(struct ppsymbol*, const char*, int, int, unsigned long);
135da2e3ebchintypedef int	(*PPOPTARG)(int, int, const char*);
136da2e3ebchintypedef void	(*PPPRAGMA)(const char*, const char*, const char*, const char*, int);
137da2e3ebchin
138da2e3ebchinstruct ppinstk				/* input stream stack frame	*/
139da2e3ebchin{
140da2e3ebchin	char*		nextchr;	/* next input char (first elt)	*/
141da2e3ebchin	struct ppinstk*	next;		/* next frame (for allocation)	*/
142da2e3ebchin	struct ppinstk*	prev;		/* previous frame		*/
143da2e3ebchin	long*		control;	/* control block level		*/
144da2e3ebchin	char*		buffer;		/* buffer base pointer		*/
145da2e3ebchin	char*		file;		/* saved file name		*/
146da2e3ebchin	char*		prefix;		/* directory prefix		*/
147da2e3ebchin	struct ppsymbol* symbol;	/* macro info			*/
148da2e3ebchin#if CHECKPOINT
149da2e3ebchin	struct ppindex*	index;		/* checkpoint include index	*/
150da2e3ebchin	int		buflen;		/* buffer count			*/
151da2e3ebchin#endif
152da2e3ebchin	int		line;		/* saved line number		*/
153da2e3ebchin	int		vendor;		/* saved pp.vendor		*/
154da2e3ebchin	short		fd;		/* file descriptor		*/
155da2e3ebchin	short		hide;		/* hide index (from pp.hide)	*/
156da2e3ebchin	short		flags;		/* IN_[a-z]* flags		*/
157da2e3ebchin	char		type;		/* input type			*/
158da2e3ebchin};
159da2e3ebchin
160da2e3ebchin#if MACKEYARGS
161da2e3ebchinstruct ppkeyarg				/* pp macro keyword arg info	*/
162da2e3ebchin{
163da2e3ebchin	char*		name;		/* keyword arg name		*/
164da2e3ebchin	char*		value;		/* keyword arg value		*/
165da2e3ebchin};
166da2e3ebchin#endif
167da2e3ebchin
168da2e3ebchinstruct pplist				/* string list			*/
169da2e3ebchin{
170da2e3ebchin	char*		value;		/* string value			*/
171da2e3ebchin	struct pplist*	next;		/* next in list			*/
172da2e3ebchin};
173da2e3ebchin
174da2e3ebchinstruct oplist				/* queue op until PP_INIT	*/
175da2e3ebchin{
176da2e3ebchin	int		op;		/* PP_* op			*/
177da2e3ebchin	char*		value;		/* op value			*/
178da2e3ebchin	struct oplist*	next;		/* next op			*/
179da2e3ebchin};
180da2e3ebchin
181da2e3ebchinstruct pphide				/* hidden symbol info		*/
182da2e3ebchin{
183da2e3ebchin	struct ppmacro*	macro;		/* saved macro info		*/
184da2e3ebchin	unsigned long	flags;		/* saved symbol flags if macro	*/
185da2e3ebchin	int		level;		/* nesting level		*/
186da2e3ebchin};
187da2e3ebchin
188da2e3ebchinstruct ppmacstk				/* macro invocation stack frame	*/
189da2e3ebchin{
190da2e3ebchin	struct ppmacstk* next;		/* next frame (for allocation)	*/
191da2e3ebchin	struct ppmacstk* prev;		/* previous frame		*/
192da2e3ebchin	int		line;		/* line number of first arg	*/
193da2e3ebchin	char*		arg[1];		/* arg text pointers		*/
194da2e3ebchin};
195da2e3ebchin
196da2e3ebchinstruct ppmember				/* archive member pun on ppfile	*/
197da2e3ebchin{
198da2e3ebchin	struct ppdirs*	archive;	/* archive holding file		*/
199da2e3ebchin	unsigned long	offset;		/* data offset			*/
200da2e3ebchin	unsigned long	size;		/* data size			*/
201da2e3ebchin};
202da2e3ebchin
203da2e3ebchinstruct counter				/* monitoring counters		*/
204da2e3ebchin{
205da2e3ebchin	int		candidate;	/* macro candidates		*/
206da2e3ebchin	int		function;	/* function macros		*/
207da2e3ebchin	int		macro;		/* macro hits			*/
208da2e3ebchin	int		pplex;		/* pplex() calls		*/
209da2e3ebchin	int		push;		/* input stream pushes		*/
210da2e3ebchin	int		terminal;	/* terminal states		*/
211da2e3ebchin	int		token;		/* emitted tokens		*/
212da2e3ebchin};
213da2e3ebchin
214da2e3ebchinstruct pptuple				/* tuple macro			*/
215da2e3ebchin{
216da2e3ebchin	struct pptuple*	nomatch;	/* nomatch tuple		*/
217da2e3ebchin	struct pptuple*	match;		/* match tuple			*/
218da2e3ebchin	char		token[1];	/* matching token		*/
219da2e3ebchin};
220da2e3ebchin
221da2e3ebchinstruct ppfileid				/* physical file id		*/
222da2e3ebchin{
223da2e3ebchin	unsigned long	st_dev;		/* dev				*/
224da2e3ebchin	unsigned long	st_ino;		/* ino				*/
225da2e3ebchin};
226da2e3ebchin
227da2e3ebchinstruct pathid				/* physical file name and id	*/
228da2e3ebchin{
229da2e3ebchin	char*		path;		/* file path			*/
230da2e3ebchin	struct ppfileid	id;		/* file id			*/
231da2e3ebchin};
232da2e3ebchin
233da2e3ebchin#define SAMEID(a,b)	((a)->st_ino==(unsigned long)(b)->st_ino&&(a)->st_dev==(unsigned long)(b)->st_dev)
234da2e3ebchin#define SAVEID(a,b)	((a)->st_ino=(unsigned long)(b)->st_ino,(a)->st_dev=(unsigned long)(b)->st_dev)
235da2e3ebchin
236da2e3ebchin#define _PP_CONTEXT_PRIVATE_		/* ppglobals private context	*/ \
237da2e3ebchin	struct ppcontext* context;	/* current context		*/ \
238da2e3ebchin	long		state;		/* pp state flags		*/ \
239da2e3ebchin	long		mode;		/* uncoupled pp state flags	*/ \
240da2e3ebchin	long		option;		/* option flags			*/ \
241da2e3ebchin	long		test;		/* implementation tests		*/ \
242da2e3ebchin	struct								   \
243da2e3ebchin	{								   \
244da2e3ebchin	Sfio_t*		sp;		/* FILEDEPS output stream	*/ \
245da2e3ebchin	long		flags;		/* PP_FILEDEPS flags		*/ \
246da2e3ebchin	}		filedeps;	/* FILEDEPS info		*/ \
247da2e3ebchin	struct ppdirs*	firstdir;	/* first include dir		*/ \
248da2e3ebchin	struct ppdirs*	lastdir;	/* last include dir		*/ \
249da2e3ebchin	int		hide;		/* current include hide index	*/ \
250da2e3ebchin	int		column;		/* FILEDEPS column		*/ \
251da2e3ebchin	int		pending;	/* ppline() pending output	*/ \
252da2e3ebchin	char*		firstfile;	/* ppline() first file		*/ \
253da2e3ebchin	char*		lastfile;	/* ppline() most recent file	*/ \
254da2e3ebchin	char*		ignore;		/* include ignore list file	*/ \
255da2e3ebchin	char*		probe;		/* ppdefault probe key		*/ \
256da2e3ebchin	Hash_table_t*	filtab;		/* file name hash table		*/ \
257da2e3ebchin	Hash_table_t*	prdtab;		/* predicate hash table		*/ \
258da2e3ebchin	char*		date;		/* start date string		*/ \
259da2e3ebchin	char*		time;		/* start time string		*/ \
260da2e3ebchin	char*		maps;		/* directive maps		*/ \
261da2e3ebchin	long		ro_state;	/* readonly state		*/ \
262da2e3ebchin	long		ro_mode;	/* readonly mode		*/ \
263da2e3ebchin	long		ro_option;	/* readonly option		*/ \
264da2e3ebchin	struct pathid	cdir;		/* arg C dir			*/ \
265da2e3ebchin	struct pathid	hostdir;	/* arg host dir			*/ \
266da2e3ebchin	char*		ppdefault;	/* arg default info file	*/ \
267da2e3ebchin	struct ppindex*	firstindex;	/* first include index entry	*/ \
268da2e3ebchin	struct ppindex*	lastindex;	/* last include index entry	*/ \
269da2e3ebchin	struct oplist*	firstop;	/* first arg op			*/ \
270da2e3ebchin	struct oplist*	lastop;		/* last arg op			*/ \
271da2e3ebchin	struct oplist*	firsttx;	/* first text file		*/ \
272da2e3ebchin	struct oplist*	lasttx;		/* last text file		*/ \
273da2e3ebchin	unsigned char	arg_file;	/* arg file index		*/ \
274da2e3ebchin	unsigned char	arg_mode;	/* arg mode			*/ \
275da2e3ebchin	unsigned char	arg_style;	/* arg style			*/ \
276da2e3ebchin	unsigned char	c;		/* arg C state			*/ \
277da2e3ebchin	unsigned char	hosted;		/* arg hosted state		*/ \
278da2e3ebchin	unsigned char	ignoresrc;	/* arg ignore source state	*/ \
279da2e3ebchin	unsigned char	initialized;	/* arg initialized state	*/ \
280da2e3ebchin	unsigned char	standalone;	/* arg standalone state		*/ \
281da2e3ebchin	unsigned char	spare_1;	/* padding spare		*/
282da2e3ebchin
283da2e3ebchin#define _PP_GLOBALS_PRIVATE_		/* ppglobals private additions	*/ \
284da2e3ebchin	char*		checkpoint;	/* checkpoint version		*/ \
285da2e3ebchin	int		constack;	/* pp.control size		*/ \
286da2e3ebchin	struct ppinstk*	in;		/* input stream stack pointer	*/ \
287da2e3ebchin	char*		addp;	    	/* addbuf pointer		*/ \
288da2e3ebchin	char*		args;		/* predicate args		*/ \
289da2e3ebchin	char*		addbuf;		/* ADD buffer			*/ \
290da2e3ebchin	char*		catbuf;		/* catenation buffer		*/ \
291da2e3ebchin	char*		hdrbuf;		/* HEADEREXPAND buffer		*/ \
292da2e3ebchin	char*		hidebuf;	/* pp:hide buffer		*/ \
293da2e3ebchin	char*		path;		/* full path of last #include	*/ \
294da2e3ebchin	char*		tmpbuf;		/* very temporary buffer	*/ \
295da2e3ebchin	char*		valbuf;		/* builtin macro value buffer	*/ \
296da2e3ebchin	char*		optflags;	/* OPT_* flags indexed by X_*	*/ \
297da2e3ebchin	int		lastout;	/* last output char		*/ \
298da2e3ebchin		/* the rest are implicitly initialized */ \
299da2e3ebchin	char*		include;	/* saved path of last #include	*/ \
300da2e3ebchin	char*		prefix;		/* current directory prefix	*/ \
301da2e3ebchin	struct ppmember* member;	/* include archive member data	*/ \
302da2e3ebchin	int		hidden;		/* hidden newline count		*/ \
303da2e3ebchin	int		hiding;		/* number of symbols in hiding	*/ \
304da2e3ebchin	int		level;		/* pplex() recursion level	*/ \
305da2e3ebchin	struct								   \
306da2e3ebchin	{								   \
307da2e3ebchin	int		input;		/* pool input			*/ \
308da2e3ebchin	int		output;		/* pool output			*/ \
309da2e3ebchin	}		pool;		/* loop on input,output,error	*/ \
310da2e3ebchin	struct								   \
311da2e3ebchin	{								   \
312da2e3ebchin	long		ro_state;	/* original pp.ro_state		*/ \
313da2e3ebchin	long		ro_mode;	/* original pp.ro_mode		*/ \
314da2e3ebchin	long		ro_option;	/* original pp.ro_option	*/ \
315da2e3ebchin	int		on;		/* PP_RESET enabled		*/ \
316da2e3ebchin	Hash_table_t*	symtab;		/* original pp.symtab scope	*/ \
317da2e3ebchin	}		reset;		/* PP_RESET state		*/ \
318da2e3ebchin	int		truncate;	/* identifier truncation length	*/ \
319da2e3ebchin	struct ppmacstk* macp;		/* top of macro actual stack	*/ \
320da2e3ebchin	char*		maxmac;		/* maximum size of macro stack	*/ \
321da2e3ebchin	char*		mactop;		/* top of current macro frame	*/ \
322da2e3ebchin	char*		toknxt;		/* '\0' of pp.token		*/ \
323da2e3ebchin	long*		control;	/* control block flags pointer	*/ \
324da2e3ebchin	long*		maxcon;		/* max control block frame	*/ \
325da2e3ebchin	struct oplist*	chop;		/* include prefix chop list	*/ \
326da2e3ebchin	struct ppfile*	insert;		/* inserted line sync file	*/ \
327da2e3ebchin	struct ppfile*	original;	/* original include name	*/ \
328da2e3ebchin	struct ppdirs*	found;		/* last successful ppsearch dir	*/ \
329da2e3ebchin	int		vendor;		/* vendor includes only		*/ \
330da2e3ebchin	Hash_table_t*	dirtab;		/* directive hash table		*/ \
331da2e3ebchin	Hash_table_t*	strtab;		/* string hash table		*/ \
332da2e3ebchin	PPBUILTIN	builtin;	/* builtin macro handler	*/ \
333da2e3ebchin	PPCOMMENT	comment;	/* pass along comments		*/ \
334da2e3ebchin	PPINCREF	incref;		/* include file push/return	*/ \
335da2e3ebchin	PPLINESYNC	linesync;	/* pass along line sync info	*/ \
336da2e3ebchin	PPLINESYNC	olinesync;	/* original linesync value	*/ \
337da2e3ebchin	PPMACREF	macref;		/* called on macro def/ref	*/ \
338da2e3ebchin	PPOPTARG	optarg;		/* unknown option arg handler	*/ \
339da2e3ebchin	PPPRAGMA	pragma;		/* pass along unknown pragmas	*/ \
340da2e3ebchin	struct counter	counter;	/* monitoring counters		*/ \
341da2e3ebchin	char		funbuf[256];	/* last __FUNCTION__		*/
342da2e3ebchin
343da2e3ebchin#define _PP_SYMBOL_PRIVATE_		/* ppsymbol private additions	*/ \
344da2e3ebchin	struct pphide*	hidden;		/* hidden symbol info		*/
345da2e3ebchin
346da2e3ebchin#if MACKEYARGS
347da2e3ebchin#define _PP_MACRO_PRIVATE_		/* ppmacro private additions	*/ \
348da2e3ebchin	struct pptuple*	tuple;		/* tuple macro			*/ \
349da2e3ebchin	union								   \
350da2e3ebchin	{								   \
351da2e3ebchin	char*		formal;		/* normal formals list		*/ \
352da2e3ebchin	struct ppkeyarg* key;		/* keyword formals table	*/ \
353da2e3ebchin	}		args;		/* macro args info		*/ \
354da2e3ebchin	int		size;		/* body size			*/
355da2e3ebchin#define formals		args.formal	/* formal argument list		*/
356da2e3ebchin#define formkeys	args.key	/* formal keyword argument list	*/
357da2e3ebchin#else
358da2e3ebchin#define _PP_MACRO_PRIVATE_		/* ppmacro private additions	*/ \
359da2e3ebchin	struct pptuple*	tuple;		/* tuple macro			*/ \
360da2e3ebchin	char*		formals;	/* formal argument list		*/ \
361da2e3ebchin	int		size;		/* body size			*/
362da2e3ebchin#endif
363da2e3ebchin
364da2e3ebchin#define _PP_DIRS_PRIVATE_		/* ppdirs private additions	*/ \
365da2e3ebchin	unsigned char	c;		/* files here are C language	*/ \
366da2e3ebchin	unsigned char	index;		/* prefix,local,standard index	*/ \
367da2e3ebchin	unsigned char	type;		/* dir type			*/ \
368da2e3ebchin	union								   \
369da2e3ebchin	{								   \
370da2e3ebchin	char*		buffer;		/* TYPE_BUFFER buffer		*/ \
371da2e3ebchin	Sfio_t*		sp;		/* archive stream		*/ \
372da2e3ebchin	struct ppdirs*	subdir;		/* subdir list			*/ \
373da2e3ebchin	}		info;		/* type info			*/ \
374da2e3ebchin	struct ppfileid	id;		/* directory id			*/ \
375da2e3ebchin
376da2e3ebchin#if !PROTOMAIN
377da2e3ebchin#include <ast.h>
378da2e3ebchin#include <error.h>
379da2e3ebchin#endif
380da2e3ebchin
381da2e3ebchin#undef	newof
382da2e3ebchin#define newof(p,t,n,x)	((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
383da2e3ebchin
384da2e3ebchin#include "pp.h"
385da2e3ebchin#include "ppdef.h"
386da2e3ebchin#include "ppkey.h"
387da2e3ebchin
388da2e3ebchin#undef	setstate			/* random clash!		*/
389da2e3ebchin
390da2e3ebchin/*
391da2e3ebchin * DEBUG is encoded with the following bits
392da2e3ebchin */
393da2e3ebchin
394da2e3ebchin#define TRACE_message		01
395da2e3ebchin#define TRACE_count		02
396da2e3ebchin#define TRACE_debug		04
397da2e3ebchin
398da2e3ebchin#if DEBUG && !lint
399da2e3ebchin#define	PANIC		(ERROR_PANIC|ERROR_SOURCE|ERROR_SYSTEM),__FILE__,__LINE__
400da2e3ebchin#else
401da2e3ebchin#define	PANIC		ERROR_PANIC
402da2e3ebchin#endif
403da2e3ebchin
404da2e3ebchin#if DEBUG & TRACE_count
405da2e3ebchin#define count(x)	pp.counter.x++
406da2e3ebchin#else
407da2e3ebchin#define count(x)
408da2e3ebchin#endif
409da2e3ebchin
410da2e3ebchin#if DEBUG & TRACE_message
411da2e3ebchin#define message(x)	do { if (tracing) error x; } while (0)
412da2e3ebchin#else
413da2e3ebchin#define message(x)
414da2e3ebchin#endif
415da2e3ebchin
416da2e3ebchin#if DEBUG & TRACE_debug
417da2e3ebchin#define debug(x)	do { if (tracing) error x; } while (0)
418da2e3ebchin#else
419da2e3ebchin#define debug(x)
420da2e3ebchin#endif
421da2e3ebchin
422da2e3ebchin/*
423da2e3ebchin * note that MEMCPY advances the associated pointers
424da2e3ebchin */
425da2e3ebchin
426da2e3ebchin#define MEMCPY(to,fr,n) \
427da2e3ebchin	do switch(n) \
428da2e3ebchin	{ default : memcpy(to,fr,n); to += n; fr += n; break; \
429da2e3ebchin	  case  7 : *to++ = *fr++; \
430da2e3ebchin	  case  6 : *to++ = *fr++; \
431da2e3ebchin	  case  5 : *to++ = *fr++; \
432da2e3ebchin	  case  4 : *to++ = *fr++; \
433da2e3ebchin	  case  3 : *to++ = *fr++; \
434da2e3ebchin	  case  2 : *to++ = *fr++; \
435da2e3ebchin	  case  1 : *to++ = *fr++; \
436da2e3ebchin	  case  0 : break; \
437da2e3ebchin	} while (0)
438da2e3ebchin
439da2e3ebchin#define NEWDIRECTIVE	(-1)
440da2e3ebchin
441da2e3ebchin#undef	dirname
442da2e3ebchin#undef	error
443da2e3ebchin
444da2e3ebchin#define dirname(x)	ppkeyname(x,1)
445da2e3ebchin#define error		pperror
446da2e3ebchin#define keyname(x)	ppkeyname(x,0)
447da2e3ebchin#define nextframe(m,p)	(m->next=m+(p-(char*)m+sizeof(struct ppmacstk)-1)/sizeof(struct ppmacstk)+1)
448da2e3ebchin#define popframe(m)	(m=m->prev)
449da2e3ebchin#define pptokchr(c)	pptokstr(NiL,(c))
450da2e3ebchin#define pushcontrol()	do { if (pp.control++ >= pp.maxcon) ppnest(); } while (0)
451da2e3ebchin#define pushframe(m)	(m->next->prev=m,m=m->next)
452da2e3ebchin#define setmode(m,v)	((v)?(pp.mode|=(m)):(pp.mode&=~(m)))
453da2e3ebchin#define setoption(m,v)	((v)?(pp.option|=(m)):(pp.option&=~(m)))
454da2e3ebchin#define setstate(s,v)	((v)?(pp.state|=(s)):(pp.state&=~(s)))
455da2e3ebchin#define tracing		(error_info.trace<0)
456da2e3ebchin
457da2e3ebchin#define ppgetfile(x)	((struct ppfile*)hashlook(pp.filtab,x,HASH_LOOKUP,NiL))
458da2e3ebchin#define ppsetfile(x)	((struct ppfile*)hashlook(pp.filtab,x,HASH_CREATE|HASH_SIZE(sizeof(struct ppfile)),NiL))
459da2e3ebchin
460da2e3ebchin#define ppkeyget(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_LOOKUP,NiL)
461da2e3ebchin#define ppkeyref(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_LOOKUP|HASH_INTERNAL,NiL)
462da2e3ebchin#define ppkeyset(t,n)	(struct ppsymkey*)hashlook(t,n,HASH_CREATE|HASH_SIZE(sizeof(struct ppsymkey)),NiL)
463da2e3ebchin
464da2e3ebchin#define MARK		'@'		/* internal mark		*/
465da2e3ebchin#define ARGOFFSET	'1'		/* macro arg mark offset	*/
466da2e3ebchin
467da2e3ebchin#define STRAPP(p,v,r)	do{r=(v);while((*p++)=(*r++));}while(0)
468da2e3ebchin#define STRCOPY(p,v,r)	do{r=(v);while((*p++)=(*r++));p--;}while(0)
469da2e3ebchin#define STRCOPY2(p,r)	do{while((*p++)=(*r++));p--;}while(0)
470da2e3ebchin
471da2e3ebchin#define SETFILE(p,v)	(p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'F',(long)v,MARK))
472da2e3ebchin#define SETLINE(p,v)	(p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'L',(long)v,MARK))
473da2e3ebchin
474da2e3ebchin#define peekchr()	(*pp.in->nextchr)
475da2e3ebchin#define ungetchr(c)	(*--pp.in->nextchr=(c))
476da2e3ebchin
477da2e3ebchin#define MAXID		255		/* maximum identifier size	*/
478da2e3ebchin#define MAXTOKEN	PPTOKSIZ	/* maximum token size		*/
479da2e3ebchin#define MAXFORMALS	64		/* maximum number macro formals	*/
480da2e3ebchin#define MAXHIDDEN	8		/* ppline if hidden>=MAXHIDDEN	*/
481da2e3ebchin#define DEFMACSTACK	(MAXFORMALS*32*32)/* default macstack size	*/
482da2e3ebchin
483da2e3ebchin#define FSM_COMPATIBILITY	1	/* compatibility mode		*/
484da2e3ebchin#define FSM_IDADD	2		/* add to identifer set		*/
485da2e3ebchin#define FSM_IDDEL	3		/* delete from identifer set	*/
486da2e3ebchin#define FSM_INIT	4		/* initilize			*/
487da2e3ebchin#define FSM_MACRO	5		/* add new macro		*/
488da2e3ebchin#define FSM_OPSPACE	6		/* handle <binop><space>=	*/
489da2e3ebchin#define FSM_PLUSPLUS	7		/* C++ lexical analysis		*/
490da2e3ebchin#define FSM_QUOTADD	8		/* add to quote set		*/
491da2e3ebchin#define FSM_QUOTDEL	9		/* delete from quote set	*/
492da2e3ebchin
493da2e3ebchin#define IN_TOP		01		/* top level -- directives ok	*/
494da2e3ebchin
495da2e3ebchin#define IN_BUFFER	(2|IN_TOP)	/* buffer of lines		*/
496da2e3ebchin#define IN_COPY		2		/* macro arg (copied)		*/
497da2e3ebchin#define IN_EXPAND	4		/* macro arg (expanded)		*/
498da2e3ebchin#define IN_FILE		(4|IN_TOP)	/* file				*/
499da2e3ebchin#define IN_INIT		(6|IN_TOP)	/* initialization IN_BUFFER	*/
500da2e3ebchin#define IN_MACRO	8		/* macro text			*/
501da2e3ebchin#define IN_MULTILINE	(8|IN_TOP)	/* multi-line macro text	*/
502da2e3ebchin#define IN_QUOTE	10		/* "..." macro arg (copied)	*/
503da2e3ebchin#define IN_RESCAN	(10|IN_TOP)	/* directive rescan buffer	*/
504da2e3ebchin#define IN_SQUOTE	12		/* '...' macro arg (copied)	*/
505da2e3ebchin#define IN_STRING	14		/* string			*/
506da2e3ebchin
507da2e3ebchin#define INC_CLEAR	((struct ppsymbol*)0)
508da2e3ebchin#define INC_IGNORE	((struct ppsymbol*)pp.addbuf)
509da2e3ebchin#define INC_TEST	((struct ppsymbol*)pp.catbuf)
510da2e3ebchin
511da2e3ebchin#define INC_BOUND(n)	(1<<(n))
512da2e3ebchin#define INC_MEMBER(n)	(1<<((n)+INC_MAX))
513da2e3ebchin#define INC_PREFIX	0
514da2e3ebchin#define INC_LOCAL	1
515da2e3ebchin#define INC_STANDARD	2
516da2e3ebchin#define INC_VENDOR	3
517da2e3ebchin#define INC_MAX		4
518da2e3ebchin#define INC_SELF	(1<<(2*INC_MAX+0))
519da2e3ebchin#define INC_EXISTS	(1<<(2*INC_MAX+1))
520da2e3ebchin#define INC_LISTED	(1<<(2*INC_MAX+2))
521da2e3ebchin#define INC_MAPALL	(1<<(2*INC_MAX+3))
522da2e3ebchin#define INC_MAPHOSTED	(1<<(2*INC_MAX+4))
523da2e3ebchin#define INC_MAPNOHOSTED	(1<<(2*INC_MAX+5))
524da2e3ebchin#define INC_MAPNOLOCAL	(1<<(2*INC_MAX+6))
525da2e3ebchin#define INC_HOSTED	(1<<(2*INC_MAX+7))
526da2e3ebchin
527da2e3ebchin#define TYPE_ARCHIVE	(1<<0)
528da2e3ebchin#define TYPE_BUFFER	(1<<1)
529da2e3ebchin#define TYPE_CHECKPOINT	(1<<2)
530da2e3ebchin#define TYPE_DIRECTORY	(1<<3)
531da2e3ebchin#define TYPE_HOSTED	(1<<4)
532da2e3ebchin#define TYPE_INCLUDE	(1<<5)
533da2e3ebchin#define TYPE_VENDOR	(1<<6)
534da2e3ebchin
535da2e3ebchin#define TOK_BUILTIN	(1<<0)		/* last token was #(		*/
536da2e3ebchin#define TOK_FORMAL	(1<<1)		/* last token was arg formal id	*/
537da2e3ebchin#define TOK_ID		(1<<2)		/* last token was identifier	*/
538da2e3ebchin#define TOK_TOKCAT	(1<<3)		/* last token was ##		*/
539da2e3ebchin
540da2e3ebchin#define HADELSE		(1<<0)		/* already had else part	*/
541da2e3ebchin#define KEPT		(1<<1)		/* already kept part of block	*/
542da2e3ebchin#define SKIP		(1<<2)		/* skip this block		*/
543da2e3ebchin#define BLOCKBITS	3		/* block flag bits		*/
544da2e3ebchin
545da2e3ebchin#define SETIFBLOCK(p)	(*(p)=(*((p)-1)&SKIP)|((long)error_info.line<<BLOCKBITS))
546da2e3ebchin#define GETIFLINE(p)	((*(p)>>BLOCKBITS)&((1L<<(sizeof(long)*CHAR_BIT-BLOCKBITS))-1))
547da2e3ebchin
548da2e3ebchin#define PUSH(t,p)		\
549da2e3ebchin	do \
550da2e3ebchin	{ \
551da2e3ebchin		count(push); \
552da2e3ebchin		if (!pp.in->next) \
553da2e3ebchin		{ \
554da2e3ebchin			pp.in->next = newof(0, struct ppinstk, 1, 0); \
555da2e3ebchin			pp.in->next->prev = pp.in; \
556da2e3ebchin		} \
557da2e3ebchin		p = pp.in = pp.in->next; \
558da2e3ebchin		p->type = t; \
559da2e3ebchin		p->flags = 0; \
560da2e3ebchin	} while (0)
561da2e3ebchin
562da2e3ebchin#define PUSH_BUFFER(f,p,n)		\
563da2e3ebchin	pppush(IN_BUFFER,f,p,n)
564da2e3ebchin
565da2e3ebchin#define PUSH_COPY(p,n)		\
566da2e3ebchin	do \
567da2e3ebchin	{ \
568da2e3ebchin		register struct ppinstk*	cur; \
569da2e3ebchin		PUSH(IN_COPY, cur); \
570da2e3ebchin		cur->line = error_info.line; \
571da2e3ebchin		error_info.line = n; \
572da2e3ebchin		cur->nextchr = p; \
573da2e3ebchin		cur->prev->symbol->flags &= ~SYM_DISABLED; \
574da2e3ebchin		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
575da2e3ebchin	} while (0)
576da2e3ebchin
577da2e3ebchin#define PUSH_EXPAND(p,n)	\
578da2e3ebchin	do \
579da2e3ebchin	{ \
580da2e3ebchin		register struct ppinstk*	cur; \
581da2e3ebchin		PUSH(IN_EXPAND, cur); \
582da2e3ebchin		cur->line = error_info.line; \
583da2e3ebchin		error_info.line = n; \
584da2e3ebchin		cur->prev->symbol->flags &= ~SYM_DISABLED; \
585da2e3ebchin		cur->buffer = cur->nextchr = ppexpand(p); \
586da2e3ebchin		if (!(cur->prev->symbol->flags & SYM_MULTILINE)) \
587da2e3ebchin			cur->prev->symbol->flags |= SYM_DISABLED; \
588da2e3ebchin		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
589da2e3ebchin	} while (0)
590da2e3ebchin
591da2e3ebchin#define PUSH_FILE(f,d)	\
592da2e3ebchin	pppush(IN_FILE,f,NiL,d)
593da2e3ebchin
594da2e3ebchin#define PUSH_INIT(f,p)	\
595da2e3ebchin	pppush(IN_INIT,f,p,1)
596da2e3ebchin
597da2e3ebchin#define PUSH_MACRO(p)		\
598da2e3ebchin	do \
599da2e3ebchin	{ \
600da2e3ebchin		register struct ppinstk*	cur; \
601da2e3ebchin		PUSH(IN_MACRO, cur); \
602da2e3ebchin		cur->symbol = p; \
603da2e3ebchin		cur->nextchr = p->macro->value; \
604da2e3ebchin		p->flags |= SYM_DISABLED; \
605da2e3ebchin		if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
606da2e3ebchin		pp.state &= ~NEWLINE; \
607da2e3ebchin		debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
608da2e3ebchin	} while (0)
609da2e3ebchin
610da2e3ebchin#define PUSH_TUPLE(p,v)		\
611da2e3ebchin	do \
612da2e3ebchin	{ \
613da2e3ebchin		register struct ppinstk*	cur; \
614da2e3ebchin		PUSH(IN_MACRO, cur); \
615da2e3ebchin		cur->symbol = p; \
616da2e3ebchin		cur->nextchr = v; \
617