xref: /titanic_41/usr/src/lib/libpp/common/ppproto.c (revision 34f9b3eef6fdadbda0a846aa4d68691ac40eace5)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*34f9b3eeSRoland Mainz *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
26da2e3ebdSchin  * slips into the pp block read
27da2e3ebdSchin  *
28da2e3ebdSchin  * define PROTOMAIN for standalone proto
29da2e3ebdSchin  * PROTOMAIN is coded for minimal library support
30da2e3ebdSchin  */
31da2e3ebdSchin 
327c2fbfb3SApril Chin static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2008-05-11 $\0\n";
33da2e3ebdSchin 
34da2e3ebdSchin #if PROTOMAIN
35da2e3ebdSchin 
36da2e3ebdSchin #include "ppfsm.c"
37da2e3ebdSchin 
38da2e3ebdSchin #include <hashkey.h>
39da2e3ebdSchin 
40da2e3ebdSchin #if PROTO_STANDALONE
41da2e3ebdSchin #undef	O_RDONLY
42da2e3ebdSchin #endif
43da2e3ebdSchin 
44da2e3ebdSchin #else
45da2e3ebdSchin 
46da2e3ebdSchin #include "pplib.h"
47da2e3ebdSchin #include "ppfsm.h"
48da2e3ebdSchin 
49da2e3ebdSchin #endif
50da2e3ebdSchin 
51da2e3ebdSchin #define MAGICGEN	"/* : : generated by proto : : */\n"
52da2e3ebdSchin 
53da2e3ebdSchin #define MAGICDIR	"pragma"	/* proto magic directive	*/
54da2e3ebdSchin #define MAGICARG	"prototyped"	/* proto magic directive arg	*/
55da2e3ebdSchin #define MAGICOFF	"noticed"	/* no notice if found in pragma	*/
56da2e3ebdSchin #define MAGICTOP	64		/* must be in these top lines	*/
57da2e3ebdSchin #define NOTICED		"Copyright"	/* no notice if found in magic	*/
587c2fbfb3SApril Chin #define PUBLICDOMAIN	"Public Domain"	/* no notice if found in magic	*/
59da2e3ebdSchin 
60da2e3ebdSchin struct proto				/* proto buffer state		*/
61da2e3ebdSchin {
62da2e3ebdSchin 	int		brace;		/* {..} level			*/
63da2e3ebdSchin 	int		call;		/* call level			*/
64da2e3ebdSchin 	int		fd;		/* input file descriptor	*/
65da2e3ebdSchin 	char*		file;		/* input file name		*/
66da2e3ebdSchin 	long		flags;		/* coupled flags		*/
67da2e3ebdSchin 	long		options;	/* uncoupled flags		*/
68da2e3ebdSchin 	char*		package;	/* header package		*/
69da2e3ebdSchin 	int		line;		/* input line count		*/
70da2e3ebdSchin 	int		test;		/* testing			*/
71da2e3ebdSchin 
72da2e3ebdSchin 	char*		tp;		/* input token base		*/
73da2e3ebdSchin 
74da2e3ebdSchin 	int		iz;		/* input buffer size		*/
75da2e3ebdSchin 	char*		ib;		/* input buffer base		*/
76da2e3ebdSchin 	char*		ip;		/* input buffer pointer		*/
77da2e3ebdSchin 
78da2e3ebdSchin 	int		oz;		/* output buffer size		*/
79da2e3ebdSchin 	char*		ob;		/* output buffer base		*/
80da2e3ebdSchin 	char*		op;		/* output buffer pointer	*/
81da2e3ebdSchin 	char*		ox;		/* output buffer externalize	*/
82da2e3ebdSchin 
83da2e3ebdSchin 	char		cc[3];		/* beg mid end comment char	*/
84da2e3ebdSchin 	char		pushback[4];	/* pushback area for caller	*/
85da2e3ebdSchin 
86da2e3ebdSchin 	char		variadic[256];	/* variadic args buffer		*/
87da2e3ebdSchin 
88da2e3ebdSchin 	/* output buffer */
89da2e3ebdSchin 	/* slide buffer */
90da2e3ebdSchin 	/* input buffer */
91da2e3ebdSchin };
92da2e3ebdSchin 
93da2e3ebdSchin /*
94da2e3ebdSchin  * proto is separate from pp so these undef's are ok
95da2e3ebdSchin  */
96da2e3ebdSchin 
97da2e3ebdSchin #undef	CLASSIC
98da2e3ebdSchin #define CLASSIC		(1L<<0)
99da2e3ebdSchin #undef	DECLARE
100da2e3ebdSchin #define DECLARE		(1L<<1)
101da2e3ebdSchin #undef	DEFINE
102da2e3ebdSchin #define DEFINE		(1L<<2)
103da2e3ebdSchin #undef	DIRECTIVE
104da2e3ebdSchin #define DIRECTIVE	(1L<<3)
105da2e3ebdSchin #undef	ERROR
106da2e3ebdSchin #define ERROR		(1L<<4)
107da2e3ebdSchin #undef	EXTERN
108da2e3ebdSchin #define EXTERN		(1L<<5)
109da2e3ebdSchin #undef	EXTERNALIZE
110da2e3ebdSchin #define EXTERNALIZE	(1L<<6)
111da2e3ebdSchin #undef	IDID
112da2e3ebdSchin #define IDID		(1L<<7)
113da2e3ebdSchin #undef	INDIRECT
114da2e3ebdSchin #define INDIRECT	(1L<<8)
115da2e3ebdSchin #undef	INIT
116da2e3ebdSchin #define INIT		(1L<<9)
117da2e3ebdSchin #undef	INIT_DEFINE
118da2e3ebdSchin #define INIT_DEFINE	(1L<<10)
119da2e3ebdSchin #undef	INIT_INCLUDE
120da2e3ebdSchin #define INIT_INCLUDE	(1L<<11)
121da2e3ebdSchin #undef	JUNK
122da2e3ebdSchin #define JUNK		(1L<<12)
123da2e3ebdSchin #undef	LINESYNC
124da2e3ebdSchin #define LINESYNC	(1L<<13)
125da2e3ebdSchin #undef	MANGLE
126da2e3ebdSchin #define MANGLE		(1L<<14)
127da2e3ebdSchin #undef	MATCH
128da2e3ebdSchin #define MATCH		(1L<<15)
129da2e3ebdSchin #undef	MORE
130da2e3ebdSchin #define MORE		(1L<<16)
131da2e3ebdSchin #undef	OTHER
132da2e3ebdSchin #define OTHER		(1L<<17)
133da2e3ebdSchin #undef	PASS
134da2e3ebdSchin #define PASS		(1L<<18)
135da2e3ebdSchin #undef	PLUSONLY
136da2e3ebdSchin #define PLUSONLY	(1L<<19)
137da2e3ebdSchin #undef	PLUSPLUS
138da2e3ebdSchin #define PLUSPLUS	(1L<<20)
139da2e3ebdSchin #undef	RECURSIVE
140da2e3ebdSchin #define RECURSIVE	(1L<<21)
141da2e3ebdSchin #undef	SHARP
142da2e3ebdSchin #define SHARP		(1L<<22)
143da2e3ebdSchin #undef	SKIP
144da2e3ebdSchin #define SKIP		(1L<<23)
145da2e3ebdSchin #undef	SLIDE
146da2e3ebdSchin #define SLIDE		(1L<<24)
147da2e3ebdSchin #undef	TOKENS
148da2e3ebdSchin #define TOKENS		(1L<<25)
149da2e3ebdSchin #undef	TYPEDEF
150da2e3ebdSchin #define TYPEDEF		(1L<<26)
151da2e3ebdSchin #undef	VARIADIC
152da2e3ebdSchin #define VARIADIC	(1L<<27)
153da2e3ebdSchin #undef	VARIADIC2
154da2e3ebdSchin #define VARIADIC2	(1L<<28)
155da2e3ebdSchin #undef	YACC
156da2e3ebdSchin #define YACC		(1L<<29)
157da2e3ebdSchin #undef	YACCSPLIT
158da2e3ebdSchin #define YACCSPLIT	(1L<<30)
159da2e3ebdSchin #undef	YACC2
160da2e3ebdSchin #define YACC2		(1L<<31)
161da2e3ebdSchin 
162da2e3ebdSchin #undef	GLOBAL
163da2e3ebdSchin #define GLOBAL		(MORE)
164da2e3ebdSchin 
165da2e3ebdSchin #undef	REGULAR
166da2e3ebdSchin #define REGULAR		(1L<<0)
167da2e3ebdSchin 
168da2e3ebdSchin #ifndef CHUNK
169da2e3ebdSchin #define CHUNK		1024
170da2e3ebdSchin #endif
171da2e3ebdSchin #define BLOCK		(8*CHUNK)
172da2e3ebdSchin 
173da2e3ebdSchin #define T_VA_START	(N_TOKEN+1)
174da2e3ebdSchin 
175da2e3ebdSchin #define RESERVED(b,e,n)	((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
176da2e3ebdSchin 
177da2e3ebdSchin /*
178da2e3ebdSchin  * generate integer
179da2e3ebdSchin  * pointer to end returned
180da2e3ebdSchin  */
181da2e3ebdSchin 
182da2e3ebdSchin static char*
number(register char * p,register long n)183da2e3ebdSchin number(register char* p, register long n)
184da2e3ebdSchin {
185da2e3ebdSchin 	register long	d;
186da2e3ebdSchin 
187da2e3ebdSchin 	for (d = 1000000; d > 1; d /= 10)
188da2e3ebdSchin 		if (n >= d) *p++ = '0' + (n / d) % 10;
189da2e3ebdSchin 	*p++ = '0' + n % 10;
190da2e3ebdSchin 	return p;
191da2e3ebdSchin }
192da2e3ebdSchin 
193da2e3ebdSchin #if PROTOMAIN
194da2e3ebdSchin 
195da2e3ebdSchin static int		errors;
196da2e3ebdSchin 
197da2e3ebdSchin #if PROTO_STANDALONE
198da2e3ebdSchin 
199da2e3ebdSchin /*
200da2e3ebdSchin  * namespace pollution forces us to claim parts of libc
201da2e3ebdSchin  */
202da2e3ebdSchin 
203da2e3ebdSchin #undef	memcpy
204da2e3ebdSchin #define memcpy(t,f,n)	memcopy(t,f,n)
205da2e3ebdSchin #undef	strcpy
206da2e3ebdSchin #define strcpy(t,f)	strcopy(t,f)
207da2e3ebdSchin #undef	strlen
208da2e3ebdSchin #define strlen(s)	sstrlen(s)
209da2e3ebdSchin #undef	strncmp
210da2e3ebdSchin #define strncmp(s,t,n)	sstrncmp(s,t,n)
211da2e3ebdSchin 
212da2e3ebdSchin /*
213da2e3ebdSchin  * environmentally safe strlen()
214da2e3ebdSchin  */
215da2e3ebdSchin 
216da2e3ebdSchin static int
sstrlen(register const char * s)217da2e3ebdSchin sstrlen(register const char* s)
218da2e3ebdSchin {
219da2e3ebdSchin 	register const char*	b;
220da2e3ebdSchin 
221da2e3ebdSchin 	for (b = s; *s; s++);
222da2e3ebdSchin 	return s - b;
223da2e3ebdSchin }
224da2e3ebdSchin 
225da2e3ebdSchin /*
226da2e3ebdSchin  * environmentally safe strncmp()
227da2e3ebdSchin  */
228da2e3ebdSchin 
229da2e3ebdSchin static int
sstrncmp(register const char * s,register char * t,register int n)230da2e3ebdSchin sstrncmp(register const char* s, register char* t, register int n)
231da2e3ebdSchin {
232da2e3ebdSchin 	register const char*	e = s + n;
233da2e3ebdSchin 
234da2e3ebdSchin 	while (s < e)
235da2e3ebdSchin 	{
236da2e3ebdSchin 		if (*s != *t || !*s)
237da2e3ebdSchin 			return *s - *t;
238da2e3ebdSchin 		s++;
239da2e3ebdSchin 		t++;
240da2e3ebdSchin 	}
241da2e3ebdSchin 	return 0;
242da2e3ebdSchin }
243da2e3ebdSchin 
244da2e3ebdSchin /*
245da2e3ebdSchin  * strcpy() except pointer to end returned
246da2e3ebdSchin  */
247da2e3ebdSchin 
248da2e3ebdSchin static char*
strcopy(register char * s,register const char * t)249da2e3ebdSchin strcopy(register char* s, register const char* t)
250da2e3ebdSchin {
251da2e3ebdSchin 	while (*s++ = *t++);
252da2e3ebdSchin 	return s - 1;
253da2e3ebdSchin }
254da2e3ebdSchin 
255da2e3ebdSchin #endif
256da2e3ebdSchin 
257da2e3ebdSchin static void
proto_error(char * iob,int level,char * msg,char * arg)258da2e3ebdSchin proto_error(char* iob, int level, char* msg, char* arg)
259da2e3ebdSchin {
260da2e3ebdSchin 	register char*	p;
261da2e3ebdSchin 	char		buf[1024];
262da2e3ebdSchin 
263da2e3ebdSchin 	p = strcopy(buf, "proto: ");
264da2e3ebdSchin 	if (iob)
265da2e3ebdSchin 	{
266da2e3ebdSchin 		register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
267da2e3ebdSchin 
268da2e3ebdSchin 		if (proto->line)
269da2e3ebdSchin 		{
270da2e3ebdSchin 			if (proto->file)
271da2e3ebdSchin 			{
272da2e3ebdSchin 				*p++ = '"';
273da2e3ebdSchin 				p = strcopy(p, proto->file);
274da2e3ebdSchin 				*p++ = '"';
275da2e3ebdSchin 				*p++ = ',';
276da2e3ebdSchin 				*p++ = ' ';
277da2e3ebdSchin 			}
278da2e3ebdSchin 			p = strcopy(p, "line ");
279da2e3ebdSchin 			p = number(p, proto->line);
280da2e3ebdSchin 		}
281da2e3ebdSchin 		else if (proto->file)
282da2e3ebdSchin 			p = strcopy(p, proto->file);
283da2e3ebdSchin 	}
284da2e3ebdSchin 	else
285da2e3ebdSchin 	{
286da2e3ebdSchin 		p = strcopy(p, msg);
287da2e3ebdSchin 		msg = arg;
288da2e3ebdSchin 		arg = 0;
289da2e3ebdSchin 	}
290da2e3ebdSchin 	if (*(p - 1) != ' ')
291da2e3ebdSchin 	{
292da2e3ebdSchin 		*p++ = ':';
293da2e3ebdSchin 		*p++ = ' ';
294da2e3ebdSchin 	}
295da2e3ebdSchin 	if (level == 1)
296da2e3ebdSchin 		p = strcopy(p, "warning: ");
297da2e3ebdSchin 	p = strcopy(p, msg);
298da2e3ebdSchin 	if (arg)
299da2e3ebdSchin 	{
300da2e3ebdSchin 		*p++ = ' ';
301da2e3ebdSchin 		p = strcopy(p, arg);
302da2e3ebdSchin 	}
303da2e3ebdSchin 	*p++ = '\n';
304da2e3ebdSchin 	write(2, buf, p - buf);
305da2e3ebdSchin 	if (level >= 3)
306da2e3ebdSchin 		exit(level - 2);
307da2e3ebdSchin 	if (level >= 2)
308da2e3ebdSchin 		errors++;
309da2e3ebdSchin }
310da2e3ebdSchin 
311da2e3ebdSchin /*
312da2e3ebdSchin  * memcpy() but pointer to end returned
313da2e3ebdSchin  */
314da2e3ebdSchin 
315da2e3ebdSchin static char*
memcopy(register char * s,register char * t,int n)316da2e3ebdSchin memcopy(register char* s, register char* t, int n)
317da2e3ebdSchin {
318da2e3ebdSchin 	register char*	e = t + n;
319da2e3ebdSchin 
320da2e3ebdSchin 	while (t < e) *s++ = *t++;
321da2e3ebdSchin 	return s;
322da2e3ebdSchin }
323da2e3ebdSchin 
324da2e3ebdSchin #include "../libast/port/astlicense.c"
325da2e3ebdSchin 
326da2e3ebdSchin #else
327da2e3ebdSchin 
328da2e3ebdSchin #define memcopy(s,t,n)	(((char*)memcpy(s,t,n))+(n))
329da2e3ebdSchin 
330da2e3ebdSchin #endif
331da2e3ebdSchin 
332da2e3ebdSchin /*
333da2e3ebdSchin  * generate line sync
334da2e3ebdSchin  * pointer to end returned
335da2e3ebdSchin  */
336da2e3ebdSchin 
337da2e3ebdSchin static char*
linesync(register struct proto * proto,register char * p,register long n)338da2e3ebdSchin linesync(register struct proto* proto, register char* p, register long n)
339da2e3ebdSchin {
340da2e3ebdSchin #if PROTOMAIN
341da2e3ebdSchin 	if (proto->flags & LINESYNC)
342da2e3ebdSchin #endif
343da2e3ebdSchin 	{
344da2e3ebdSchin #if PROTOMAIN
345da2e3ebdSchin 		p = strcopy(p, "\n#line ");
346da2e3ebdSchin #else
347da2e3ebdSchin 		p = strcopy(p, "\n# ");
348da2e3ebdSchin #endif
349da2e3ebdSchin 		p = number(p, n);
350da2e3ebdSchin 		*p++ = '\n';
351da2e3ebdSchin 	}
352da2e3ebdSchin 	return p;
353da2e3ebdSchin }
354da2e3ebdSchin 
355da2e3ebdSchin /*
356da2e3ebdSchin  * output init header
357da2e3ebdSchin  * pointer to end returned
358da2e3ebdSchin  */
359da2e3ebdSchin 
360da2e3ebdSchin static char*
init(struct proto * proto,char * op,int flags)361da2e3ebdSchin init(struct proto* proto, char* op, int flags)
362da2e3ebdSchin {
363da2e3ebdSchin 	register char*	s;
364da2e3ebdSchin 
365da2e3ebdSchin 	if (flags & INIT_DEFINE)
366da2e3ebdSchin 	{
367da2e3ebdSchin 		op = strcopy(op, "\
368da2e3ebdSchin \n\
369da2e3ebdSchin #if !defined(__PROTO__)\n\
370da2e3ebdSchin #  if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
371da2e3ebdSchin #    if defined(__cplusplus)\n\
372da2e3ebdSchin #      define __LINKAGE__	\"C\"\n\
373da2e3ebdSchin #    else\n\
374da2e3ebdSchin #      define __LINKAGE__\n\
375da2e3ebdSchin #    endif\n\
376da2e3ebdSchin #    define __STDARG__\n\
377da2e3ebdSchin #    define __PROTO__(x)	x\n\
378da2e3ebdSchin #    define __OTORP__(x)\n\
379da2e3ebdSchin #    define __PARAM__(n,o)	n\n\
380da2e3ebdSchin #    if !defined(__STDC__) && !defined(__cplusplus)\n\
381da2e3ebdSchin #      if !defined(c_plusplus)\n\
382da2e3ebdSchin #      	define const\n\
383da2e3ebdSchin #      endif\n\
384da2e3ebdSchin #      define signed\n\
385da2e3ebdSchin #      define void		int\n\
386da2e3ebdSchin #      define volatile\n\
387da2e3ebdSchin #      define __V_		char\n\
388da2e3ebdSchin #    else\n\
389da2e3ebdSchin #      define __V_		void\n\
390da2e3ebdSchin #    endif\n\
391da2e3ebdSchin #  else\n\
392da2e3ebdSchin #    define __PROTO__(x)	()\n\
393da2e3ebdSchin #    define __OTORP__(x)	x\n\
394da2e3ebdSchin #    define __PARAM__(n,o)	o\n\
395da2e3ebdSchin #    define __LINKAGE__\n\
396da2e3ebdSchin #    define __V_		char\n\
397da2e3ebdSchin #    define const\n\
398da2e3ebdSchin #    define signed\n\
399da2e3ebdSchin #    define void		int\n\
400da2e3ebdSchin #    define volatile\n\
401da2e3ebdSchin #  endif\n\
402da2e3ebdSchin #  define __MANGLE__	__LINKAGE__\n\
403da2e3ebdSchin #  if defined(__cplusplus) || defined(c_plusplus)\n\
404da2e3ebdSchin #    define __VARARG__	...\n\
405da2e3ebdSchin #  else\n\
406da2e3ebdSchin #    define __VARARG__\n\
407da2e3ebdSchin #  endif\n\
408da2e3ebdSchin #  if defined(__STDARG__)\n\
409da2e3ebdSchin #    define __VA_START__(p,a)	va_start(p,a)\n\
410da2e3ebdSchin #  else\n\
411da2e3ebdSchin #    define __VA_START__(p,a)	va_start(p)\n\
412da2e3ebdSchin #  endif\n\
413da2e3ebdSchin #  if !defined(__INLINE__)\n\
414da2e3ebdSchin #    if defined(__cplusplus)\n\
415da2e3ebdSchin #      define __INLINE__	extern __MANGLE__ inline\n\
416da2e3ebdSchin #    else\n\
417da2e3ebdSchin #      if defined(_WIN32) && !defined(__GNUC__)\n\
418da2e3ebdSchin #      	define __INLINE__	__inline\n\
419da2e3ebdSchin #      endif\n\
420da2e3ebdSchin #    endif\n\
421da2e3ebdSchin #  endif\n\
422da2e3ebdSchin #endif\n\
423da2e3ebdSchin #if !defined(__LINKAGE__)\n\
424da2e3ebdSchin #define __LINKAGE__		/* 2004-08-11 transition */\n\
425da2e3ebdSchin #endif\n\
426da2e3ebdSchin ");
427da2e3ebdSchin 	}
428da2e3ebdSchin 	else
429da2e3ebdSchin 		op = strcopy(op, "\
430da2e3ebdSchin \n\
431da2e3ebdSchin #if !defined(__PROTO__)\n\
432da2e3ebdSchin #include <prototyped.h>\n\
433da2e3ebdSchin #endif\n\
434da2e3ebdSchin #if !defined(__LINKAGE__)\n\
435da2e3ebdSchin #define __LINKAGE__		/* 2004-08-11 transition */\n\
436da2e3ebdSchin #endif\n\
437da2e3ebdSchin ");
438da2e3ebdSchin 	if (proto->package)
439da2e3ebdSchin 	{
440da2e3ebdSchin 		s = "\
441da2e3ebdSchin #ifndef	__MANGLE_%_DATA__\n\
442da2e3ebdSchin #  ifdef _BLD_%\n\
443da2e3ebdSchin #    ifdef __EXPORT__\n\
444da2e3ebdSchin #      define	__MANGLE_%_DATA__	__MANGLE__ __EXPORT__\n\
445da2e3ebdSchin #    else\n\
446da2e3ebdSchin #      define	__MANGLE_%_DATA__	__MANGLE__\n\
447da2e3ebdSchin #    endif\n\
448da2e3ebdSchin #    define	__MANGLE_%_FUNC__	__MANGLE__\n\
449da2e3ebdSchin #  else\n\
450da2e3ebdSchin #    ifdef __IMPORT__\n\
451da2e3ebdSchin #      define	__MANGLE_%_DATA__	__MANGLE__ __IMPORT__\n\
452da2e3ebdSchin #    else\n\
453da2e3ebdSchin #      define	__MANGLE_%_DATA__	__MANGLE__\n\
454da2e3ebdSchin #    endif\n\
455da2e3ebdSchin #    define	__MANGLE_%_FUNC__	__MANGLE__\n\
456da2e3ebdSchin #  endif\n\
457da2e3ebdSchin #endif\n\
458da2e3ebdSchin ";
459da2e3ebdSchin 		for (;;)
460da2e3ebdSchin 		{
461da2e3ebdSchin 			switch (*op++ = *s++)
462da2e3ebdSchin 			{
463da2e3ebdSchin 			case 0:
464da2e3ebdSchin 				op--;
465da2e3ebdSchin 				break;
466da2e3ebdSchin 			case '%':
467da2e3ebdSchin 				op = strcopy(op - 1, proto->package);
468da2e3ebdSchin 				continue;
469da2e3ebdSchin 			default:
470da2e3ebdSchin 				continue;
471da2e3ebdSchin 			}
472da2e3ebdSchin 			break;
473da2e3ebdSchin 		}
474da2e3ebdSchin 	}
475da2e3ebdSchin 	return op;
476da2e3ebdSchin }
477da2e3ebdSchin 
478da2e3ebdSchin #define BACKOUT()	(op=ko)
479da2e3ebdSchin #define CACHE()		do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
480da2e3ebdSchin #define CACHEIN()	(ip=proto->ip)
481da2e3ebdSchin #define CACHEOUT()	(op=proto->op)
482da2e3ebdSchin #define GETCHR()	(*(unsigned char*)ip++)
483da2e3ebdSchin #define KEEPOUT()	(ko=op)
484da2e3ebdSchin #define LASTOUT()	(*(op-1))
485da2e3ebdSchin #define PUTCHR(c)	(*op++=(c))
486da2e3ebdSchin #define SYNC()		do{SYNCIN();SYNCOUT();proto->flags&=~(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->flags|=flags&(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->call=call;}while(0)
487da2e3ebdSchin #define SYNCIN()	(proto->ip=ip)
488da2e3ebdSchin #define SYNCOUT()	(proto->op=op)
489da2e3ebdSchin #define UNGETCHR()	(ip--)
490da2e3ebdSchin #define UNPUTCHR()	(op--)
491da2e3ebdSchin 
492da2e3ebdSchin /*
493da2e3ebdSchin  * advance to the next non-space character
494da2e3ebdSchin  */
495da2e3ebdSchin 
496da2e3ebdSchin static char*
nns(register char * s)497da2e3ebdSchin nns(register char* s)
498da2e3ebdSchin {
499da2e3ebdSchin 	while (*s == ' ' || *s == '\t' || *s == '\n')
500da2e3ebdSchin 		s++;
501da2e3ebdSchin 	return s;
502da2e3ebdSchin }
503da2e3ebdSchin 
504da2e3ebdSchin #define DIR_if	01
505da2e3ebdSchin #define DIR_el	02
506da2e3ebdSchin #define DIR_en	03
507da2e3ebdSchin #define DIR	03
508da2e3ebdSchin 
509da2e3ebdSchin /*
510da2e3ebdSchin  * update directive mask
511da2e3ebdSchin  */
512da2e3ebdSchin 
513da2e3ebdSchin static int
directive(register char * s,int dir)514da2e3ebdSchin directive(register char* s, int dir)
515da2e3ebdSchin {
516da2e3ebdSchin 	switch (*(s = nns(s)))
517da2e3ebdSchin 	{
518da2e3ebdSchin 	case 'e':
519da2e3ebdSchin 	case 'i':
520da2e3ebdSchin 		dir <<= 2;
521da2e3ebdSchin 		switch (*++s)
522da2e3ebdSchin 		{
523da2e3ebdSchin 		case 'f':
524da2e3ebdSchin 			dir |= DIR_if;
525da2e3ebdSchin 			break;
526da2e3ebdSchin 		case 'l':
527da2e3ebdSchin 			dir |= DIR_el;
528da2e3ebdSchin 			break;
529da2e3ebdSchin 		case 'n':
530da2e3ebdSchin 			dir |= DIR_en;
531da2e3ebdSchin 			break;
532da2e3ebdSchin 		}
533da2e3ebdSchin 		break;
534da2e3ebdSchin 	}
535da2e3ebdSchin 	return dir;
536da2e3ebdSchin }
537da2e3ebdSchin 
538da2e3ebdSchin /*
539da2e3ebdSchin  * the tokenizer
540da2e3ebdSchin  * top level calls loop until EOB
541da2e3ebdSchin  * recursive calls just return the next token
542da2e3ebdSchin  */
543da2e3ebdSchin 
544da2e3ebdSchin static int
lex(register struct proto * proto,register long flags)545da2e3ebdSchin lex(register struct proto* proto, register long flags)
546da2e3ebdSchin {
547da2e3ebdSchin 	register char*		ip;
548da2e3ebdSchin 	register char*		op;
549da2e3ebdSchin 	register int		c;
550da2e3ebdSchin 	register int		state;
551da2e3ebdSchin 	register short*		rp;
552da2e3ebdSchin 	char*			m;
553da2e3ebdSchin 	char*			e;
554da2e3ebdSchin 	char*			t;
555da2e3ebdSchin 	char*			bp;
556da2e3ebdSchin 	char*			v;
557da2e3ebdSchin 	char*			im;
558da2e3ebdSchin 	char*			ko;
559da2e3ebdSchin 	char*			aom;
560da2e3ebdSchin 	int			n;
561da2e3ebdSchin 	int			line;
562da2e3ebdSchin 	int			quot;
563da2e3ebdSchin 	int			brack;
564da2e3ebdSchin 	int			sub;
565da2e3ebdSchin 	int			x;
566da2e3ebdSchin 	int			vc;
567da2e3ebdSchin 
568da2e3ebdSchin 	char*			ie = 0;
569da2e3ebdSchin 	char*			om = 0;
570da2e3ebdSchin 	char*			aim = 0;
571da2e3ebdSchin 	char*			aie = 0;
572da2e3ebdSchin 	char*			func = 0;
573da2e3ebdSchin 	int			call = 0;
574da2e3ebdSchin 	int			dir = 0;
575da2e3ebdSchin 	int			group = 0;
576da2e3ebdSchin 	int			last = 0;
577da2e3ebdSchin 	int			paren = 0;
578da2e3ebdSchin #if PROTOMAIN
579da2e3ebdSchin 	char*			qe = 0;
580da2e3ebdSchin 	int			qn = 0;
581da2e3ebdSchin 	int			args = 0;
582da2e3ebdSchin #endif
583da2e3ebdSchin 
584da2e3ebdSchin 	CACHE();
585da2e3ebdSchin #if PROTOMAIN
586da2e3ebdSchin 	if (flags & EXTERN) KEEPOUT();
587da2e3ebdSchin #endif
588da2e3ebdSchin  fsm_start:
589da2e3ebdSchin 	proto->tp = ip;
590da2e3ebdSchin 	state = PROTO;
591da2e3ebdSchin 	bp = ip;
592da2e3ebdSchin 	do
593da2e3ebdSchin 	{
594da2e3ebdSchin 		rp = fsm[state];
595da2e3ebdSchin  fsm_get:
596da2e3ebdSchin 		while (!(state = rp[c = GETCHR()]));
597da2e3ebdSchin  fsm_next:
598da2e3ebdSchin 		;
599da2e3ebdSchin 	} while (state > 0);
600da2e3ebdSchin 	if ((n = ip - bp - 1) > 0)
601da2e3ebdSchin 	{
602da2e3ebdSchin 		ip = bp;
603da2e3ebdSchin 		MEMCPY(op, ip, n);
604da2e3ebdSchin 		ip++;
605da2e3ebdSchin 	}
606da2e3ebdSchin 	state = ~state;
607da2e3ebdSchin  fsm_terminal:
608da2e3ebdSchin 	switch (TERM(state))
609da2e3ebdSchin 	{
610da2e3ebdSchin 	case S_CHR:
611da2e3ebdSchin 		if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
612da2e3ebdSchin 		{
613da2e3ebdSchin 		case '+':
614da2e3ebdSchin 		case '-':
615da2e3ebdSchin 		case '*':
616da2e3ebdSchin 		case '&':
617da2e3ebdSchin 			PUTCHR(' ');
618da2e3ebdSchin 			break;
619da2e3ebdSchin 		}
620da2e3ebdSchin 		PUTCHR(c);
621da2e3ebdSchin 		break;
622da2e3ebdSchin 
623da2e3ebdSchin 	case S_CHRB:
624da2e3ebdSchin 		UNGETCHR();
625da2e3ebdSchin 		c = LASTOUT();
626da2e3ebdSchin 		break;
627da2e3ebdSchin 
628da2e3ebdSchin 	case S_COMMENT:
629da2e3ebdSchin 		switch (c)
630da2e3ebdSchin 		{
631da2e3ebdSchin 		case '\n':
632da2e3ebdSchin 			if (INCOMMENTXX(rp)) goto fsm_newline;
633da2e3ebdSchin 			PUTCHR(c);
634da2e3ebdSchin 			proto->line++;
635da2e3ebdSchin 			rp = fsm[COM2];
636da2e3ebdSchin 			break;
637da2e3ebdSchin 		case '/':
638da2e3ebdSchin #if PROTOMAIN
639da2e3ebdSchin 			if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
640da2e3ebdSchin 			else
641da2e3ebdSchin #endif
642da2e3ebdSchin 			PUTCHR(c);
643da2e3ebdSchin 			if (INCOMMENTXX(rp))
644da2e3ebdSchin 			{
645da2e3ebdSchin 				rp = fsm[COM5];
646da2e3ebdSchin 				break;
647da2e3ebdSchin 			}
648da2e3ebdSchin 			goto fsm_start;
649da2e3ebdSchin 		case EOF:
650da2e3ebdSchin 			break;
651da2e3ebdSchin 		default:
652da2e3ebdSchin #if PROTOMAIN
653da2e3ebdSchin 			if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
654da2e3ebdSchin 			else
655da2e3ebdSchin #endif
656da2e3ebdSchin 			PUTCHR(c);
657da2e3ebdSchin 			rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
658da2e3ebdSchin 			break;
659da2e3ebdSchin 		}
660da2e3ebdSchin 		bp = ip;
661da2e3ebdSchin 		goto fsm_get;
662da2e3ebdSchin 
663da2e3ebdSchin 	case S_EOB:
664da2e3ebdSchin 		if (c)
665da2e3ebdSchin 		{
666da2e3ebdSchin 			if (state = fsm[TERMINAL][INDEX(rp)+1])
667da2e3ebdSchin 				goto fsm_terminal;
668da2e3ebdSchin 			SYNC();
669da2e3ebdSchin 			return 0;
670da2e3ebdSchin 		}
671da2e3ebdSchin 		UNGETCHR();
672da2e3ebdSchin  fsm_eob:
673da2e3ebdSchin 		if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE))
674da2e3ebdSchin 		{
675da2e3ebdSchin #if PROTOMAIN
676da2e3ebdSchin 			if (!(flags & EXTERN)) /* XXX */
677da2e3ebdSchin #endif
678da2e3ebdSchin 			flags |= SLIDE;
679da2e3ebdSchin 			c = ip - proto->ib;
680da2e3ebdSchin 			if (!(flags & MATCH))
681da2e3ebdSchin 				im = proto->tp;
682da2e3ebdSchin 			if (ip > proto->ib)
683da2e3ebdSchin 			{
684da2e3ebdSchin 				n = ip - im;
685da2e3ebdSchin 				if (ip - n < proto->ib)
686da2e3ebdSchin 					proto->flags |= ERROR;
687da2e3ebdSchin 				memcopy(proto->ib - n, ip - n, n);
688da2e3ebdSchin 				ip = proto->ib;
689da2e3ebdSchin 			}
690da2e3ebdSchin 			proto->tp -= c;
691da2e3ebdSchin 			if (flags & MATCH)
692da2e3ebdSchin 			{
693da2e3ebdSchin 				im -= c;
694da2e3ebdSchin 				ie -= c;
695da2e3ebdSchin 			}
696da2e3ebdSchin 			if (aim)
697da2e3ebdSchin 				aim -= c;
698da2e3ebdSchin 			if (aie)
699da2e3ebdSchin 				aie -= c;
700da2e3ebdSchin 			if ((n = read(proto->fd, ip, proto->iz)) > 0)
701da2e3ebdSchin 			{
702da2e3ebdSchin 				if ((proto->options & REGULAR) && n < proto->iz)
703da2e3ebdSchin 				{
704da2e3ebdSchin 					proto->flags &= ~MORE;
705da2e3ebdSchin 					close(proto->fd);
706da2e3ebdSchin 				}
707da2e3ebdSchin 				*(ip + n) = 0;
708da2e3ebdSchin 				if (state & SPLICE)
709da2e3ebdSchin 					goto fsm_splice;
710da2e3ebdSchin 				bp = ip;
711da2e3ebdSchin 				goto fsm_get;
712da2e3ebdSchin 			}
713da2e3ebdSchin 			*ip = 0;
714da2e3ebdSchin 			proto->flags &= ~MORE;
715da2e3ebdSchin 			close(proto->fd);
716da2e3ebdSchin 		}
717da2e3ebdSchin 		if (state & SPLICE)
718da2e3ebdSchin 			goto fsm_splice;
719da2e3ebdSchin 		/* NOTE: RECURSIVE lex() should really SLIDE too */
720da2e3ebdSchin 		if (!(flags & RECURSIVE) && (state = rp[c = EOF]))
721da2e3ebdSchin 		{
722da2e3ebdSchin 			bp = ip;
723da2e3ebdSchin 			goto fsm_next;
724da2e3ebdSchin 		}
725da2e3ebdSchin 		SYNC();
726da2e3ebdSchin 		return 0;
727da2e3ebdSchin 
728da2e3ebdSchin 	case S_LITBEG:
729da2e3ebdSchin 		quot = c;
730da2e3ebdSchin #if PROTOMAIN
731da2e3ebdSchin 		if (c == '"' && qe)
732da2e3ebdSchin 		{
733da2e3ebdSchin 			for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
734da2e3ebdSchin 			if (t == op)
735da2e3ebdSchin 			{
736da2e3ebdSchin 				op = qe;
737da2e3ebdSchin 				qe = 0;
738da2e3ebdSchin 				qn = n;
739da2e3ebdSchin 			}
740da2e3ebdSchin 			else PUTCHR(c);
741da2e3ebdSchin 		}
742da2e3ebdSchin 		else
743da2e3ebdSchin #endif
744da2e3ebdSchin 		PUTCHR(c);
745da2e3ebdSchin 		rp = fsm[LIT1];
746da2e3ebdSchin 		bp = ip;
747da2e3ebdSchin 		goto fsm_get;
748da2e3ebdSchin 
749da2e3ebdSchin 	case S_LITEND:
750da2e3ebdSchin 		if (c == quot)
751da2e3ebdSchin 		{
752da2e3ebdSchin #if PROTOMAIN
753da2e3ebdSchin 			if (!(flags & DIRECTIVE))
754da2e3ebdSchin 				qe = (c == '"') ? op : (char*)0;
755da2e3ebdSchin #endif
756da2e3ebdSchin 			PUTCHR(c);
757da2e3ebdSchin #if PROTOMAIN
758da2e3ebdSchin 			while (qn > 0)
759da2e3ebdSchin 			{
760da2e3ebdSchin 				qn--;
761da2e3ebdSchin 				PUTCHR('\n');
762da2e3ebdSchin 			}
763da2e3ebdSchin #endif
764da2e3ebdSchin 		}
765da2e3ebdSchin 		else if (c != '\n' && c != EOF)
766da2e3ebdSchin 		{
767da2e3ebdSchin 			PUTCHR(c);
768da2e3ebdSchin 			bp = ip;
769da2e3ebdSchin 			goto fsm_get;
770da2e3ebdSchin 		}
771da2e3ebdSchin 		else
772da2e3ebdSchin 		{
773da2e3ebdSchin #if PROTOMAIN
774da2e3ebdSchin 			while (qn > 0)
775da2e3ebdSchin 			{
776da2e3ebdSchin 				qn--;
777da2e3ebdSchin 				PUTCHR('\n');
778da2e3ebdSchin 			}
779da2e3ebdSchin #endif
780da2e3ebdSchin 			UNGETCHR();
781da2e3ebdSchin 		}
782da2e3ebdSchin 		c = T_INVALID;
783da2e3ebdSchin 		break;
784da2e3ebdSchin 
785da2e3ebdSchin 	case S_LITESC:
786da2e3ebdSchin #if PROTOMAIN
787da2e3ebdSchin 		if (flags & CLASSIC) PUTCHR(c);
788da2e3ebdSchin 		else
789da2e3ebdSchin #endif
790da2e3ebdSchin 		switch (c)
791da2e3ebdSchin 		{
792da2e3ebdSchin 		case 'a':
793da2e3ebdSchin 			n = CC_bel;
794da2e3ebdSchin 			goto fsm_oct;
795da2e3ebdSchin 		case 'E':
796da2e3ebdSchin 			n = CC_esc;
797da2e3ebdSchin 			goto fsm_oct;
798da2e3ebdSchin 		case 'v':
799da2e3ebdSchin 			n = CC_vt;
800da2e3ebdSchin 			goto fsm_oct;
801da2e3ebdSchin 		case 'x':
802da2e3ebdSchin 			SYNC();
803da2e3ebdSchin 			lex(proto, (flags & GLOBAL) | RECURSIVE);
804da2e3ebdSchin 			for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c)
805da2e3ebdSchin 			{
806da2e3ebdSchin 			case '0': case '1': case '2': case '3':
807da2e3ebdSchin 			case '4': case '5': case '6': case '7':
808da2e3ebdSchin 			case '8': case '9':
809da2e3ebdSchin 				n = (n << 4) + c - '0';
810da2e3ebdSchin 				break;
811da2e3ebdSchin 			case 'a': case 'b': case 'c': case 'd':
812da2e3ebdSchin 			case 'e': case 'f':
813da2e3ebdSchin 				n = (n << 4) + c - 'a' + 10;
814da2e3ebdSchin 				break;
815da2e3ebdSchin 			case 'A': case 'B': case 'C': case 'D':
816da2e3ebdSchin 			case 'E': case 'F':
817da2e3ebdSchin 				n = (n << 4) + c - 'A' + 10;
818da2e3ebdSchin 				break;
819da2e3ebdSchin 			default:
820da2e3ebdSchin 				goto fsm_hex;
821da2e3ebdSchin 			}
822da2e3ebdSchin  fsm_hex:
823da2e3ebdSchin 			UNGETCHR();
824da2e3ebdSchin  fsm_oct:
825da2e3ebdSchin 			PUTCHR(((n >> 6) & 07) + '0');
826da2e3ebdSchin 			PUTCHR(((n >> 3) & 07) + '0');
827da2e3ebdSchin 			PUTCHR((n & 07) + '0');
828da2e3ebdSchin 			break;
829da2e3ebdSchin 		default:
830da2e3ebdSchin 			PUTCHR(c);
831da2e3ebdSchin 			break;
832da2e3ebdSchin 		}
833da2e3ebdSchin 		rp = fsm[LIT1];
834da2e3ebdSchin 		bp = ip;
835da2e3ebdSchin 		goto fsm_get;
836da2e3ebdSchin 
837da2e3ebdSchin 	case S_MACRO:
838da2e3ebdSchin 		UNGETCHR();
839da2e3ebdSchin #if PROTOMAIN
840da2e3ebdSchin 		if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6))
841da2e3ebdSchin 		{
842da2e3ebdSchin 			c = T_EXTERN;
843da2e3ebdSchin 			break;
844da2e3ebdSchin 		}
845da2e3ebdSchin #endif
846da2e3ebdSchin 		if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#';
847da2e3ebdSchin 		else c = T_ID;
848da2e3ebdSchin 
849da2e3ebdSchin 		break;
850da2e3ebdSchin 
851da2e3ebdSchin 	case S_NL:
852da2e3ebdSchin  fsm_newline:
853da2e3ebdSchin 		proto->line++;
854da2e3ebdSchin #if PROTOMAIN
855da2e3ebdSchin 		if (flags & EXTERN)
856da2e3ebdSchin 		{
857da2e3ebdSchin 			if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n')
858da2e3ebdSchin 				PUTCHR(' ');
859da2e3ebdSchin 		}
860da2e3ebdSchin 		else
861da2e3ebdSchin #endif
862da2e3ebdSchin 		PUTCHR(c);
863da2e3ebdSchin 		if (flags & DIRECTIVE)
864da2e3ebdSchin 		{
865da2e3ebdSchin #if PROTOMAIN
866da2e3ebdSchin 			if (flags & CLASSIC)
867da2e3ebdSchin 			{
868da2e3ebdSchin 				if (flags & EXTERN) BACKOUT();
869da2e3ebdSchin 				if (flags & JUNK)
870da2e3ebdSchin 				{
871da2e3ebdSchin 					*(ip - 1) = 0;
872da2e3ebdSchin 					op = strcopy(om, "/* ");
873da2e3ebdSchin 					op = strcopy(op, im);
874da2e3ebdSchin 					op = strcopy(op, " */\n");
875da2e3ebdSchin 				}
876da2e3ebdSchin 				flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF);
877da2e3ebdSchin 			}
878da2e3ebdSchin 			else
879da2e3ebdSchin #endif
880da2e3ebdSchin 			{
881da2e3ebdSchin 				if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP))
882da2e3ebdSchin 				{
883da2e3ebdSchin 					*(ip - 1) = 0;
884da2e3ebdSchin 					op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
885da2e3ebdSchin 					op = strcopy(op, im);
886da2e3ebdSchin 					op = strcopy(op, "\n#else\n");
887da2e3ebdSchin 					bp = ip;
888da2e3ebdSchin 					ip = im;
889da2e3ebdSchin 					*op++ = *ip++;
890da2e3ebdSchin 					while (*op = *ip++)
891da2e3ebdSchin 						if (*op++ == '#' && *ip != '(')
892da2e3ebdSchin 						{
893da2e3ebdSchin 							op--;
894da2e3ebdSchin 							while (*--op == ' ' || *op == '\t');
895da2e3ebdSchin 							if (*ip == '#')
896da2e3ebdSchin 							{
897da2e3ebdSchin 								op = strcopy(op + 1, "/**/");
898da2e3ebdSchin 								while (*++ip == ' ' || *ip == '\t');
899da2e3ebdSchin 							}
900da2e3ebdSchin 							else
901da2e3ebdSchin 							{
902da2e3ebdSchin 								if (*op != '"') *++op = '"';
903da2e3ebdSchin 								op++;
904da2e3ebdSchin 								while (*ip == ' ' || *ip == '\t') ip++;
905da2e3ebdSchin 								while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
906da2e3ebdSchin 								while (*ip == ' ' || *ip == '\t') ip++;
907da2e3ebdSchin 								if (*ip == '"') ip++;
908da2e3ebdSchin 								else *op++ = '"';
909da2e3ebdSchin 							}
910da2e3ebdSchin 						}
911da2e3ebdSchin 					ip = bp;
912da2e3ebdSchin 					op = strcopy(op, "\n#endif\n");
913da2e3ebdSchin 					op = linesync(proto, op, proto->line);
914da2e3ebdSchin 				}
915da2e3ebdSchin 				flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF);
916da2e3ebdSchin 			}
917da2e3ebdSchin 			call = 0;
918da2e3ebdSchin 			group = 0;
919da2e3ebdSchin 			paren = 0;
920da2e3ebdSchin 			last = '\n';
921da2e3ebdSchin 		}
922da2e3ebdSchin 		if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE)
923da2e3ebdSchin 		{
924da2e3ebdSchin #if PROTOMAIN
925da2e3ebdSchin 			if (flags & EXTERN) BACKOUT();
926da2e3ebdSchin #endif
927da2e3ebdSchin 			SYNC();
928da2e3ebdSchin 			return 0;
929da2e3ebdSchin 		}
930da2e3ebdSchin 		goto fsm_start;
931da2e3ebdSchin 
932da2e3ebdSchin 	case S_QUAL:
933da2e3ebdSchin 		PUTCHR(c);
934da2e3ebdSchin 		rp = fsm[NEXT(state)];
935da2e3ebdSchin 		bp = ip;
936da2e3ebdSchin 		goto fsm_get;
937da2e3ebdSchin 
938da2e3ebdSchin 	case S_TOK:
939da2e3ebdSchin 		PUTCHR(c);
940da2e3ebdSchin 		c = TYPE(state);
941da2e3ebdSchin 		break;
942da2e3ebdSchin 
943da2e3ebdSchin 	case S_TOKB:
944da2e3ebdSchin 		UNGETCHR();
945da2e3ebdSchin 		c = TYPE(state);
946da2e3ebdSchin 		break;
947da2e3ebdSchin 
948da2e3ebdSchin 	case S_RESERVED:
949da2e3ebdSchin 		UNGETCHR();
950da2e3ebdSchin 		c = T_ID;
951da2e3ebdSchin 		if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp))
952da2e3ebdSchin 		{
953da2e3ebdSchin 		case RESERVED('N', 'N', 3):
954da2e3ebdSchin 			if (proto->tp[1] == 'o')
955da2e3ebdSchin 				c = T_DO;
956da2e3ebdSchin 			break;
957da2e3ebdSchin 		case RESERVED('d', 'o', 2):
958da2e3ebdSchin 			c = T_DO;
959da2e3ebdSchin 			break;
960da2e3ebdSchin 		case RESERVED('e', 'e', 4):
961da2e3ebdSchin 			if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4))
962da2e3ebdSchin 			{
963da2e3ebdSchin 				c = T_ELSE;
964da2e3ebdSchin 				goto fsm_id;
965da2e3ebdSchin 			}
966da2e3ebdSchin 			break;
967da2e3ebdSchin 		case RESERVED('e', 'n', 6):
968da2e3ebdSchin 			if (!strncmp(proto->tp, "extern", 6))
969da2e3ebdSchin 				c = T_EXTERN;
970da2e3ebdSchin 			break;
971da2e3ebdSchin 		case RESERVED('f', 'r', 3):
972da2e3ebdSchin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3))
973da2e3ebdSchin 			{
974da2e3ebdSchin 				c = T_FOR;
975da2e3ebdSchin 				goto fsm_id;
976da2e3ebdSchin 			}
977da2e3ebdSchin 			break;
978da2e3ebdSchin 		case RESERVED('i', 'f', 2):
979da2e3ebdSchin 			c = T_IF;
980da2e3ebdSchin 			break;
981da2e3ebdSchin 		case RESERVED('i', 'e', 6):
982da2e3ebdSchin 			if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
983da2e3ebdSchin 			{
984da2e3ebdSchin 				flags |= SKIP;
985da2e3ebdSchin 				SYNC();
986da2e3ebdSchin 				line = proto->line;
987da2e3ebdSchin 				op = strcopy(op - 6, "__INLINE__");
988da2e3ebdSchin 				SYNC();
989da2e3ebdSchin 			}
990da2e3ebdSchin 			break;
991da2e3ebdSchin 		case RESERVED('r', 'n', 6):
992da2e3ebdSchin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6))
993da2e3ebdSchin 			{
994da2e3ebdSchin 				c = T_RETURN;
995da2e3ebdSchin 				goto fsm_id;
996da2e3ebdSchin 			}
997da2e3ebdSchin 			break;
998da2e3ebdSchin 		case RESERVED('s', 'c', 6):
999da2e3ebdSchin 			if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6))
1000da2e3ebdSchin 			{
1001da2e3ebdSchin 				proto->ox = op - 6;
1002da2e3ebdSchin 				flags |= EXTERNALIZE;
1003da2e3ebdSchin 			}
1004da2e3ebdSchin 			break;
1005da2e3ebdSchin 		case RESERVED('t', 'f', 7):
1006da2e3ebdSchin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7))
1007da2e3ebdSchin 			{
1008da2e3ebdSchin 				flags |= TYPEDEF;
1009da2e3ebdSchin 				c = T_EXTERN;
1010da2e3ebdSchin 			}
1011da2e3ebdSchin 			break;
1012da2e3ebdSchin 		case RESERVED('v', 't', 8):
1013da2e3ebdSchin 			if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START;
1014da2e3ebdSchin 			break;
1015da2e3ebdSchin 		case RESERVED('v', 'd', 4):
1016da2e3ebdSchin 			if (!strncmp(proto->tp, "void", 4))
1017da2e3ebdSchin 			{
1018da2e3ebdSchin 				if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID;
1019da2e3ebdSchin 				else
1020da2e3ebdSchin 				{
1021da2e3ebdSchin 					SYNC();
1022da2e3ebdSchin 					line = proto->line;
1023da2e3ebdSchin 					if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*')
1024da2e3ebdSchin 					{
1025da2e3ebdSchin 						memcopy(op - 4, "__V_", 4);
1026da2e3ebdSchin 						memcopy(ip - 4, "__V_", 4);
1027da2e3ebdSchin 					}
1028da2e3ebdSchin 					else c = T_VOID;
1029da2e3ebdSchin 					proto->line = line;
1030da2e3ebdSchin 					SYNC();
1031da2e3ebdSchin 					bp = ip;
1032da2e3ebdSchin 				}
1033da2e3ebdSchin 			}
1034da2e3ebdSchin 			break;
1035da2e3ebdSchin 		case RESERVED('w', 'e', 5):
1036da2e3ebdSchin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5))
1037da2e3ebdSchin 			{
1038da2e3ebdSchin 				c = T_WHILE;
1039da2e3ebdSchin 				goto fsm_id;
1040da2e3ebdSchin 			}
1041da2e3ebdSchin 			break;
1042da2e3ebdSchin 		}
1043da2e3ebdSchin #if PROTOMAIN
1044da2e3ebdSchin 		if ((flags & CLASSIC) && c != T_EXTERN)
1045da2e3ebdSchin 			c = T_ID;
1046da2e3ebdSchin #endif
1047da2e3ebdSchin 		break;
1048da2e3ebdSchin 
1049da2e3ebdSchin 	case S_VS:
1050da2e3ebdSchin 		goto fsm_start;
1051da2e3ebdSchin 
1052da2e3ebdSchin 	case S_WS:
1053da2e3ebdSchin 		UNGETCHR();
1054da2e3ebdSchin #if PROTOMAIN
1055da2e3ebdSchin 		if ((flags & (EXTERN|MATCH)) == EXTERN)
1056da2e3ebdSchin 		{
1057da2e3ebdSchin 			while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
1058da2e3ebdSchin 				op--;
1059da2e3ebdSchin 			if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
1060da2e3ebdSchin 		}
1061da2e3ebdSchin #endif
1062da2e3ebdSchin 		goto fsm_start;
1063da2e3ebdSchin 
1064da2e3ebdSchin 	default:
1065da2e3ebdSchin 		if (state & SPLICE)
1066da2e3ebdSchin 		{
1067da2e3ebdSchin 			if (c == '\\')
1068da2e3ebdSchin 			{
1069da2e3ebdSchin 				if (!(n = GETCHR()))
1070da2e3ebdSchin 				{
1071da2e3ebdSchin 					goto fsm_eob;
1072da2e3ebdSchin  fsm_splice:
1073da2e3ebdSchin 					c = '\\';
1074da2e3ebdSchin 					n = GETCHR();
1075da2e3ebdSchin 				}
1076da2e3ebdSchin 				if (n == '\n')
1077da2e3ebdSchin 				{
1078da2e3ebdSchin 					proto->line++;
1079da2e3ebdSchin 					PUTCHR('\\');
1080da2e3ebdSchin 					PUTCHR('\n');
1081da2e3ebdSchin 					bp = ip;
1082da2e3ebdSchin 					goto fsm_get;
1083da2e3ebdSchin 				}
1084da2e3ebdSchin 				UNGETCHR();
1085da2e3ebdSchin 			}
1086da2e3ebdSchin 			state &= ~SPLICE;
1087da2e3ebdSchin 			if (state >= TERMINAL)
1088da2e3ebdSchin 				goto fsm_terminal;
1089da2e3ebdSchin 			rp = fsm[state];
1090da2e3ebdSchin 		}
1091da2e3ebdSchin 		PUTCHR(c);
1092da2e3ebdSchin 		bp = ip;
1093da2e3ebdSchin 		goto fsm_get;
1094da2e3ebdSchin 	}
1095da2e3ebdSchin 	if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE)))
1096da2e3ebdSchin 	{
1097da2e3ebdSchin 		if (!(flags & DIRECTIVE)) switch (c)
1098da2e3ebdSchin 		{
1099da2e3ebdSchin 		case '(':
1100da2e3ebdSchin #if PROTOMAIN
1101da2e3ebdSchin 			if (!(flags & CLASSIC) || proto->brace == 0)
1102da2e3ebdSchin #endif
1103da2e3ebdSchin 			{
1104da2e3ebdSchin 				if (paren++ == 0)
1105da2e3ebdSchin 				{
1106da2e3ebdSchin #if PROTOMAIN
1107da2e3ebdSchin 					if (!(flags & CLASSIC) || group <= 1)
1108da2e3ebdSchin #endif
1109da2e3ebdSchin 					{
1110da2e3ebdSchin #if PROTOMAIN
1111da2e3ebdSchin 						args = 0;
1112da2e3ebdSchin #endif
1113da2e3ebdSchin 						if (group++ == 0) group++;
1114da2e3ebdSchin 						else if (flags & INDIRECT) call++;
1115da2e3ebdSchin 						flags |= MATCH;
1116da2e3ebdSchin 						im = ip - 1;
1117da2e3ebdSchin 						om = op - 1;
1118da2e3ebdSchin 					}
1119da2e3ebdSchin 					sub = 0;
1120da2e3ebdSchin 				}
1121da2e3ebdSchin 				else if (paren == 2 && !aim)
1122da2e3ebdSchin 				{
1123da2e3ebdSchin 					sub++;
1124da2e3ebdSchin 					if (last == '(')
1125da2e3ebdSchin 					{
1126da2e3ebdSchin 						flags &= ~MATCH;
1127da2e3ebdSchin 						om = 0;
1128da2e3ebdSchin 					}
1129da2e3ebdSchin 					else if (flags & INDIRECT)
1130da2e3ebdSchin 					{
1131da2e3ebdSchin 						aim = ip - 1;
1132da2e3ebdSchin 						aom = op - 1;
1133da2e3ebdSchin 					}
1134da2e3ebdSchin 					else if ((flags & (MATCH|TOKENS)) == MATCH)
1135da2e3ebdSchin 					{
1136da2e3ebdSchin 						for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
1137da2e3ebdSchin 						if (m != im && sub == 1)
1138da2e3ebdSchin 						{
1139da2e3ebdSchin 							m = im + (*nns(ip) == '*');
1140da2e3ebdSchin 						}
1141da2e3ebdSchin 						if (m == im)
1142da2e3ebdSchin 						{
1143da2e3ebdSchin 							flags &= ~MATCH;
1144da2e3ebdSchin 							om = 0;
1145da2e3ebdSchin 						}
1146da2e3ebdSchin 					}
1147da2e3ebdSchin 					else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*')
1148da2e3ebdSchin 					{
1149da2e3ebdSchin 						flags &= ~MATCH;
1150da2e3ebdSchin 						om = 0;
1151da2e3ebdSchin 					}
1152da2e3ebdSchin 				}
1153da2e3ebdSchin 				flags &= ~TOKENS;
1154da2e3ebdSchin 			}
1155da2e3ebdSchin 			break;
1156da2e3ebdSchin 		case ')':
1157da2e3ebdSchin #if PROTOMAIN
1158da2e3ebdSchin 			if (!(flags & CLASSIC) || proto->brace == 0)
1159da2e3ebdSchin #endif
1160da2e3ebdSchin 			if (--paren == 0)
1161da2e3ebdSchin 			{
1162da2e3ebdSchin #if PROTOMAIN
1163da2e3ebdSchin 				if (flags & CLASSIC)
1164da2e3ebdSchin 				{
1165da2e3ebdSchin 					if (group != 2)
1166da2e3ebdSchin 					{
1167da2e3ebdSchin 						c = T_ID;
1168da2e3ebdSchin 						break;
1169da2e3ebdSchin 					}
1170da2e3ebdSchin 					group++;
1171da2e3ebdSchin 				}
1172da2e3ebdSchin #endif
1173da2e3ebdSchin 				ie = ip;
1174da2e3ebdSchin 			}
1175da2e3ebdSchin 			else if (paren == 1 && (flags & INDIRECT) && !aie)
1176da2e3ebdSchin 				aie = ip;
1177da2e3ebdSchin 			break;
1178da2e3ebdSchin 		case '*':
1179da2e3ebdSchin 			if (last == '(' && group == 2)
1180da2e3ebdSchin 			{
1181da2e3ebdSchin 				group--;
1182da2e3ebdSchin 				if (paren == 1)
1183da2e3ebdSchin 				{
1184da2e3ebdSchin 					flags |= INDIRECT;
1185da2e3ebdSchin 					aim = aie = 0;
1186da2e3ebdSchin 				}
1187da2e3ebdSchin 			}
1188da2e3ebdSchin 			break;
1189da2e3ebdSchin 		case '#':
1190da2e3ebdSchin 			dir = directive(ip, dir);
1191da2e3ebdSchin 			if (proto->brace == 0 && paren == 0 && last != '=' && (flags & (CLASSIC|DECLARE|DIRECTIVE|MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS) && ((dir & DIR) != DIR_en || ((dir>>2) & DIR) != DIR_if))
1192da2e3ebdSchin 				flags |= DIRECTIVE;
1193da2e3ebdSchin 			else if (!(flags & (DECLARE|DIRECTIVE)))
1194da2e3ebdSchin 			{
1195da2e3ebdSchin 				flags |= DIRECTIVE;
1196da2e3ebdSchin 				if (!(flags & PLUSONLY))
1197da2e3ebdSchin 				{
1198da2e3ebdSchin 					bp = ip;
1199da2e3ebdSchin 					while (*ip == ' ' || *ip == '\t') ip++;
1200da2e3ebdSchin 					if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
1201da2e3ebdSchin 					{
1202da2e3ebdSchin 						if (*++ip == ' ' || *ip == '\t')
1203da2e3ebdSchin 						{
1204da2e3ebdSchin 							proto->line = 0;
1205da2e3ebdSchin 							while (*++ip >= '0' && *ip <= '9')
1206da2e3ebdSchin 								proto->line = proto->line * 10 + *ip - '0';
1207da2e3ebdSchin 							proto->line--;
1208da2e3ebdSchin 						}
1209da2e3ebdSchin 					}
1210da2e3ebdSchin #if PROTOMAIN
1211da2e3ebdSchin 					else if ((flags & (CLASSIC|EXTERN)) == CLASSIC)
1212da2e3ebdSchin 					{
1213da2e3ebdSchin 						n = 0;
1214da2e3ebdSchin 						t = ip + 6;
1215da2e3ebdSchin 						while (ip < t && *ip >= 'a' && *ip <= 'z')
1216da2e3ebdSchin 							n = HASHKEYPART(n, *ip++);
1217da2e3ebdSchin 						switch (n)
1218da2e3ebdSchin 						{
1219da2e3ebdSchin 						case HASHKEY4('e','l','s','e'):
1220da2e3ebdSchin 						case HASHKEY5('e','n','d','i','f'):
1221da2e3ebdSchin 							while (*ip == ' ' || *ip == '\t') ip++;
1222da2e3ebdSchin 							if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
1223da2e3ebdSchin 							{
1224da2e3ebdSchin 								flags |= JUNK|MATCH;
1225da2e3ebdSchin 								im = ip;
1226da2e3ebdSchin 								om = op + (ip - bp);
1227da2e3ebdSchin 							}
1228da2e3ebdSchin 							break;
1229da2e3ebdSchin 						case HASHKEY4('e','l','i','f'):
1230da2e3ebdSchin 						case HASHKEY5('e','r','r','o','r'):
1231da2e3ebdSchin 						case HASHKEY2('i','f'):
1232da2e3ebdSchin 						case HASHKEY5('i','f','d','e','f'):
1233da2e3ebdSchin 						case HASHKEY6('i','f','n','d','e','f'):
1234da2e3ebdSchin 						case HASHKEY5('u','n','d','e','f'):
1235da2e3ebdSchin 							break;
1236da2e3ebdSchin 						case HASHKEY6('i','n','c','l','u','d'):
1237da2e3ebdSchin 							if (*ip == 'e') ip++;
1238da2e3ebdSchin 							/*FALLTHROUGH*/
1239da2e3ebdSchin 						case HASHKEY6('d','e','f','i','n','e'):
1240da2e3ebdSchin 						case HASHKEY6('p','r','a','g','m','a'):
1241da2e3ebdSchin 							if (*ip < 'a' || *ip > 'z') break;
1242da2e3ebdSchin 							/*FALLTHROUGH*/
1243da2e3ebdSchin 						default:
1244da2e3ebdSchin 							flags |= JUNK|MATCH;
1245da2e3ebdSchin 							im = bp - 1;
1246da2e3ebdSchin 							om = op - 1;
1247da2e3ebdSchin 							break;
1248da2e3ebdSchin 						}
1249da2e3ebdSchin 					}
1250da2e3ebdSchin 					else
1251da2e3ebdSchin #endif
1252da2e3ebdSchin 					{
1253da2e3ebdSchin 						if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
1254da2e3ebdSchin 						{
1255da2e3ebdSchin 							while (*++ip == ' ' || *ip == '\t');
1256da2e3ebdSchin 							if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
1257da2e3ebdSchin 							{
1258da2e3ebdSchin 								op = strcopy(op, "\
1259da2e3ebdSchin if !defined(va_start)\n\
1260da2e3ebdSchin #if defined(__STDARG__)\n\
1261da2e3ebdSchin #include <stdarg.h>\n\
1262da2e3ebdSchin #else\n\
1263da2e3ebdSchin #include <varargs.h>\n\
1264da2e3ebdSchin #endif\n\
1265da2e3ebdSchin #endif\n\
1266da2e3ebdSchin ");
1267da2e3ebdSchin 								op = linesync(proto, op, proto->line);
1268da2e3ebdSchin 								break;
1269da2e3ebdSchin 							}
1270da2e3ebdSchin 						}
1271da2e3ebdSchin 						else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
1272da2e3ebdSchin 						{
1273da2e3ebdSchin 							while (*++ip == ' ' || *ip == '\t');
1274da2e3ebdSchin 							if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
1275da2e3ebdSchin 							{
1276da2e3ebdSchin 								t = ip;
1277da2e3ebdSchin 								while (*++t == ' ' || *t == '\t');
1278da2e3ebdSchin 								if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
1279da2e3ebdSchin 									ip = t;
1280da2e3ebdSchin 								t = ip;
1281da2e3ebdSchin 								while (*++t == ' ' || *t == '\t');
1282da2e3ebdSchin 								if (*t == '_' && *(t + 1) == '_')
1283da2e3ebdSchin 								{
1284da2e3ebdSchin 									op = strcopy(op, "undef __MANGLE__\n");
1285da2e3ebdSchin 									op = linesync(proto, op, proto->line);
1286da2e3ebdSchin 									op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1287da2e3ebdSchin 									break;
1288da2e3ebdSchin 								}
1289da2e3ebdSchin 							}
1290da2e3ebdSchin 							flags |= DEFINE|MATCH;
1291da2e3ebdSchin 							im = bp - 1;
1292da2e3ebdSchin 							om = op - 1;
1293da2e3ebdSchin 						}
1294da2e3ebdSchin 						else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
1295da2e3ebdSchin 						{
1296da2e3ebdSchin 							while (*++ip == ' ' || *ip == '\t');
1297da2e3ebdSchin 							if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
1298da2e3ebdSchin 							{
1299da2e3ebdSchin 								op = strcopy(op, "undef __MANGLE__\n");
1300da2e3ebdSchin 								op = linesync(proto, op, proto->line);
1301da2e3ebdSchin 								op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1302da2e3ebdSchin 								break;
1303da2e3ebdSchin 							}
1304da2e3ebdSchin 							flags |= DEFINE|MATCH;
1305da2e3ebdSchin 							im = bp - 1;
1306da2e3ebdSchin 							om = op - 1;
1307da2e3ebdSchin 						}
1308da2e3ebdSchin 					}
1309da2e3ebdSchin 					ip = bp;
1310da2e3ebdSchin 				}
1311da2e3ebdSchin 				break;
1312da2e3ebdSchin 			}
1313da2e3ebdSchin 			else
1314da2e3ebdSchin 				break;
1315da2e3ebdSchin 			/*FALLTHROUGH*/
1316da2e3ebdSchin 		case '{':
1317da2e3ebdSchin 			if (proto->brace++ == 0 && paren == 0)
1318da2e3ebdSchin 			{
1319da2e3ebdSchin 				if (last == '=') flags |= INIT;
1320da2e3ebdSchin #if PROTOMAIN
1321da2e3ebdSchin 				else if (flags & CLASSIC)
1322da2e3ebdSchin 				{
1323da2e3ebdSchin 					if ((flags & (MATCH|OTHER|SKIP)) == MATCH)
1324da2e3ebdSchin 					{
1325da2e3ebdSchin 						if (args)
1326da2e3ebdSchin 						{
1327da2e3ebdSchin 							v = number(op, args < 0 ? -args : args);
1328da2e3ebdSchin 							v = strcopy(v, " argument actual/formal mismatch");
1329da2e3ebdSchin 							*v++ = ' ';
1330da2e3ebdSchin 							v = memcopy(v, im, ie - im);
1331da2e3ebdSchin 							*v = 0;
1332da2e3ebdSchin 							proto_error((char*)proto + sizeof(struct proto), 2, op, NiL);
1333da2e3ebdSchin 						}
1334da2e3ebdSchin 						ip--;
1335da2e3ebdSchin 						/*UNDENT...*/
1336da2e3ebdSchin 	v = ie;
1337da2e3ebdSchin 	while (ie < ip)
1338da2e3ebdSchin 		if (*ie++ == '/' && *ie == '*')
1339da2e3ebdSchin 		{
1340da2e3ebdSchin 			e = ie - 1;
1341da2e3ebdSchin 			while (++ie < ip)
1342da2e3ebdSchin 			{
1343da2e3ebdSchin 				if (*ie == '*')
1344da2e3ebdSchin 				{
1345da2e3ebdSchin 					while (ie < ip && *ie == '*') ie++;
1346da2e3ebdSchin 					if (ie < ip && *ie == '/')
1347da2e3ebdSchin 					{
1348da2e3ebdSchin 						while (++ie < ip && (*ie == ' ' || *ie == '\t'));
1349da2e3ebdSchin 						while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
1350da2e3ebdSchin 						if (e > v && *e != '\n') *e++ = ' ';
1351da2e3ebdSchin 						t = ie;
1352da2e3ebdSchin 						while (--e >= v)
1353da2e3ebdSchin 							*--t = *e;
1354da2e3ebdSchin 						v = t;
1355da2e3ebdSchin 						break;
1356da2e3ebdSchin 					}
1357da2e3ebdSchin 				}
1358da2e3ebdSchin 			}
1359da2e3ebdSchin 		}
1360da2e3ebdSchin 	ie = v;
1361da2e3ebdSchin 						/*...INDENT*/
1362da2e3ebdSchin 						op = om++;
1363da2e3ebdSchin 						if (flags & EXTERN)
1364da2e3ebdSchin 						{
1365da2e3ebdSchin 							v = op;
1366da2e3ebdSchin 							while (v > ko && *--v != ' ');
1367da2e3ebdSchin 							if (*v != ' ')
1368da2e3ebdSchin 							{
1369da2e3ebdSchin 								om = (v = (op += 4)) + 1;
1370da2e3ebdSchin 								while (v >= ko + 4)
1371da2e3ebdSchin 								{
1372da2e3ebdSchin 									*v = *(v - 4);
1373da2e3ebdSchin 									v--;
1374da2e3ebdSchin 								}
1375da2e3ebdSchin 								memcopy(ko, "int ", 4);
1376da2e3ebdSchin 							}
1377da2e3ebdSchin 							if (*v == ' ')
1378da2e3ebdSchin 							{
1379da2e3ebdSchin 								while (*(v + 1) == '*')
1380da2e3ebdSchin 									*v++ = '*';
1381da2e3ebdSchin 								*v = '\t';
1382da2e3ebdSchin 								if ((v - ko) <= 8)
1383da2e3ebdSchin 								{
1384da2e3ebdSchin 									om = (e = ++op) + 1;
1385da2e3ebdSchin 									while (e > v)
1386da2e3ebdSchin 									{
1387da2e3ebdSchin 										*e = *(e - 1);
1388da2e3ebdSchin 										e--;
1389da2e3ebdSchin 									}
1390da2e3ebdSchin 								}
1391da2e3ebdSchin 							}
1392da2e3ebdSchin 							om = (v = (op += 7)) + 1;
1393da2e3ebdSchin 							while (v >= ko + 7)
1394da2e3ebdSchin 							{
1395da2e3ebdSchin 								*v = *(v - 7);
1396da2e3ebdSchin 								v--;
1397da2e3ebdSchin 							}
1398da2e3ebdSchin 							memcopy(ko, "extern ", 7);
1399da2e3ebdSchin 						}
1400da2e3ebdSchin 						PUTCHR('(');
1401da2e3ebdSchin 						t = op;
1402da2e3ebdSchin 						e = 0;
1403da2e3ebdSchin 						/*UNDENT...*/
1404da2e3ebdSchin 	while (ie < ip)
1405da2e3ebdSchin 	{
1406da2e3ebdSchin 		if ((c = *ie) == ' ' || c == '\t' || c == '\n')
1407da2e3ebdSchin 		{
1408da2e3ebdSchin 			while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1409da2e3ebdSchin 			if (ie >= ip) break;
1410da2e3ebdSchin 			if (c != '*' && op > om) PUTCHR(' ');
1411da2e3ebdSchin 		}
1412da2e3ebdSchin 		if ((n = ((c = *ie) == ',')) || c == ';')
1413da2e3ebdSchin 		{
1414da2e3ebdSchin 			if (flags & EXTERN)
1415da2e3ebdSchin 			{
1416da2e3ebdSchin 				m = op;
1417da2e3ebdSchin 				while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
1418da2e3ebdSchin 					op--;
1419da2e3ebdSchin 				v = op;
1420da2e3ebdSchin 				while (op > om && (c = *(op - 1)) != ' ' && c != '*')
1421da2e3ebdSchin 					op--;
1422da2e3ebdSchin 				while (*(op - 1) == ' ')
1423da2e3ebdSchin 					op--;
1424da2e3ebdSchin 				if (!e)
1425da2e3ebdSchin 				{
1426da2e3ebdSchin 					e = op;
1427da2e3ebdSchin 					while (e > om && *(e - 1) == '*')
1428da2e3ebdSchin 						e--;
1429da2e3ebdSchin 				}
1430da2e3ebdSchin #if _s5r4_386_compiler_bug_fixed_
1431da2e3ebdSchin 				if (op <= om || *(op - 1) == ',' && (*op++ = ' '))
1432da2e3ebdSchin 					op = strcopy(op, "int");
1433da2e3ebdSchin #else
1434da2e3ebdSchin 				if (op <= om)
1435da2e3ebdSchin 					op = strcopy(op, "int");
1436da2e3ebdSchin 				else if (*(op - 1) == ',')
1437da2e3ebdSchin 					op = strcopy(op, " int");
1438da2e3ebdSchin #endif
1439da2e3ebdSchin 				while (v < m)
1440da2e3ebdSchin 					PUTCHR(*v++);
1441da2e3ebdSchin 			}
1442da2e3ebdSchin 			PUTCHR(',');
1443da2e3ebdSchin 			if (n)
1444da2e3ebdSchin 			{
1445da2e3ebdSchin 				if (x = !e) e = op - 1;
1446da2e3ebdSchin 				PUTCHR(' ');
1447da2e3ebdSchin 				m = t;
1448da2e3ebdSchin 				while (m < e)
1449da2e3ebdSchin 					PUTCHR(*m++);
1450da2e3ebdSchin 				if (x)
1451da2e3ebdSchin 				{
1452da2e3ebdSchin 					m = e;
1453da2e3ebdSchin 					while (*--e != ' ');
1454da2e3ebdSchin 					while (*(e - 1) == '*') e--;
1455da2e3ebdSchin 					op -= m - e;
1456da2e3ebdSchin 				}
1457da2e3ebdSchin 			}
1458da2e3ebdSchin 			while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1459da2e3ebdSchin 			if (ie >= ip) UNPUTCHR();
1460da2e3ebdSchin 			else PUTCHR(' ');
1461da2e3ebdSchin 			if (!n)
1462da2e3ebdSchin 			{
1463da2e3ebdSchin 				t = op;
1464da2e3ebdSchin 				e = 0;
1465da2e3ebdSchin 			}
1466da2e3ebdSchin 		}
1467da2e3ebdSchin 		else if (*ie == '*')
1468da2e3ebdSchin 		{
1469da2e3ebdSchin 			if (op > om && (c = *(op - 1)) == ' ') op--;
1470da2e3ebdSchin 			while (*ie == '*') PUTCHR(*ie++);
1471da2e3ebdSchin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1472da2e3ebdSchin 			if (c != '(') PUTCHR(' ');
1473da2e3ebdSchin 		}
1474da2e3ebdSchin 		else if (*ie == '(')
1475da2e3ebdSchin 		{
1476da2e3ebdSchin 			if (op > om && *(op - 1) == ' ') op--;
1477da2e3ebdSchin 			PUTCHR(*ie++);
1478da2e3ebdSchin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1479da2e3ebdSchin 		}
1480da2e3ebdSchin 		else if (*ie == ')')
1481da2e3ebdSchin 		{
1482da2e3ebdSchin 			if (op > om && *(op - 1) == '(')
1483da2e3ebdSchin 				proto_error((char*)proto + sizeof(struct proto), 1, "function pointer argument prototype omitted", NiL);
1484da2e3ebdSchin 			PUTCHR(*ie++);
1485da2e3ebdSchin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1486da2e3ebdSchin 		}
1487da2e3ebdSchin 		else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
1488da2e3ebdSchin 		{
1489da2e3ebdSchin 			ie += 8;
1490da2e3ebdSchin 			if (op > om) UNPUTCHR();
1491da2e3ebdSchin 		}
1492da2e3ebdSchin 		else PUTCHR(*ie++);
1493da2e3ebdSchin 	}
1494da2e3ebdSchin 						/*...INDENT*/
1495da2e3ebdSchin 						if (op <= om) op = strcopy(op, "void");
1496da2e3ebdSchin 						PUTCHR(')');
1497da2e3ebdSchin 						if (flags & EXTERN)
1498da2e3ebdSchin 						{
1499da2e3ebdSchin 							PUTCHR(';');
1500da2e3ebdSchin 							PUTCHR('\n');
1501da2e3ebdSchin 							SYNCOUT();
1502da2e3ebdSchin 							KEEPOUT();
1503da2e3ebdSchin 						}
1504da2e3ebdSchin 						else
1505da2e3ebdSchin 						{
1506da2e3ebdSchin 							PUTCHR('\n');
1507da2e3ebdSchin 							PUTCHR(*ip);
1508da2e3ebdSchin 						}
1509da2e3ebdSchin 						ip++;
1510da2e3ebdSchin 						flags &= ~(MATCH|SKIP);
1511da2e3ebdSchin 					}
1512da2e3ebdSchin 				}
1513da2e3ebdSchin #endif
1514da2e3ebdSchin 				else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS))
1515da2e3ebdSchin 				{
1516da2e3ebdSchin 					line = proto->line;
1517da2e3ebdSchin 					op = strcopy(om, " __PARAM__(");
1518da2e3ebdSchin 					op = memcopy(op, im, ie - im);
1519da2e3ebdSchin 					PUTCHR(',');
1520da2e3ebdSchin 					PUTCHR(' ');
1521da2e3ebdSchin 					PUTCHR('(');
1522da2e3ebdSchin 					flags &= ~(MATCH|SKIP);
1523da2e3ebdSchin 					if (flags & VARIADIC)
1524da2e3ebdSchin 					{
1525da2e3ebdSchin 						if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
1526da2e3ebdSchin 						memcopy(proto->variadic, im, vc);
1527da2e3ebdSchin 						op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
1528da2e3ebdSchin 					}
1529da2e3ebdSchin 					else
1530da2e3ebdSchin 					{
1531da2e3ebdSchin 						flags |= SKIP;
1532da2e3ebdSchin 						proto->ip = im;
1533da2e3ebdSchin 						proto->op = op;
1534da2e3ebdSchin 						group = 0;
1535da2e3ebdSchin 						brack = 0;
1536da2e3ebdSchin 						for (;;)
1537da2e3ebdSchin 						{
1538da2e3ebdSchin 							switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1539da2e3ebdSchin 							{
1540da2e3ebdSchin 							case '[':
1541da2e3ebdSchin 								brack++;
1542da2e3ebdSchin 								continue;
1543da2e3ebdSchin 							case ']':
1544da2e3ebdSchin 								brack--;
1545da2e3ebdSchin 								continue;
1546da2e3ebdSchin 							case '(':
1547da2e3ebdSchin 								if (paren++) group++;
1548da2e3ebdSchin 								continue;
1549da2e3ebdSchin 							case ')':
1550da2e3ebdSchin 								if (--paren == 0)
1551da2e3ebdSchin 								{
1552da2e3ebdSchin 									group = 0;
1553da2e3ebdSchin 									if (flags & MATCH)
1554da2e3ebdSchin 									{
1555da2e3ebdSchin 										flags &= ~(MATCH|SKIP);
1556da2e3ebdSchin 										op = memcopy(op, m, e - m);
1557da2e3ebdSchin 									}
1558da2e3ebdSchin 									break;
1559da2e3ebdSchin 								}
1560da2e3ebdSchin 								continue;
1561da2e3ebdSchin 							case ',':
1562da2e3ebdSchin 								if (paren == 1)
1563da2e3ebdSchin 								{
1564da2e3ebdSchin 									group = 0;
1565da2e3ebdSchin 									if (flags & MATCH)
1566da2e3ebdSchin 									{
1567da2e3ebdSchin 										flags &= ~(MATCH|SKIP);
1568da2e3ebdSchin 										op = memcopy(op, m, e - m);
1569da2e3ebdSchin 									}
1570da2e3ebdSchin 									PUTCHR(',');
1571da2e3ebdSchin 									PUTCHR(' ');
1572da2e3ebdSchin 									proto->op = op;
1573da2e3ebdSchin 								}
1574da2e3ebdSchin 								continue;
1575da2e3ebdSchin 							case T_ID:
1576da2e3ebdSchin 								if (group <= 1 && !brack)
1577da2e3ebdSchin 								{
1578da2e3ebdSchin 									flags |= MATCH;
1579da2e3ebdSchin 									m = proto->tp;
1580da2e3ebdSchin 									e = proto->ip;
1581da2e3ebdSchin 								}
1582da2e3ebdSchin 								continue;
1583da2e3ebdSchin 							default:
1584da2e3ebdSchin 								continue;
1585da2e3ebdSchin 							}
1586da2e3ebdSchin 							break;
1587da2e3ebdSchin 						}
1588da2e3ebdSchin 						PUTCHR(')');
1589da2e3ebdSchin 						PUTCHR(')');
1590da2e3ebdSchin 					}
1591da2e3ebdSchin 					if (!(flags & SKIP))
1592da2e3ebdSchin 					{
1593da2e3ebdSchin 						flags |= SKIP;
1594da2e3ebdSchin 						proto->op = strcopy(op, " __OTORP__(");
1595da2e3ebdSchin 						proto->ip = im + 1;
1596da2e3ebdSchin 						n = *(ie - 1);
1597da2e3ebdSchin 						*(ie - 1) = ';';
1598da2e3ebdSchin 						c = *ie;
1599da2e3ebdSchin 						*ie = 0;
1600da2e3ebdSchin 						lex(proto, (flags & GLOBAL) | DECLARE);
1601da2e3ebdSchin 						*(ie - 1) = n;
1602da2e3ebdSchin 						*ie = c;
1603da2e3ebdSchin 						proto->ip = ie;
1604da2e3ebdSchin 						op = proto->op;
1605da2e3ebdSchin 						PUTCHR(')');
1606da2e3ebdSchin 					}
1607da2e3ebdSchin 					if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1608da2e3ebdSchin 					op = linesync(proto, op, proto->line = line);
1609da2e3ebdSchin 					if (flags & DIRECTIVE)
1610da2e3ebdSchin 					{
1611da2e3ebdSchin 						proto->brace = 0;
1612da2e3ebdSchin 						PUTCHR('\n');
1613da2e3ebdSchin 						PUTCHR('#');
1614da2e3ebdSchin 					}
1615da2e3ebdSchin 					else if (!(flags & VARIADIC)) PUTCHR('{');
1616da2e3ebdSchin 				}
1617da2e3ebdSchin 			}
1618da2e3ebdSchin 			flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1619da2e3ebdSchin 			call = 0;
1620da2e3ebdSchin 			group = 0;
1621da2e3ebdSchin 			break;
1622da2e3ebdSchin 		case '}':
1623da2e3ebdSchin 			flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS);
1624da2e3ebdSchin 			if (--proto->brace == 0)
1625da2e3ebdSchin 			{
1626da2e3ebdSchin 				flags &= ~(INIT|VARIADIC|VARIADIC2);
1627da2e3ebdSchin #if PROTOMAIN
1628da2e3ebdSchin 				if (flags & EXTERN) BACKOUT();
1629da2e3ebdSchin #endif
1630da2e3ebdSchin 			}
1631da2e3ebdSchin 			call = 0;
1632da2e3ebdSchin 			group = 0;
1633da2e3ebdSchin 			paren = 0;
1634da2e3ebdSchin 			break;
1635da2e3ebdSchin 		case '=':
1636da2e3ebdSchin 			if (last == '?') flags |= DIRECTIVE;
16377c2fbfb3SApril Chin 			else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH)
16387c2fbfb3SApril Chin 			{
16397c2fbfb3SApril Chin 				if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= SKIP;
16407c2fbfb3SApril Chin 				else goto fsm_statement;
16417c2fbfb3SApril Chin 			}
1642da2e3ebdSchin 			goto fsm_other;
1643da2e3ebdSchin 		case ',':
1644da2e3ebdSchin #if PROTOMAIN
1645da2e3ebdSchin 			if (flags & CLASSIC)
1646da2e3ebdSchin 			{
1647da2e3ebdSchin 				if (paren == 1) args++;
1648da2e3ebdSchin 				else
1649da2e3ebdSchin 				{
1650da2e3ebdSchin 					args--;
1651da2e3ebdSchin 					flags &= ~MATCH;
1652da2e3ebdSchin 				}
1653da2e3ebdSchin 				break;
1654da2e3ebdSchin 			}
1655da2e3ebdSchin #endif
1656da2e3ebdSchin 			if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';';
1657da2e3ebdSchin 			/*FALLTHROUGH*/
1658da2e3ebdSchin 		case ';':
1659da2e3ebdSchin  fsm_statement:
1660da2e3ebdSchin 			if (flags & INIT) /* ignore */;
1661da2e3ebdSchin #if PROTOMAIN
1662da2e3ebdSchin 			else if (flags & CLASSIC)
1663da2e3ebdSchin 			{
1664da2e3ebdSchin 				if (paren == 0)
1665da2e3ebdSchin 				{
1666da2e3ebdSchin 					if ((flags & MATCH) && last == ')')
1667da2e3ebdSchin 						flags &= ~MATCH;
1668da2e3ebdSchin 					if (!(flags & MATCH))
1669da2e3ebdSchin 					{
1670da2e3ebdSchin 						call = 0;
1671da2e3ebdSchin 						group = 0;
1672da2e3ebdSchin 						flags &= ~SKIP;
1673da2e3ebdSchin 						if (flags & EXTERN) BACKOUT();
1674da2e3ebdSchin 						if (flags & SLIDE)
1675da2e3ebdSchin 						{
1676da2e3ebdSchin 							SYNC();
1677da2e3ebdSchin 							return 0;
1678da2e3ebdSchin 						}
1679da2e3ebdSchin 					}
1680da2e3ebdSchin 					else
1681da2e3ebdSchin 					{
1682da2e3ebdSchin 						args--;
1683da2e3ebdSchin 						if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP))
1684da2e3ebdSchin 							BACKOUT();
1685da2e3ebdSchin 					}
1686da2e3ebdSchin 				}
1687da2e3ebdSchin 			}
1688da2e3ebdSchin #endif
1689da2e3ebdSchin 			else if (paren == 0)
1690da2e3ebdSchin 			{
1691da2e3ebdSchin 				if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1)
1692da2e3ebdSchin 				{
1693da2e3ebdSchin 					if ((flags & MANGLE) && func)
1694da2e3ebdSchin 					{
1695da2e3ebdSchin 						func[0] = 'F';
1696da2e3ebdSchin 						func[1] = 'U';
1697da2e3ebdSchin 						func[2] = 'N';
1698da2e3ebdSchin 						func[3] = 'C';
1699da2e3ebdSchin 						func = 0;
1700da2e3ebdSchin 					}
1701da2e3ebdSchin 					if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im)
1702da2e3ebdSchin 					{
1703da2e3ebdSchin 						while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
1704da2e3ebdSchin 						v = aim;
1705da2e3ebdSchin 						while (v < aie)
1706da2e3ebdSchin 							if (*v++ == ')') break;
1707da2e3ebdSchin 						while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
1708da2e3ebdSchin 						if (v == aie || !(flags & PLUSPLUS))
1709da2e3ebdSchin 						{
1710da2e3ebdSchin 							if (flags & PLUSPLUS) n = 3;
1711da2e3ebdSchin 							else if (v == aie && *v == '(') n = 10;
1712da2e3ebdSchin 							else n = 11;
1713da2e3ebdSchin 							ko = op;
1714da2e3ebdSchin 							om += n;
1715da2e3ebdSchin 							v = op += n;
1716da2e3ebdSchin 							while (v >= ko + n)
1717da2e3ebdSchin 							{
1718da2e3ebdSchin 								*v = *(v - n);
1719da2e3ebdSchin 								v--;
1720da2e3ebdSchin 							}
1721da2e3ebdSchin 							if (flags & PLUSPLUS) memcopy(aom, "(...))", 6);
1722da2e3ebdSchin 							else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
1723da2e3ebdSchin 							else
1724da2e3ebdSchin 							{
1725da2e3ebdSchin 								ko = strcopy(aom, " __PROTO__(");
1726da2e3ebdSchin 								ko = memcopy(ko, aim, aie - aim);
1727da2e3ebdSchin 								*ko = ')';
1728da2e3ebdSchin 								if (++ko >= om)
1729da2e3ebdSchin 								{
1730da2e3ebdSchin 									*ko++ = ')';
1731da2e3ebdSchin 									om = ko;
1732da2e3ebdSchin 								}
1733da2e3ebdSchin 							}
1734da2e3ebdSchin 						}
1735da2e3ebdSchin 					}
1736da2e3ebdSchin 					else if (flags & TYPEDEF)
1737da2e3ebdSchin 					{
1738da2e3ebdSchin 						op = om;
1739da2e3ebdSchin 						while (*--op == ' ' || *op == '\t' || *op == '\n');
1740da2e3ebdSchin 						if (*op != ')')
1741da2e3ebdSchin 						{
1742da2e3ebdSchin 							op = om += 14;
1743da2e3ebdSchin 							*--op = ')';
1744da2e3ebdSchin 							while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
1745da2e3ebdSchin 								*--op = x;
1746da2e3ebdSchin 							memcopy(op - 13, "(__OTORP__(*)", 13);
1747da2e3ebdSchin 						}
1748da2e3ebdSchin 					}
1749da2e3ebdSchin 					if (flags & OTHER)
1750da2e3ebdSchin 						;
1751da2e3ebdSchin 					else if (flags & PLUSPLUS)
1752da2e3ebdSchin 					{
1753da2e3ebdSchin 						op = om;
1754da2e3ebdSchin 						if (!(flags & TOKENS)) op = strcopy(op, "(...)");
1755da2e3ebdSchin 						else op = memcopy(op, im, ie - im);
1756da2e3ebdSchin 						PUTCHR(c);
1757da2e3ebdSchin 					}
1758da2e3ebdSchin 					else
1759da2e3ebdSchin 					{
1760da2e3ebdSchin 						if (flags & DECLARE) op = strcopy(om, "()");
1761da2e3ebdSchin 						else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)");
1762da2e3ebdSchin 						else
1763da2e3ebdSchin 						{
1764da2e3ebdSchin 							op = strcopy(om, " __PROTO__(");
1765da2e3ebdSchin 							op = memcopy(op, im, ie - im);
1766da2e3ebdSchin 							PUTCHR(')');
1767da2e3ebdSchin 						}
1768da2e3ebdSchin 						if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1769da2e3ebdSchin 						PUTCHR(c);
1770da2e3ebdSchin 					}
1771da2e3ebdSchin 					flags &= ~(MATCH|VARIADIC|VARIADIC2);
1772da2e3ebdSchin 					if (c == ',' && !(flags & INDIRECT))
1773da2e3ebdSchin 					{
1774da2e3ebdSchin 						call = 1;
1775da2e3ebdSchin 						group = 0;
1776da2e3ebdSchin 						break;
1777da2e3ebdSchin 					}
1778da2e3ebdSchin 				}
1779da2e3ebdSchin 				else if (flags & (OTHER|SKIP)) call = 0;
1780da2e3ebdSchin 				if (c == ';')
1781da2e3ebdSchin 				{
1782da2e3ebdSchin 					flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF);
1783da2e3ebdSchin 					call = 0;
1784da2e3ebdSchin 					if (flags & SLIDE)
1785da2e3ebdSchin 					{
1786da2e3ebdSchin 						SYNC();
1787da2e3ebdSchin 						return 0;
1788da2e3ebdSchin 					}
1789da2e3ebdSchin 				}
1790da2e3ebdSchin 				else call = call > 1 && c == ',';
1791da2e3ebdSchin 				group = 0;
1792da2e3ebdSchin 				flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1793da2e3ebdSchin 			}
1794da2e3ebdSchin 			else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER;
1795da2e3ebdSchin 			break;
1796da2e3ebdSchin 		case T_DO:
1797da2e3ebdSchin 		case T_IF:
1798da2e3ebdSchin 			flags |= TOKENS|SKIP;
1799da2e3ebdSchin 			break;
1800da2e3ebdSchin 		case T_EXTERN:
1801da2e3ebdSchin #if PROTOMAIN
1802da2e3ebdSchin 			if (flags & CLASSIC)
1803da2e3ebdSchin 			{
1804da2e3ebdSchin 				if (proto->brace == 0)
1805da2e3ebdSchin 					flags |= SKIP;
1806da2e3ebdSchin 			}
1807da2e3ebdSchin 			else
1808da2e3ebdSchin #endif
1809da2e3ebdSchin 			if (paren == 0 && !(flags & TYPEDEF))
1810da2e3ebdSchin 			{
1811da2e3ebdSchin 				flags |= MANGLE;
1812da2e3ebdSchin 				if (!(flags & PLUSONLY) || proto->package)
1813da2e3ebdSchin 				{
1814da2e3ebdSchin 					op = strcopy(op, " __MANGLE__");
1815da2e3ebdSchin 					if (proto->package)
1816da2e3ebdSchin 					{
1817da2e3ebdSchin 						op = strcopy(op - 1, proto->package);
1818da2e3ebdSchin 						func = op + 1;
1819da2e3ebdSchin 						op = strcopy(op, "_DATA__");
1820da2e3ebdSchin 					}
1821da2e3ebdSchin 				}
1822da2e3ebdSchin 				else
1823da2e3ebdSchin 					func = 0;
1824da2e3ebdSchin 			}
1825da2e3ebdSchin 			break;
1826da2e3ebdSchin 		case T_VARIADIC:
1827da2e3ebdSchin 			if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE)
1828da2e3ebdSchin 			{
1829da2e3ebdSchin 				op -= 3;
1830da2e3ebdSchin 				SYNC();
1831da2e3ebdSchin 				return c;
1832da2e3ebdSchin 			}
1833da2e3ebdSchin 			if (paren == 1 && !(flags & SKIP))
1834da2e3ebdSchin 				flags |= VARIADIC;
1835da2e3ebdSchin 			flags |= TOKENS;
1836da2e3ebdSchin 			break;
1837da2e3ebdSchin 		case T_VOID:
1838da2e3ebdSchin 			goto fsm_id;
1839da2e3ebdSchin 		case T_VA_START:
1840da2e3ebdSchin 			if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC)
1841da2e3ebdSchin 			{
1842da2e3ebdSchin 				flags &= ~MATCH;
1843da2e3ebdSchin 				line = proto->line;
1844da2e3ebdSchin 				op = strcopy(op - 8, "__VA_START__");
1845da2e3ebdSchin 				SYNC();
1846da2e3ebdSchin 				for (;;)
1847da2e3ebdSchin 				{
1848da2e3ebdSchin 					switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1849da2e3ebdSchin 					{
1850da2e3ebdSchin 					case 0:
1851da2e3ebdSchin 					case ';':
1852da2e3ebdSchin 						break;
1853da2e3ebdSchin 					case T_ID:
1854da2e3ebdSchin 						if (!(flags & MATCH))
1855da2e3ebdSchin 						{
1856da2e3ebdSchin 							flags |= MATCH;
1857da2e3ebdSchin 							m = proto->tp;
1858da2e3ebdSchin 							e = proto->ip;
1859da2e3ebdSchin 						}
1860da2e3ebdSchin 						continue;
1861da2e3ebdSchin 					default:
1862da2e3ebdSchin 						continue;
1863da2e3ebdSchin 					}
1864da2e3ebdSchin 					break;
1865da2e3ebdSchin 				}
1866da2e3ebdSchin 				CACHE();
1867da2e3ebdSchin 				if (flags & MATCH)
1868da2e3ebdSchin 				{
1869da2e3ebdSchin 					v = m;
1870da2e3ebdSchin 					n = e - m;
1871da2e3ebdSchin 				}
1872da2e3ebdSchin 				else
1873da2e3ebdSchin 				{
1874da2e3ebdSchin 					v = "ap";
1875da2e3ebdSchin 					n = 2;
1876da2e3ebdSchin 				}
1877da2e3ebdSchin 				op = strcopy(op, " __OTORP__(");
1878da2e3ebdSchin 				proto->ip = proto->variadic;
1879da2e3ebdSchin 				proto->op = op;
1880da2e3ebdSchin 				flags &= ~MATCH;
1881da2e3ebdSchin 				group = 0;
1882da2e3ebdSchin 				bp = proto->ip + 1;
1883da2e3ebdSchin 				if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1884da2e3ebdSchin 				for (;;)
1885da2e3ebdSchin 				{
1886da2e3ebdSchin 					switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1887da2e3ebdSchin 					{
1888da2e3ebdSchin 					case '(':
1889da2e3ebdSchin 						if (paren++) group++;
1890da2e3ebdSchin 						continue;
1891da2e3ebdSchin 					case ')':
1892da2e3ebdSchin 						if (--paren == 0)
1893da2e3ebdSchin 						{
1894da2e3ebdSchin 							if (flags & MATCH)
1895da2e3ebdSchin 							{
1896da2e3ebdSchin 								flags &= ~MATCH;
1897da2e3ebdSchin 								if (!(flags & VARIADIC2))
1898da2e3ebdSchin 								{
1899da2e3ebdSchin 									op = memcopy(op, m, e - m);
1900da2e3ebdSchin 									op = strcopy(op, " = ");
1901da2e3ebdSchin 								}
1902da2e3ebdSchin 								op = strcopy(op, "va_arg(");
1903da2e3ebdSchin 								op = memcopy(op, v, n);
1904da2e3ebdSchin 								PUTCHR(',');
1905da2e3ebdSchin 								PUTCHR(' ');
1906da2e3ebdSchin 								if (m > bp) op = memcopy(op, bp, m - bp);
1907da2e3ebdSchin 								else op = strcopy(op, "int ");
1908da2e3ebdSchin 								if (group > 1) op = strcopy(op, ")()");
1909da2e3ebdSchin 								else op = memcopy(op, e, proto->ip - e - 1);
1910da2e3ebdSchin 								PUTCHR(')');
1911da2e3ebdSchin 								PUTCHR(';');
1912da2e3ebdSchin 							}
1913da2e3ebdSchin 							group = 0;
1914da2e3ebdSchin 							break;
1915da2e3ebdSchin 						}
1916da2e3ebdSchin 						continue;
1917da2e3ebdSchin 					case ',':
1918da2e3ebdSchin 						if (paren == 1)
1919da2e3ebdSchin 						{
1920da2e3ebdSchin 							if (flags & MATCH)
1921da2e3ebdSchin 							{
1922da2e3ebdSchin 								flags &= ~MATCH;
1923da2e3ebdSchin 								if (!(flags & VARIADIC2))
1924da2e3ebdSchin 								{
1925da2e3ebdSchin 									op = memcopy(op, m, e - m);
1926da2e3ebdSchin 									op = strcopy(op, " = ");
1927da2e3ebdSchin 								}
1928da2e3ebdSchin 								op = strcopy(op, "va_arg(");
1929da2e3ebdSchin 								op = memcopy(op, v, n);
1930da2e3ebdSchin 								PUTCHR(',');
1931da2e3ebdSchin 								PUTCHR(' ');
1932da2e3ebdSchin 								if (m > bp) op = memcopy(op, bp, m - bp);
1933da2e3ebdSchin 								else op = strcopy(op, "int ");
1934da2e3ebdSchin 								if (group > 1) op = strcopy(op, ")()");
1935da2e3ebdSchin 								else op = memcopy(op, e, proto->ip - e - 1);
1936da2e3ebdSchin 								PUTCHR(')');
1937da2e3ebdSchin 								PUTCHR(';');
1938da2e3ebdSchin 								bp = proto->ip + 1;
1939da2e3ebdSchin 								if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1940da2e3ebdSchin 							}
1941da2e3ebdSchin 							group = 0;
1942da2e3ebdSchin 							proto->op = op;
1943da2e3ebdSchin 						}
1944da2e3ebdSchin 						continue;
1945da2e3ebdSchin 					case T_ID:
1946da2e3ebdSchin 						if (group <= 1)
1947da2e3ebdSchin 						{
1948da2e3ebdSchin 							flags |= MATCH;
1949da2e3ebdSchin 							m = proto->tp;
1950da2e3ebdSchin 							e = proto->ip;
1951da2e3ebdSchin 						}
1952da2e3ebdSchin 						continue;
1953da2e3ebdSchin 					default:
1954da2e3ebdSchin 						continue;
1955da2e3ebdSchin 					}
1956da2e3ebdSchin 					break;
1957da2e3ebdSchin 				}
1958da2e3ebdSchin 				op = strcopy(op, ")");
1959da2e3ebdSchin 				flags |= VARIADIC2;
1960da2e3ebdSchin 				proto->line = line;
1961da2e3ebdSchin 				call = 0;
1962da2e3ebdSchin 				break;
1963da2e3ebdSchin 			}
1964da2e3ebdSchin 			/*FALLTHROUGH*/
1965da2e3ebdSchin 		case T_ID:
1966da2e3ebdSchin  fsm_id:
1967da2e3ebdSchin #if PROTOMAIN
1968da2e3ebdSchin 			if (flags & CLASSIC)
1969da2e3ebdSchin 			{
1970da2e3ebdSchin 				if (!args && paren == 1) args++;
1971da2e3ebdSchin 				break;
1972da2e3ebdSchin 			}
1973da2e3ebdSchin #endif
1974da2e3ebdSchin 			if (paren == 0)
1975da2e3ebdSchin 			{
1976da2e3ebdSchin 				if (last == ')')
1977da2e3ebdSchin 				{
1978da2e3ebdSchin 					if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP;
1979da2e3ebdSchin 					call = !call;
1980da2e3ebdSchin 				}
1981da2e3ebdSchin 				else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++;
1982da2e3ebdSchin 				else flags |= SKIP;
1983da2e3ebdSchin 				if (last == T_ID) flags |= IDID;
1984da2e3ebdSchin 			}
1985da2e3ebdSchin 			c = T_ID;
1986da2e3ebdSchin 			flags |= TOKENS;
1987da2e3ebdSchin 			break;
1988da2e3ebdSchin 		case T_INVALID:
1989da2e3ebdSchin 			if (*proto->tp >= '0' && *proto->tp <= '9')
1990da2e3ebdSchin 			{
1991da2e3ebdSchin 				n = 0;
1992da2e3ebdSchin 				for (;; op--)
1993da2e3ebdSchin 				{
1994da2e3ebdSchin 					switch (*(op - 1))
1995da2e3ebdSchin 					{
1996da2e3ebdSchin 					case 'f':
1997da2e3ebdSchin 					case 'F':
1998da2e3ebdSchin 						t = op;
1999da2e3ebdSchin 						while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
2000da2e3ebdSchin 						if (*t == '.')
2001da2e3ebdSchin 							op--;
2002da2e3ebdSchin 						n = 0;
2003da2e3ebdSchin 						break;
2004da2e3ebdSchin 					case 'l':
2005da2e3ebdSchin 					case 'L':
2006da2e3ebdSchin 						if (!(n & 01))
2007da2e3ebdSchin 						{
2008da2e3ebdSchin 							n |= 01;
2009da2e3ebdSchin 							t = op;
2010da2e3ebdSchin 							while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
2011da2e3ebdSchin 							if (*t == '.')
2012da2e3ebdSchin 							{
2013da2e3ebdSchin 								n = 0;
2014da2e3ebdSchin 								op--;
2015da2e3ebdSchin 								break;
2016da2e3ebdSchin 							}
2017da2e3ebdSchin 						}
2018da2e3ebdSchin 						continue;
2019da2e3ebdSchin 					case 'u':
2020da2e3ebdSchin 					case 'U':
2021da2e3ebdSchin 						n |= 02;
2022da2e3ebdSchin 						continue;
2023da2e3ebdSchin 					}
2024da2e3ebdSchin 					break;
2025da2e3ebdSchin 				}
2026da2e3ebdSchin 				if (n & 01)
2027da2e3ebdSchin 					*op++ = 'L';
2028da2e3ebdSchin 				if (n & 02)
2029da2e3ebdSchin 				{
2030da2e3ebdSchin 					m = op;
2031da2e3ebdSchin 					t = op = m + 10;
2032da2e3ebdSchin 					while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
2033da2e3ebdSchin 						*--t = c;
2034da2e3ebdSchin 					c = *t;
2035da2e3ebdSchin 					strcopy(m + 1, "(unsigned)");
2036da2e3ebdSchin 					*t = c;
2037da2e3ebdSchin 					break;
2038da2e3ebdSchin 				}
2039da2e3ebdSchin 			}
2040da2e3ebdSchin 			goto fsm_other;
2041da2e3ebdSchin #if PROTOMAIN
2042da2e3ebdSchin 		case '[':
2043da2e3ebdSchin 			if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP;
2044da2e3ebdSchin 			/*FALLTHROUGH*/
2045da2e3ebdSchin #endif
2046da2e3ebdSchin 		default:
2047da2e3ebdSchin  fsm_other:
2048da2e3ebdSchin #if PROTOMAIN
2049da2e3ebdSchin 			if (flags & CLASSIC) break;
2050da2e3ebdSchin #endif
2051da2e3ebdSchin 			flags |= TOKENS;
2052da2e3ebdSchin 			if (paren == 0) flags |= OTHER;
2053da2e3ebdSchin 			break;
2054da2e3ebdSchin 		}
2055da2e3ebdSchin 		else if (c == '#' && *ip != '(') flags |= SHARP;
2056da2e3ebdSchin 		last = c;
2057da2e3ebdSchin #if PROTOMAIN
2058da2e3ebdSchin 		if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID))
2059da2e3ebdSchin 			CACHEOUT();
2060da2e3ebdSchin 		else
2061da2e3ebdSchin #endif
2062da2e3ebdSchin 		SYNCOUT();
2063da2e3ebdSchin 		goto fsm_start;
2064da2e3ebdSchin 	}
2065da2e3ebdSchin 	else if (flags & (INIT_DEFINE|INIT_INCLUDE))
2066da2e3ebdSchin 	{
2067da2e3ebdSchin #if PROTOMAIN
2068da2e3ebdSchin 		if ((flags & YACC) && c == '%' && *ip == '{') t = 0;
2069da2e3ebdSchin 		else
2070da2e3ebdSchin #endif
2071da2e3ebdSchin 		{
2072da2e3ebdSchin 			if (c == '#') for (t = ip; *t == ' ' || *t == '\t'; t++);
2073da2e3ebdSchin 			else t = "";
2074da2e3ebdSchin 			if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
2075da2e3ebdSchin 			{
2076da2e3ebdSchin #if !PROTOMAIN
2077da2e3ebdSchin 				while (*t == ' ' || *t == '\t') t++;
2078da2e3ebdSchin 				if (*t != '_')
2079da2e3ebdSchin #endif
2080da2e3ebdSchin 					t = 0;
2081da2e3ebdSchin 			}
2082da2e3ebdSchin 		}
2083da2e3ebdSchin 		if (t)
2084da2e3ebdSchin 		{
2085da2e3ebdSchin 			ip = bp;
2086da2e3ebdSchin 			op = proto->op;
2087da2e3ebdSchin 		}
2088da2e3ebdSchin 		else while (*ip != '\n') *op++ = *ip++;
2089da2e3ebdSchin 		op = init(proto, op, flags);
2090da2e3ebdSchin 		op = linesync(proto, op, proto->line);
2091da2e3ebdSchin 		flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2092da2e3ebdSchin 		proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2093da2e3ebdSchin 		goto fsm_start;
2094da2e3ebdSchin 	}
2095da2e3ebdSchin 	SYNC();
2096da2e3ebdSchin 	return c;
2097da2e3ebdSchin }
2098da2e3ebdSchin 
2099da2e3ebdSchin /*
2100da2e3ebdSchin  * close a proto buffer stream
2101da2e3ebdSchin  */
2102da2e3ebdSchin 
2103da2e3ebdSchin void
pppclose(char * iob)2104da2e3ebdSchin pppclose(char* iob)
2105da2e3ebdSchin {
2106da2e3ebdSchin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
2107da2e3ebdSchin 
2108da2e3ebdSchin 	if (proto->flags & MORE) close(proto->fd);
2109da2e3ebdSchin 	free((char*)proto); /* some ANSI cc's botch the free() prototype */
2110da2e3ebdSchin }
2111da2e3ebdSchin 
2112da2e3ebdSchin /*
2113da2e3ebdSchin  * open a new proto buffer stream
2114da2e3ebdSchin  * read buffer pointer returned
2115da2e3ebdSchin  * 0 returned on error or if no magic
2116da2e3ebdSchin  *
2117da2e3ebdSchin  *	file	!=0	file path to open, otherwise use fd
2118da2e3ebdSchin  *	fd		open file fd if file==0
2119da2e3ebdSchin  *	notice	!=0	copyright notice info commented at the top
2120da2e3ebdSchin  *	options	!=0	additional notice name=value pairs, space or ; separated
2121da2e3ebdSchin  *	package	!=0	generate header for this package
2122da2e3ebdSchin  */
2123da2e3ebdSchin 
2124da2e3ebdSchin char*
pppopen(char * file,int fd,char * notice,char * options,char * package,char * comment,int flags)2125da2e3ebdSchin pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags)
2126da2e3ebdSchin {
2127da2e3ebdSchin 	register struct proto*	proto;
2128da2e3ebdSchin 	register char*		iob;
2129da2e3ebdSchin 	register long		n;
2130da2e3ebdSchin 	register char*		s;
2131da2e3ebdSchin 	int			pragma;
2132da2e3ebdSchin 	char*			b;
2133da2e3ebdSchin #if PROTOMAIN
2134da2e3ebdSchin 	int			comlen;
2135da2e3ebdSchin 	char			com[80];
2136da2e3ebdSchin #endif
2137da2e3ebdSchin 	int			m = 0;
2138da2e3ebdSchin 
2139da2e3ebdSchin 	static int		retain;
2140da2e3ebdSchin 
2141da2e3ebdSchin 	/*
2142da2e3ebdSchin 	 * initialize proto
2143da2e3ebdSchin 	 */
2144da2e3ebdSchin 
2145da2e3ebdSchin #if PROTOMAIN
2146da2e3ebdSchin 	if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE;
2147da2e3ebdSchin #endif
2148da2e3ebdSchin 	if (flags & PROTO_RETAIN) flags &= ~retain;
2149da2e3ebdSchin 	else retain &= PROTO_INITIALIZED;
2150da2e3ebdSchin 	if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
2151da2e3ebdSchin #if !PROTOMAIN
2152da2e3ebdSchin 	if ((n = lseek(fd, 0L, 2)) > 0)
2153da2e3ebdSchin 	{
2154da2e3ebdSchin 		if (lseek(fd, 0L, 0)) return 0;
2155da2e3ebdSchin 		if (n < CHUNK) n = CHUNK;
2156da2e3ebdSchin 		else if (n > 2 * BLOCK) n = 0;
2157da2e3ebdSchin 		m = 1;
2158da2e3ebdSchin 	}
2159da2e3ebdSchin 	if (n > 0)
2160da2e3ebdSchin 	{
2161da2e3ebdSchin 		/*
2162da2e3ebdSchin 		 * file read in one chunk
2163da2e3ebdSchin 		 */
2164da2e3ebdSchin 
2165da2e3ebdSchin 		if (!(proto = newof(0, struct proto, 1, 4 * n + 2)))
2166da2e3ebdSchin 			return 0;
2167da2e3ebdSchin 		proto->iz = n;
2168da2e3ebdSchin 		proto->oz = 3 * n;
2169da2e3ebdSchin 		n = 0;
2170da2e3ebdSchin 	}
2171da2e3ebdSchin 	else
2172da2e3ebdSchin #endif
2173da2e3ebdSchin 	{
2174da2e3ebdSchin 		/*
2175da2e3ebdSchin 		 * file read in BLOCK chunks
2176da2e3ebdSchin 		 */
2177da2e3ebdSchin 
2178da2e3ebdSchin 		n = BLOCK;
2179da2e3ebdSchin 		if (!(proto = newof(0, struct proto, 1, 5 * n + 2)))
2180da2e3ebdSchin 			return 0;
2181da2e3ebdSchin 		proto->iz = n;
2182da2e3ebdSchin 		proto->oz = 3 * n;
2183da2e3ebdSchin 		proto->flags |= MORE;
2184da2e3ebdSchin 	}
2185da2e3ebdSchin 	proto->fd = fd;
2186da2e3ebdSchin 	proto->package = package;
2187da2e3ebdSchin 	iob = (char*)proto + sizeof(struct proto);
2188da2e3ebdSchin 	proto->op = proto->ob = iob;
2189da2e3ebdSchin 	proto->ip = proto->ib = iob + proto->oz + n;
2190da2e3ebdSchin 	if (m) proto->options |= REGULAR;
2191da2e3ebdSchin 	if (!comment)
2192da2e3ebdSchin 		comment = "/*";
2193da2e3ebdSchin 	if (!(proto->cc[0] = comment[0]))
2194da2e3ebdSchin 		notice = options = 0;
2195da2e3ebdSchin 	else if (comment[1])
2196da2e3ebdSchin 	{
2197da2e3ebdSchin 		proto->cc[1] = comment[1];
2198da2e3ebdSchin 		proto->cc[2] = comment[2] ? comment[2] : comment[0];
2199da2e3ebdSchin 	}
2200da2e3ebdSchin 	else
2201da2e3ebdSchin 		proto->cc[1] = proto->cc[2] = comment[0];
2202da2e3ebdSchin 
2203da2e3ebdSchin 	/*
2204da2e3ebdSchin 	 * read the first chunk
2205da2e3ebdSchin 	 */
2206da2e3ebdSchin 
2207da2e3ebdSchin 	n = read(fd, proto->ip, proto->iz);
2208da2e3ebdSchin 	if (!(proto->flags & MORE))
2209da2e3ebdSchin 		close(fd);
2210da2e3ebdSchin 	if (n < 0)
2211da2e3ebdSchin 	{
2212da2e3ebdSchin 		pppclose(iob);
2213da2e3ebdSchin 		return 0;
2214da2e3ebdSchin 	}
2215da2e3ebdSchin 	*(proto->ip + n) = 0;
2216da2e3ebdSchin 
2217da2e3ebdSchin 	/*
2218da2e3ebdSchin 	 * check for proto pragma in first block of lines
2219da2e3ebdSchin 	 * pragma blanked out if found
2220da2e3ebdSchin 	 *
2221da2e3ebdSchin 	 *	-1	no pragma
2222da2e3ebdSchin 	 *	 0	#pragma noprototyped
2223da2e3ebdSchin 	 *	 1	#pragma prototyped
2224da2e3ebdSchin 	 *
2225da2e3ebdSchin 	 * NOTE: matches may occur inside comments and quotes
2226da2e3ebdSchin 	 */
2227da2e3ebdSchin 
2228da2e3ebdSchin #if PROTOMAIN
2229da2e3ebdSchin 	if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
2230da2e3ebdSchin 		*com = 0;
2231da2e3ebdSchin #endif
2232da2e3ebdSchin 	pragma = -1;
2233da2e3ebdSchin 	s = proto->ip;
2234da2e3ebdSchin 	m = MAGICTOP;
2235da2e3ebdSchin 	while (m-- > 0 && *s)
2236da2e3ebdSchin 	{
2237da2e3ebdSchin 		while (*s == ' ' || *s == '\t') s++;
2238da2e3ebdSchin 		if (*s == '#')
2239da2e3ebdSchin 		{
2240da2e3ebdSchin 			b = s++;
2241da2e3ebdSchin 			while (*s == ' ' || *s == '\t') s++;
2242da2e3ebdSchin 			if (!strncmp(s, MAGICDIR, sizeof(MAGICDIR) - 1) && (*(s += sizeof(MAGICDIR) - 1) == ' ' || *s == '\t'))
2243da2e3ebdSchin 			{
2244da2e3ebdSchin 				while (*s == ' ' || *s == '\t') s++;
2245da2e3ebdSchin 				if (*s == 'n' && *(s + 1) == 'o')
2246da2e3ebdSchin 				{
2247da2e3ebdSchin 					s += 2;
2248da2e3ebdSchin 					pragma = -2;
2249da2e3ebdSchin 				}
2250da2e3ebdSchin 				if (!strncmp(s, MAGICARG, sizeof(MAGICARG) - 1) && (*(s += sizeof(MAGICARG) - 1) == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
2251da2e3ebdSchin 					while (*s)
2252da2e3ebdSchin 					{
2253da2e3ebdSchin 						if ((*(s - 1) == ' ' || *(s - 1) == '\t') && *s == *MAGICOFF && !strncmp(s, MAGICOFF, sizeof(MAGICOFF) - 1))
2254da2e3ebdSchin 							notice = options = 0;
2255da2e3ebdSchin 						if (*s++ == '\n')
2256da2e3ebdSchin 						{
2257da2e3ebdSchin 							pragma += 2;
2258da2e3ebdSchin #if PROTOMAIN
2259da2e3ebdSchin 							if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA))
2260da2e3ebdSchin #endif
2261da2e3ebdSchin 							for (s--; b < s; *b++ = ' ');
2262da2e3ebdSchin 							goto magic;
2263da2e3ebdSchin 						}
2264da2e3ebdSchin 					}
2265da2e3ebdSchin 				pragma = -1;
2266da2e3ebdSchin 			}
2267da2e3ebdSchin 		}
2268da2e3ebdSchin 		else if (*s == '/' && !strncmp(s, MAGICGEN, sizeof(MAGICGEN) - 1))
2269da2e3ebdSchin 		{
2270da2e3ebdSchin 			pragma = 0;
2271da2e3ebdSchin 			break;
2272da2e3ebdSchin 		}
2273da2e3ebdSchin #if PROTOMAIN
2274da2e3ebdSchin 		else if (*s == '%' && *(s + 1) == '{')
2275da2e3ebdSchin 			proto->flags |= YACC;
2276da2e3ebdSchin 		if (notice || options)
2277da2e3ebdSchin 		{
2278da2e3ebdSchin 			if (*s == *com && !strncmp(s, com, comlen))
2279da2e3ebdSchin 				notice = options = 0;
2280da2e3ebdSchin 			else
2281da2e3ebdSchin 				while (*s)
2282da2e3ebdSchin 				{
2283da2e3ebdSchin 					if (*s == *NOTICED && !strncmp(s, NOTICED, sizeof(NOTICED) - 1))
2284da2e3ebdSchin 					{
2285da2e3ebdSchin 						s += sizeof(NOTICED) - 1;
2286da2e3ebdSchin 						while (*s == ' ' || *s == '\t')
2287da2e3ebdSchin 							s++;
2288da2e3ebdSchin 						if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
2289da2e3ebdSchin 						{
2290da2e3ebdSchin 							notice = options = 0;
2291da2e3ebdSchin 							break;
2292da2e3ebdSchin 						}
2293da2e3ebdSchin 					}
22947c2fbfb3SApril Chin 					if (*s == *PUBLICDOMAIN && !strncmp(s, PUBLICDOMAIN, sizeof(PUBLICDOMAIN) - 1))
22957c2fbfb3SApril Chin 					{
22967c2fbfb3SApril Chin 						notice = options = 0;
22977c2fbfb3SApril Chin 						break;
22987c2fbfb3SApril Chin 					}
2299da2e3ebdSchin 					else if (*s++ == '\n')
2300da2e3ebdSchin 					{
2301da2e3ebdSchin 						s--;
2302da2e3ebdSchin 						break;
2303da2e3ebdSchin 					}
2304da2e3ebdSchin 				}
2305da2e3ebdSchin 		}
2306da2e3ebdSchin #endif
2307da2e3ebdSchin 		while (*s && *s++ != '\n');
2308da2e3ebdSchin 	}
2309da2e3ebdSchin  magic:
2310da2e3ebdSchin 	if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS;
2311da2e3ebdSchin 	if (flags & PROTO_TEST) proto->test = 1;
2312da2e3ebdSchin 	if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE;
2313da2e3ebdSchin #if PROTOMAIN
2314da2e3ebdSchin 	if (flags & PROTO_CLASSIC) pragma = -pragma;
2315da2e3ebdSchin 	if (flags & PROTO_DISABLE) pragma = 0;
2316da2e3ebdSchin 	if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC;
2317da2e3ebdSchin 	if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.')
2318da2e3ebdSchin 		proto->flags |= YACC;
2319da2e3ebdSchin #endif
2320da2e3ebdSchin 	if (pragma <= 0)
2321da2e3ebdSchin 	{
2322da2e3ebdSchin 		if (flags & PROTO_PLUSPLUS)
2323da2e3ebdSchin 		{
2324da2e3ebdSchin 			flags &= ~(PROTO_HEADER|PROTO_INCLUDE);
2325da2e3ebdSchin 			proto->flags |= PLUSONLY;
2326da2e3ebdSchin 		}
2327da2e3ebdSchin 		else if (!(flags & (PROTO_FORCE|PROTO_PASS)))
2328da2e3ebdSchin 		{
2329da2e3ebdSchin 			pppclose(iob);
2330da2e3ebdSchin 			return 0;
2331da2e3ebdSchin 		}
2332da2e3ebdSchin 		else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma)
2333da2e3ebdSchin 		{
2334da2e3ebdSchin 			proto->flags |= PASS;
2335da2e3ebdSchin 			if (proto->flags & MORE)
2336da2e3ebdSchin 				proto->oz += proto->iz;
2337da2e3ebdSchin 			proto->iz = n;
2338da2e3ebdSchin 			if (notice || options)
2339da2e3ebdSchin 			{
2340da2e3ebdSchin 				if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
2341da2e3ebdSchin 				{
2342da2e3ebdSchin 					s = proto->ip;
2343da2e3ebdSchin 					while (*s && *s++ != '\n');
2344da2e3ebdSchin 					m = s - proto->ip;
2345da2e3ebdSchin 					proto->op = memcopy(proto->op, proto->ip, m);
2346da2e3ebdSchin 					proto->ip = s;
2347da2e3ebdSchin 					proto->iz = n -= m;
2348da2e3ebdSchin 				}
2349da2e3ebdSchin #if PROTOMAIN
2350da2e3ebdSchin 				if (proto->cc[0])
2351da2e3ebdSchin 				{
2352da2e3ebdSchin 					if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2353da2e3ebdSchin 						proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
2354da2e3ebdSchin 					else
2355da2e3ebdSchin 						proto->op += comlen;
2356da2e3ebdSchin 				}
2357da2e3ebdSchin 				if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC))
2358da2e3ebdSchin #endif
2359da2e3ebdSchin 				proto->op = linesync(proto, proto->op, 1);
2360da2e3ebdSchin 				proto->iz += proto->op - proto->ob;
2361da2e3ebdSchin 			}
2362da2e3ebdSchin 			memcopy(proto->op, proto->ip, n);
2363da2e3ebdSchin 			return iob;
2364da2e3ebdSchin 		}
2365da2e3ebdSchin 	}
2366da2e3ebdSchin #if PROTOMAIN
2367da2e3ebdSchin 	if (!(retain & PROTO_INITIALIZED))
2368da2e3ebdSchin 	{
2369da2e3ebdSchin 		retain |= PROTO_INITIALIZED;
2370da2e3ebdSchin 		ppfsm(FSM_INIT, NiL);
2371da2e3ebdSchin 	}
2372da2e3ebdSchin #endif
2373da2e3ebdSchin 	proto->line = 1;
2374da2e3ebdSchin #if CHUNK >= 512
2375da2e3ebdSchin 	if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE)))
2376da2e3ebdSchin 	{
2377da2e3ebdSchin #if PROTOMAIN
2378da2e3ebdSchin 		if (notice || options)
2379da2e3ebdSchin 		{
2380da2e3ebdSchin 			if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2381da2e3ebdSchin 				proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
2382da2e3ebdSchin 			else
2383da2e3ebdSchin 				proto->op += comlen;
2384da2e3ebdSchin 		}
2385da2e3ebdSchin #endif
2386da2e3ebdSchin 		if (flags & PROTO_INCLUDE)
2387da2e3ebdSchin 		{
2388da2e3ebdSchin 			proto->flags |= INIT_INCLUDE;
2389da2e3ebdSchin 			if (flags & PROTO_RETAIN)
2390da2e3ebdSchin 				retain |= PROTO_INCLUDE;
2391da2e3ebdSchin 		}
2392da2e3ebdSchin 		else if (flags & PROTO_HEADER)
2393da2e3ebdSchin 		{
2394da2e3ebdSchin 			if (flags & PROTO_RETAIN) retain |= PROTO_HEADER;
2395da2e3ebdSchin #if PROTOMAIN
2396da2e3ebdSchin 			if (flags & PROTO_CLASSIC)
2397da2e3ebdSchin 			{
2398da2e3ebdSchin 				*proto->op++ = '#';
2399da2e3ebdSchin 				proto->op = strcopy(proto->op, MAGICDIR);
2400da2e3ebdSchin 				*proto->op++ = ' ';
2401da2e3ebdSchin 				proto->op = strcopy(proto->op, MAGICARG);
2402da2e3ebdSchin 				*proto->op++ = '\n';
2403da2e3ebdSchin 			}
2404da2e3ebdSchin 			else
2405da2e3ebdSchin #endif
2406da2e3ebdSchin 			proto->flags |= INIT_DEFINE;
2407da2e3ebdSchin 		}
2408da2e3ebdSchin #if PROTOMAIN
2409da2e3ebdSchin 		if (!(flags & PROTO_CLASSIC))
2410da2e3ebdSchin 		{
2411da2e3ebdSchin 			if (proto->flags & YACC)
2412da2e3ebdSchin 			{
2413da2e3ebdSchin 				proto->op = strcopy(proto->op, "\n%{\n" + !notice);
2414da2e3ebdSchin 				proto->op = strcopy(proto->op, MAGICGEN);
2415da2e3ebdSchin 				proto->op = strcopy(proto->op, "%}\n");
2416da2e3ebdSchin 			}
2417da2e3ebdSchin 			else
2418da2e3ebdSchin 			{
2419da2e3ebdSchin 				if (n || notice || options)
2420da2e3ebdSchin 					*proto->op++ = '\n';
2421da2e3ebdSchin 				proto->op = strcopy(proto->op, MAGICGEN);
2422da2e3ebdSchin 				if (n)
2423da2e3ebdSchin 					proto->op = linesync(proto, proto->op, proto->line);
2424da2e3ebdSchin 				else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE))
2425da2e3ebdSchin 					proto->op = init(proto, proto->op, proto->flags);
2426da2e3ebdSchin 			}
2427da2e3ebdSchin 		}
2428da2e3ebdSchin #endif
2429da2e3ebdSchin 	}
2430da2e3ebdSchin #endif
2431da2e3ebdSchin #if PROTOMAIN
2432da2e3ebdSchin 	proto->file = file;
2433da2e3ebdSchin 	if (flags & PROTO_CLASSIC)
2434da2e3ebdSchin 	{
2435da2e3ebdSchin 		proto->flags |= CLASSIC;
2436da2e3ebdSchin 		if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN;
2437da2e3ebdSchin 	}
2438da2e3ebdSchin #endif
2439da2e3ebdSchin 	return iob;
2440da2e3ebdSchin }
2441da2e3ebdSchin 
2442da2e3ebdSchin /*
2443da2e3ebdSchin  * read next proto'd chunk into iob
2444da2e3ebdSchin  * the chunk is 0 terminated and its size is returned
2445da2e3ebdSchin  */
2446da2e3ebdSchin 
2447da2e3ebdSchin int
pppread(char * iob)2448da2e3ebdSchin pppread(char* iob)
2449da2e3ebdSchin {
2450da2e3ebdSchin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
2451da2e3ebdSchin 	register int		n;
2452da2e3ebdSchin 
2453da2e3ebdSchin 	if (proto->flags & PASS)
2454da2e3ebdSchin 	{
2455da2e3ebdSchin 		if (proto->iz)
2456da2e3ebdSchin 		{
2457da2e3ebdSchin 			n = proto->iz;
2458da2e3ebdSchin 			proto->iz = 0;
2459da2e3ebdSchin 		}
2460da2e3ebdSchin 		else if (!(proto->flags & MORE)) n = 0;
2461da2e3ebdSchin 		else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz)
2462da2e3ebdSchin 		{
2463da2e3ebdSchin 			proto->flags &= ~MORE;
2464da2e3ebdSchin 			close(proto->fd);
2465da2e3ebdSchin 		}
2466da2e3ebdSchin 	}
2467da2e3ebdSchin 	else
2468da2e3ebdSchin 	{
2469da2e3ebdSchin 		if (proto->op == proto->ob)
2470da2e3ebdSchin 		{
2471da2e3ebdSchin 			if (proto->flags & ERROR) return -1;
2472da2e3ebdSchin #if PROTOMAIN
2473da2e3ebdSchin 			if (proto->flags & YACC)
2474da2e3ebdSchin 			{
2475da2e3ebdSchin 				register char*	ip = proto->ip;
2476da2e3ebdSchin 				register char*	op = proto->ob;
2477da2e3ebdSchin 				register char*	ep = proto->ob + proto->oz - 2;
2478da2e3ebdSchin 
2479da2e3ebdSchin 				if (!*ip)
2480da2e3ebdSchin 				{
2481da2e3ebdSchin 					ip = proto->ip = proto->ib;
2482da2e3ebdSchin 					if (!(proto->flags & MORE)) n = 0;
2483da2e3ebdSchin 					else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz)
2484da2e3ebdSchin 					{
2485da2e3ebdSchin 						if (n < 0) n = 0;
2486da2e3ebdSchin 						proto->flags &= ~MORE;
2487da2e3ebdSchin 						close(proto->fd);
2488da2e3ebdSchin 					}
2489da2e3ebdSchin 					ip[n] = 0;
2490da2e3ebdSchin 				}
2491da2e3ebdSchin 				if (proto->flags & YACCSPLIT)
2492da2e3ebdSchin 				{
2493da2e3ebdSchin 					proto->flags &= ~YACCSPLIT;
2494da2e3ebdSchin 					if (*ip == '%')
2495da2e3ebdSchin 					{
2496da2e3ebdSchin 						*op++ = *ip++;
2497da2e3ebdSchin 						if (proto->flags & YACC2) proto->flags &= ~YACC;
2498da2e3ebdSchin 						else proto->flags |= YACC2;
2499da2e3ebdSchin 					}
2500da2e3ebdSchin 				}
2501da2e3ebdSchin 				if (proto->flags & YACC)
2502da2e3ebdSchin 					while (op < ep && (n = *op++ = *ip))
2503da2e3ebdSchin 					{
2504da2e3ebdSchin 						ip++;
2505da2e3ebdSchin 						if (n == '%')
2506da2e3ebdSchin 						{
2507da2e3ebdSchin 							if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
2508da2e3ebdSchin 							{
2509da2e3ebdSchin 								*op++ = *ip++;
2510da2e3ebdSchin 								if (proto->flags & YACC2) proto->flags &= ~YACC;
2511da2e3ebdSchin 								else proto->flags |= YACC2;
2512da2e3ebdSchin 								break;
2513da2e3ebdSchin 							}
2514da2e3ebdSchin 							if (!*ip)
2515da2e3ebdSchin 							{
2516da2e3ebdSchin 								*op++ = '%';
2517da2e3ebdSchin 								proto->flags |= YACCSPLIT;
2518da2e3ebdSchin 								break;
2519da2e3ebdSchin 							}
2520da2e3ebdSchin 						}
2521da2e3ebdSchin 						else if (n == '\n') proto->line++;
2522da2e3ebdSchin 					}
2523da2e3ebdSchin 				proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
2524da2e3ebdSchin 				proto->ip = ip;
2525da2e3ebdSchin 			}
2526da2e3ebdSchin 			else
2527da2e3ebdSchin #endif
2528da2e3ebdSchin 			lex(proto, proto->flags);
2529da2e3ebdSchin 			if ((proto->flags & (ERROR|MORE)) == ERROR)
2530da2e3ebdSchin 				proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
2531da2e3ebdSchin 		}
2532da2e3ebdSchin 		n = proto->op - proto->ob;
2533da2e3ebdSchin 		proto->op = proto->ob;
2534da2e3ebdSchin 	}
2535da2e3ebdSchin 	return n;
2536da2e3ebdSchin }
2537da2e3ebdSchin 
2538da2e3ebdSchin #if !PROTOMAIN
2539da2e3ebdSchin 
2540da2e3ebdSchin /*
2541da2e3ebdSchin  * drop control of iob after first pppread()
2542da2e3ebdSchin  * return value is input fd
2543da2e3ebdSchin  * if fd<0 then all data in iob
2544da2e3ebdSchin  */
2545da2e3ebdSchin 
2546da2e3ebdSchin int
pppdrop(char * iob)2547da2e3ebdSchin pppdrop(char* iob)
2548da2e3ebdSchin {
2549da2e3ebdSchin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
2550da2e3ebdSchin 
2551da2e3ebdSchin 	if (proto->flags & MORE)
2552da2e3ebdSchin 	{
2553da2e3ebdSchin 		proto->flags &= ~MORE;
2554da2e3ebdSchin 		return proto->fd;
2555da2e3ebdSchin 	}
2556da2e3ebdSchin 	return -1;
2557da2e3ebdSchin }
2558da2e3ebdSchin 
2559da2e3ebdSchin #endif
2560