xref: /onnv-gate/usr/src/lib/libpp/common/ppproto.c (revision 10898:1883b621b3ea)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*10898Sroland.mainz@nrubsig.org *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * Glenn Fowler
234887Schin  * AT&T Research
244887Schin  *
254887Schin  * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
264887Schin  * slips into the pp block read
274887Schin  *
284887Schin  * define PROTOMAIN for standalone proto
294887Schin  * PROTOMAIN is coded for minimal library support
304887Schin  */
314887Schin 
328462SApril.Chin@Sun.COM static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2008-05-11 $\0\n";
334887Schin 
344887Schin #if PROTOMAIN
354887Schin 
364887Schin #include "ppfsm.c"
374887Schin 
384887Schin #include <hashkey.h>
394887Schin 
404887Schin #if PROTO_STANDALONE
414887Schin #undef	O_RDONLY
424887Schin #endif
434887Schin 
444887Schin #else
454887Schin 
464887Schin #include "pplib.h"
474887Schin #include "ppfsm.h"
484887Schin 
494887Schin #endif
504887Schin 
514887Schin #define MAGICGEN	"/* : : generated by proto : : */\n"
524887Schin 
534887Schin #define MAGICDIR	"pragma"	/* proto magic directive	*/
544887Schin #define MAGICARG	"prototyped"	/* proto magic directive arg	*/
554887Schin #define MAGICOFF	"noticed"	/* no notice if found in pragma	*/
564887Schin #define MAGICTOP	64		/* must be in these top lines	*/
574887Schin #define NOTICED		"Copyright"	/* no notice if found in magic	*/
588462SApril.Chin@Sun.COM #define PUBLICDOMAIN	"Public Domain"	/* no notice if found in magic	*/
594887Schin 
604887Schin struct proto				/* proto buffer state		*/
614887Schin {
624887Schin 	int		brace;		/* {..} level			*/
634887Schin 	int		call;		/* call level			*/
644887Schin 	int		fd;		/* input file descriptor	*/
654887Schin 	char*		file;		/* input file name		*/
664887Schin 	long		flags;		/* coupled flags		*/
674887Schin 	long		options;	/* uncoupled flags		*/
684887Schin 	char*		package;	/* header package		*/
694887Schin 	int		line;		/* input line count		*/
704887Schin 	int		test;		/* testing			*/
714887Schin 
724887Schin 	char*		tp;		/* input token base		*/
734887Schin 
744887Schin 	int		iz;		/* input buffer size		*/
754887Schin 	char*		ib;		/* input buffer base		*/
764887Schin 	char*		ip;		/* input buffer pointer		*/
774887Schin 
784887Schin 	int		oz;		/* output buffer size		*/
794887Schin 	char*		ob;		/* output buffer base		*/
804887Schin 	char*		op;		/* output buffer pointer	*/
814887Schin 	char*		ox;		/* output buffer externalize	*/
824887Schin 
834887Schin 	char		cc[3];		/* beg mid end comment char	*/
844887Schin 	char		pushback[4];	/* pushback area for caller	*/
854887Schin 
864887Schin 	char		variadic[256];	/* variadic args buffer		*/
874887Schin 
884887Schin 	/* output buffer */
894887Schin 	/* slide buffer */
904887Schin 	/* input buffer */
914887Schin };
924887Schin 
934887Schin /*
944887Schin  * proto is separate from pp so these undef's are ok
954887Schin  */
964887Schin 
974887Schin #undef	CLASSIC
984887Schin #define CLASSIC		(1L<<0)
994887Schin #undef	DECLARE
1004887Schin #define DECLARE		(1L<<1)
1014887Schin #undef	DEFINE
1024887Schin #define DEFINE		(1L<<2)
1034887Schin #undef	DIRECTIVE
1044887Schin #define DIRECTIVE	(1L<<3)
1054887Schin #undef	ERROR
1064887Schin #define ERROR		(1L<<4)
1074887Schin #undef	EXTERN
1084887Schin #define EXTERN		(1L<<5)
1094887Schin #undef	EXTERNALIZE
1104887Schin #define EXTERNALIZE	(1L<<6)
1114887Schin #undef	IDID
1124887Schin #define IDID		(1L<<7)
1134887Schin #undef	INDIRECT
1144887Schin #define INDIRECT	(1L<<8)
1154887Schin #undef	INIT
1164887Schin #define INIT		(1L<<9)
1174887Schin #undef	INIT_DEFINE
1184887Schin #define INIT_DEFINE	(1L<<10)
1194887Schin #undef	INIT_INCLUDE
1204887Schin #define INIT_INCLUDE	(1L<<11)
1214887Schin #undef	JUNK
1224887Schin #define JUNK		(1L<<12)
1234887Schin #undef	LINESYNC
1244887Schin #define LINESYNC	(1L<<13)
1254887Schin #undef	MANGLE
1264887Schin #define MANGLE		(1L<<14)
1274887Schin #undef	MATCH
1284887Schin #define MATCH		(1L<<15)
1294887Schin #undef	MORE
1304887Schin #define MORE		(1L<<16)
1314887Schin #undef	OTHER
1324887Schin #define OTHER		(1L<<17)
1334887Schin #undef	PASS
1344887Schin #define PASS		(1L<<18)
1354887Schin #undef	PLUSONLY
1364887Schin #define PLUSONLY	(1L<<19)
1374887Schin #undef	PLUSPLUS
1384887Schin #define PLUSPLUS	(1L<<20)
1394887Schin #undef	RECURSIVE
1404887Schin #define RECURSIVE	(1L<<21)
1414887Schin #undef	SHARP
1424887Schin #define SHARP		(1L<<22)
1434887Schin #undef	SKIP
1444887Schin #define SKIP		(1L<<23)
1454887Schin #undef	SLIDE
1464887Schin #define SLIDE		(1L<<24)
1474887Schin #undef	TOKENS
1484887Schin #define TOKENS		(1L<<25)
1494887Schin #undef	TYPEDEF
1504887Schin #define TYPEDEF		(1L<<26)
1514887Schin #undef	VARIADIC
1524887Schin #define VARIADIC	(1L<<27)
1534887Schin #undef	VARIADIC2
1544887Schin #define VARIADIC2	(1L<<28)
1554887Schin #undef	YACC
1564887Schin #define YACC		(1L<<29)
1574887Schin #undef	YACCSPLIT
1584887Schin #define YACCSPLIT	(1L<<30)
1594887Schin #undef	YACC2
1604887Schin #define YACC2		(1L<<31)
1614887Schin 
1624887Schin #undef	GLOBAL
1634887Schin #define GLOBAL		(MORE)
1644887Schin 
1654887Schin #undef	REGULAR
1664887Schin #define REGULAR		(1L<<0)
1674887Schin 
1684887Schin #ifndef CHUNK
1694887Schin #define CHUNK		1024
1704887Schin #endif
1714887Schin #define BLOCK		(8*CHUNK)
1724887Schin 
1734887Schin #define T_VA_START	(N_TOKEN+1)
1744887Schin 
1754887Schin #define RESERVED(b,e,n)	((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
1764887Schin 
1774887Schin /*
1784887Schin  * generate integer
1794887Schin  * pointer to end returned
1804887Schin  */
1814887Schin 
1824887Schin static char*
number(register char * p,register long n)1834887Schin number(register char* p, register long n)
1844887Schin {
1854887Schin 	register long	d;
1864887Schin 
1874887Schin 	for (d = 1000000; d > 1; d /= 10)
1884887Schin 		if (n >= d) *p++ = '0' + (n / d) % 10;
1894887Schin 	*p++ = '0' + n % 10;
1904887Schin 	return p;
1914887Schin }
1924887Schin 
1934887Schin #if PROTOMAIN
1944887Schin 
1954887Schin static int		errors;
1964887Schin 
1974887Schin #if PROTO_STANDALONE
1984887Schin 
1994887Schin /*
2004887Schin  * namespace pollution forces us to claim parts of libc
2014887Schin  */
2024887Schin 
2034887Schin #undef	memcpy
2044887Schin #define memcpy(t,f,n)	memcopy(t,f,n)
2054887Schin #undef	strcpy
2064887Schin #define strcpy(t,f)	strcopy(t,f)
2074887Schin #undef	strlen
2084887Schin #define strlen(s)	sstrlen(s)
2094887Schin #undef	strncmp
2104887Schin #define strncmp(s,t,n)	sstrncmp(s,t,n)
2114887Schin 
2124887Schin /*
2134887Schin  * environmentally safe strlen()
2144887Schin  */
2154887Schin 
2164887Schin static int
sstrlen(register const char * s)2174887Schin sstrlen(register const char* s)
2184887Schin {
2194887Schin 	register const char*	b;
2204887Schin 
2214887Schin 	for (b = s; *s; s++);
2224887Schin 	return s - b;
2234887Schin }
2244887Schin 
2254887Schin /*
2264887Schin  * environmentally safe strncmp()
2274887Schin  */
2284887Schin 
2294887Schin static int
sstrncmp(register const char * s,register char * t,register int n)2304887Schin sstrncmp(register const char* s, register char* t, register int n)
2314887Schin {
2324887Schin 	register const char*	e = s + n;
2334887Schin 
2344887Schin 	while (s < e)
2354887Schin 	{
2364887Schin 		if (*s != *t || !*s)
2374887Schin 			return *s - *t;
2384887Schin 		s++;
2394887Schin 		t++;
2404887Schin 	}
2414887Schin 	return 0;
2424887Schin }
2434887Schin 
2444887Schin /*
2454887Schin  * strcpy() except pointer to end returned
2464887Schin  */
2474887Schin 
2484887Schin static char*
strcopy(register char * s,register const char * t)2494887Schin strcopy(register char* s, register const char* t)
2504887Schin {
2514887Schin 	while (*s++ = *t++);
2524887Schin 	return s - 1;
2534887Schin }
2544887Schin 
2554887Schin #endif
2564887Schin 
2574887Schin static void
proto_error(char * iob,int level,char * msg,char * arg)2584887Schin proto_error(char* iob, int level, char* msg, char* arg)
2594887Schin {
2604887Schin 	register char*	p;
2614887Schin 	char		buf[1024];
2624887Schin 
2634887Schin 	p = strcopy(buf, "proto: ");
2644887Schin 	if (iob)
2654887Schin 	{
2664887Schin 		register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
2674887Schin 
2684887Schin 		if (proto->line)
2694887Schin 		{
2704887Schin 			if (proto->file)
2714887Schin 			{
2724887Schin 				*p++ = '"';
2734887Schin 				p = strcopy(p, proto->file);
2744887Schin 				*p++ = '"';
2754887Schin 				*p++ = ',';
2764887Schin 				*p++ = ' ';
2774887Schin 			}
2784887Schin 			p = strcopy(p, "line ");
2794887Schin 			p = number(p, proto->line);
2804887Schin 		}
2814887Schin 		else if (proto->file)
2824887Schin 			p = strcopy(p, proto->file);
2834887Schin 	}
2844887Schin 	else
2854887Schin 	{
2864887Schin 		p = strcopy(p, msg);
2874887Schin 		msg = arg;
2884887Schin 		arg = 0;
2894887Schin 	}
2904887Schin 	if (*(p - 1) != ' ')
2914887Schin 	{
2924887Schin 		*p++ = ':';
2934887Schin 		*p++ = ' ';
2944887Schin 	}
2954887Schin 	if (level == 1)
2964887Schin 		p = strcopy(p, "warning: ");
2974887Schin 	p = strcopy(p, msg);
2984887Schin 	if (arg)
2994887Schin 	{
3004887Schin 		*p++ = ' ';
3014887Schin 		p = strcopy(p, arg);
3024887Schin 	}
3034887Schin 	*p++ = '\n';
3044887Schin 	write(2, buf, p - buf);
3054887Schin 	if (level >= 3)
3064887Schin 		exit(level - 2);
3074887Schin 	if (level >= 2)
3084887Schin 		errors++;
3094887Schin }
3104887Schin 
3114887Schin /*
3124887Schin  * memcpy() but pointer to end returned
3134887Schin  */
3144887Schin 
3154887Schin static char*
memcopy(register char * s,register char * t,int n)3164887Schin memcopy(register char* s, register char* t, int n)
3174887Schin {
3184887Schin 	register char*	e = t + n;
3194887Schin 
3204887Schin 	while (t < e) *s++ = *t++;
3214887Schin 	return s;
3224887Schin }
3234887Schin 
3244887Schin #include "../libast/port/astlicense.c"
3254887Schin 
3264887Schin #else
3274887Schin 
3284887Schin #define memcopy(s,t,n)	(((char*)memcpy(s,t,n))+(n))
3294887Schin 
3304887Schin #endif
3314887Schin 
3324887Schin /*
3334887Schin  * generate line sync
3344887Schin  * pointer to end returned
3354887Schin  */
3364887Schin 
3374887Schin static char*
linesync(register struct proto * proto,register char * p,register long n)3384887Schin linesync(register struct proto* proto, register char* p, register long n)
3394887Schin {
3404887Schin #if PROTOMAIN
3414887Schin 	if (proto->flags & LINESYNC)
3424887Schin #endif
3434887Schin 	{
3444887Schin #if PROTOMAIN
3454887Schin 		p = strcopy(p, "\n#line ");
3464887Schin #else
3474887Schin 		p = strcopy(p, "\n# ");
3484887Schin #endif
3494887Schin 		p = number(p, n);
3504887Schin 		*p++ = '\n';
3514887Schin 	}
3524887Schin 	return p;
3534887Schin }
3544887Schin 
3554887Schin /*
3564887Schin  * output init header
3574887Schin  * pointer to end returned
3584887Schin  */
3594887Schin 
3604887Schin static char*
init(struct proto * proto,char * op,int flags)3614887Schin init(struct proto* proto, char* op, int flags)
3624887Schin {
3634887Schin 	register char*	s;
3644887Schin 
3654887Schin 	if (flags & INIT_DEFINE)
3664887Schin 	{
3674887Schin 		op = strcopy(op, "\
3684887Schin \n\
3694887Schin #if !defined(__PROTO__)\n\
3704887Schin #  if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
3714887Schin #    if defined(__cplusplus)\n\
3724887Schin #      define __LINKAGE__	\"C\"\n\
3734887Schin #    else\n\
3744887Schin #      define __LINKAGE__\n\
3754887Schin #    endif\n\
3764887Schin #    define __STDARG__\n\
3774887Schin #    define __PROTO__(x)	x\n\
3784887Schin #    define __OTORP__(x)\n\
3794887Schin #    define __PARAM__(n,o)	n\n\
3804887Schin #    if !defined(__STDC__) && !defined(__cplusplus)\n\
3814887Schin #      if !defined(c_plusplus)\n\
3824887Schin #      	define const\n\
3834887Schin #      endif\n\
3844887Schin #      define signed\n\
3854887Schin #      define void		int\n\
3864887Schin #      define volatile\n\
3874887Schin #      define __V_		char\n\
3884887Schin #    else\n\
3894887Schin #      define __V_		void\n\
3904887Schin #    endif\n\
3914887Schin #  else\n\
3924887Schin #    define __PROTO__(x)	()\n\
3934887Schin #    define __OTORP__(x)	x\n\
3944887Schin #    define __PARAM__(n,o)	o\n\
3954887Schin #    define __LINKAGE__\n\
3964887Schin #    define __V_		char\n\
3974887Schin #    define const\n\
3984887Schin #    define signed\n\
3994887Schin #    define void		int\n\
4004887Schin #    define volatile\n\
4014887Schin #  endif\n\
4024887Schin #  define __MANGLE__	__LINKAGE__\n\
4034887Schin #  if defined(__cplusplus) || defined(c_plusplus)\n\
4044887Schin #    define __VARARG__	...\n\
4054887Schin #  else\n\
4064887Schin #    define __VARARG__\n\
4074887Schin #  endif\n\
4084887Schin #  if defined(__STDARG__)\n\
4094887Schin #    define __VA_START__(p,a)	va_start(p,a)\n\
4104887Schin #  else\n\
4114887Schin #    define __VA_START__(p,a)	va_start(p)\n\
4124887Schin #  endif\n\
4134887Schin #  if !defined(__INLINE__)\n\
4144887Schin #    if defined(__cplusplus)\n\
4154887Schin #      define __INLINE__	extern __MANGLE__ inline\n\
4164887Schin #    else\n\
4174887Schin #      if defined(_WIN32) && !defined(__GNUC__)\n\
4184887Schin #      	define __INLINE__	__inline\n\
4194887Schin #      endif\n\
4204887Schin #    endif\n\
4214887Schin #  endif\n\
4224887Schin #endif\n\
4234887Schin #if !defined(__LINKAGE__)\n\
4244887Schin #define __LINKAGE__		/* 2004-08-11 transition */\n\
4254887Schin #endif\n\
4264887Schin ");
4274887Schin 	}
4284887Schin 	else
4294887Schin 		op = strcopy(op, "\
4304887Schin \n\
4314887Schin #if !defined(__PROTO__)\n\
4324887Schin #include <prototyped.h>\n\
4334887Schin #endif\n\
4344887Schin #if !defined(__LINKAGE__)\n\
4354887Schin #define __LINKAGE__		/* 2004-08-11 transition */\n\
4364887Schin #endif\n\
4374887Schin ");
4384887Schin 	if (proto->package)
4394887Schin 	{
4404887Schin 		s = "\
4414887Schin #ifndef	__MANGLE_%_DATA__\n\
4424887Schin #  ifdef _BLD_%\n\
4434887Schin #    ifdef __EXPORT__\n\
4444887Schin #      define	__MANGLE_%_DATA__	__MANGLE__ __EXPORT__\n\
4454887Schin #    else\n\
4464887Schin #      define	__MANGLE_%_DATA__	__MANGLE__\n\
4474887Schin #    endif\n\
4484887Schin #    define	__MANGLE_%_FUNC__	__MANGLE__\n\
4494887Schin #  else\n\
4504887Schin #    ifdef __IMPORT__\n\
4514887Schin #      define	__MANGLE_%_DATA__	__MANGLE__ __IMPORT__\n\
4524887Schin #    else\n\
4534887Schin #      define	__MANGLE_%_DATA__	__MANGLE__\n\
4544887Schin #    endif\n\
4554887Schin #    define	__MANGLE_%_FUNC__	__MANGLE__\n\
4564887Schin #  endif\n\
4574887Schin #endif\n\
4584887Schin ";
4594887Schin 		for (;;)
4604887Schin 		{
4614887Schin 			switch (*op++ = *s++)
4624887Schin 			{
4634887Schin 			case 0:
4644887Schin 				op--;
4654887Schin 				break;
4664887Schin 			case '%':
4674887Schin 				op = strcopy(op - 1, proto->package);
4684887Schin 				continue;
4694887Schin 			default:
4704887Schin 				continue;
4714887Schin 			}
4724887Schin 			break;
4734887Schin 		}
4744887Schin 	}
4754887Schin 	return op;
4764887Schin }
4774887Schin 
4784887Schin #define BACKOUT()	(op=ko)
4794887Schin #define CACHE()		do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
4804887Schin #define CACHEIN()	(ip=proto->ip)
4814887Schin #define CACHEOUT()	(op=proto->op)
4824887Schin #define GETCHR()	(*(unsigned char*)ip++)
4834887Schin #define KEEPOUT()	(ko=op)
4844887Schin #define LASTOUT()	(*(op-1))
4854887Schin #define PUTCHR(c)	(*op++=(c))
4864887Schin #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)
4874887Schin #define SYNCIN()	(proto->ip=ip)
4884887Schin #define SYNCOUT()	(proto->op=op)
4894887Schin #define UNGETCHR()	(ip--)
4904887Schin #define UNPUTCHR()	(op--)
4914887Schin 
4924887Schin /*
4934887Schin  * advance to the next non-space character
4944887Schin  */
4954887Schin 
4964887Schin static char*
nns(register char * s)4974887Schin nns(register char* s)
4984887Schin {
4994887Schin 	while (*s == ' ' || *s == '\t' || *s == '\n')
5004887Schin 		s++;
5014887Schin 	return s;
5024887Schin }
5034887Schin 
5044887Schin #define DIR_if	01
5054887Schin #define DIR_el	02
5064887Schin #define DIR_en	03
5074887Schin #define DIR	03
5084887Schin 
5094887Schin /*
5104887Schin  * update directive mask
5114887Schin  */
5124887Schin 
5134887Schin static int
directive(register char * s,int dir)5144887Schin directive(register char* s, int dir)
5154887Schin {
5164887Schin 	switch (*(s = nns(s)))
5174887Schin 	{
5184887Schin 	case 'e':
5194887Schin 	case 'i':
5204887Schin 		dir <<= 2;
5214887Schin 		switch (*++s)
5224887Schin 		{
5234887Schin 		case 'f':
5244887Schin 			dir |= DIR_if;
5254887Schin 			break;
5264887Schin 		case 'l':
5274887Schin 			dir |= DIR_el;
5284887Schin 			break;
5294887Schin 		case 'n':
5304887Schin 			dir |= DIR_en;
5314887Schin 			break;
5324887Schin 		}
5334887Schin 		break;
5344887Schin 	}
5354887Schin 	return dir;
5364887Schin }
5374887Schin 
5384887Schin /*
5394887Schin  * the tokenizer
5404887Schin  * top level calls loop until EOB
5414887Schin  * recursive calls just return the next token
5424887Schin  */
5434887Schin 
5444887Schin static int
lex(register struct proto * proto,register long flags)5454887Schin lex(register struct proto* proto, register long flags)
5464887Schin {
5474887Schin 	register char*		ip;
5484887Schin 	register char*		op;
5494887Schin 	register int		c;
5504887Schin 	register int		state;
5514887Schin 	register short*		rp;
5524887Schin 	char*			m;
5534887Schin 	char*			e;
5544887Schin 	char*			t;
5554887Schin 	char*			bp;
5564887Schin 	char*			v;
5574887Schin 	char*			im;
5584887Schin 	char*			ko;
5594887Schin 	char*			aom;
5604887Schin 	int			n;
5614887Schin 	int			line;
5624887Schin 	int			quot;
5634887Schin 	int			brack;
5644887Schin 	int			sub;
5654887Schin 	int			x;
5664887Schin 	int			vc;
5674887Schin 
5684887Schin 	char*			ie = 0;
5694887Schin 	char*			om = 0;
5704887Schin 	char*			aim = 0;
5714887Schin 	char*			aie = 0;
5724887Schin 	char*			func = 0;
5734887Schin 	int			call = 0;
5744887Schin 	int			dir = 0;
5754887Schin 	int			group = 0;
5764887Schin 	int			last = 0;
5774887Schin 	int			paren = 0;
5784887Schin #if PROTOMAIN
5794887Schin 	char*			qe = 0;
5804887Schin 	int			qn = 0;
5814887Schin 	int			args = 0;
5824887Schin #endif
5834887Schin 
5844887Schin 	CACHE();
5854887Schin #if PROTOMAIN
5864887Schin 	if (flags & EXTERN) KEEPOUT();
5874887Schin #endif
5884887Schin  fsm_start:
5894887Schin 	proto->tp = ip;
5904887Schin 	state = PROTO;
5914887Schin 	bp = ip;
5924887Schin 	do
5934887Schin 	{
5944887Schin 		rp = fsm[state];
5954887Schin  fsm_get:
5964887Schin 		while (!(state = rp[c = GETCHR()]));
5974887Schin  fsm_next:
5984887Schin 		;
5994887Schin 	} while (state > 0);
6004887Schin 	if ((n = ip - bp - 1) > 0)
6014887Schin 	{
6024887Schin 		ip = bp;
6034887Schin 		MEMCPY(op, ip, n);
6044887Schin 		ip++;
6054887Schin 	}
6064887Schin 	state = ~state;
6074887Schin  fsm_terminal:
6084887Schin 	switch (TERM(state))
6094887Schin 	{
6104887Schin 	case S_CHR:
6114887Schin 		if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
6124887Schin 		{
6134887Schin 		case '+':
6144887Schin 		case '-':
6154887Schin 		case '*':
6164887Schin 		case '&':
6174887Schin 			PUTCHR(' ');
6184887Schin 			break;
6194887Schin 		}
6204887Schin 		PUTCHR(c);
6214887Schin 		break;
6224887Schin 
6234887Schin 	case S_CHRB:
6244887Schin 		UNGETCHR();
6254887Schin 		c = LASTOUT();
6264887Schin 		break;
6274887Schin 
6284887Schin 	case S_COMMENT:
6294887Schin 		switch (c)
6304887Schin 		{
6314887Schin 		case '\n':
6324887Schin 			if (INCOMMENTXX(rp)) goto fsm_newline;
6334887Schin 			PUTCHR(c);
6344887Schin 			proto->line++;
6354887Schin 			rp = fsm[COM2];
6364887Schin 			break;
6374887Schin 		case '/':
6384887Schin #if PROTOMAIN
6394887Schin 			if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
6404887Schin 			else
6414887Schin #endif
6424887Schin 			PUTCHR(c);
6434887Schin 			if (INCOMMENTXX(rp))
6444887Schin 			{
6454887Schin 				rp = fsm[COM5];
6464887Schin 				break;
6474887Schin 			}
6484887Schin 			goto fsm_start;
6494887Schin 		case EOF:
6504887Schin 			break;
6514887Schin 		default:
6524887Schin #if PROTOMAIN
6534887Schin 			if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
6544887Schin 			else
6554887Schin #endif
6564887Schin 			PUTCHR(c);
6574887Schin 			rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
6584887Schin 			break;
6594887Schin 		}
6604887Schin 		bp = ip;
6614887Schin 		goto fsm_get;
6624887Schin 
6634887Schin 	case S_EOB:
6644887Schin 		if (c)
6654887Schin 		{
6664887Schin 			if (state = fsm[TERMINAL][INDEX(rp)+1])
6674887Schin 				goto fsm_terminal;
6684887Schin 			SYNC();
6694887Schin 			return 0;
6704887Schin 		}
6714887Schin 		UNGETCHR();
6724887Schin  fsm_eob:
6734887Schin 		if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE))
6744887Schin 		{
6754887Schin #if PROTOMAIN
6764887Schin 			if (!(flags & EXTERN)) /* XXX */
6774887Schin #endif
6784887Schin 			flags |= SLIDE;
6794887Schin 			c = ip - proto->ib;
6804887Schin 			if (!(flags & MATCH))
6814887Schin 				im = proto->tp;
6824887Schin 			if (ip > proto->ib)
6834887Schin 			{
6844887Schin 				n = ip - im;
6854887Schin 				if (ip - n < proto->ib)
6864887Schin 					proto->flags |= ERROR;
6874887Schin 				memcopy(proto->ib - n, ip - n, n);
6884887Schin 				ip = proto->ib;
6894887Schin 			}
6904887Schin 			proto->tp -= c;
6914887Schin 			if (flags & MATCH)
6924887Schin 			{
6934887Schin 				im -= c;
6944887Schin 				ie -= c;
6954887Schin 			}
6964887Schin 			if (aim)
6974887Schin 				aim -= c;
6984887Schin 			if (aie)
6994887Schin 				aie -= c;
7004887Schin 			if ((n = read(proto->fd, ip, proto->iz)) > 0)
7014887Schin 			{
7024887Schin 				if ((proto->options & REGULAR) && n < proto->iz)
7034887Schin 				{
7044887Schin 					proto->flags &= ~MORE;
7054887Schin 					close(proto->fd);
7064887Schin 				}
7074887Schin 				*(ip + n) = 0;
7084887Schin 				if (state & SPLICE)
7094887Schin 					goto fsm_splice;
7104887Schin 				bp = ip;
7114887Schin 				goto fsm_get;
7124887Schin 			}
7134887Schin 			*ip = 0;
7144887Schin 			proto->flags &= ~MORE;
7154887Schin 			close(proto->fd);
7164887Schin 		}
7174887Schin 		if (state & SPLICE)
7184887Schin 			goto fsm_splice;
7194887Schin 		/* NOTE: RECURSIVE lex() should really SLIDE too */
7204887Schin 		if (!(flags & RECURSIVE) && (state = rp[c = EOF]))
7214887Schin 		{
7224887Schin 			bp = ip;
7234887Schin 			goto fsm_next;
7244887Schin 		}
7254887Schin 		SYNC();
7264887Schin 		return 0;
7274887Schin 
7284887Schin 	case S_LITBEG:
7294887Schin 		quot = c;
7304887Schin #if PROTOMAIN
7314887Schin 		if (c == '"' && qe)
7324887Schin 		{
7334887Schin 			for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
7344887Schin 			if (t == op)
7354887Schin 			{
7364887Schin 				op = qe;
7374887Schin 				qe = 0;
7384887Schin 				qn = n;
7394887Schin 			}
7404887Schin 			else PUTCHR(c);
7414887Schin 		}
7424887Schin 		else
7434887Schin #endif
7444887Schin 		PUTCHR(c);
7454887Schin 		rp = fsm[LIT1];
7464887Schin 		bp = ip;
7474887Schin 		goto fsm_get;
7484887Schin 
7494887Schin 	case S_LITEND:
7504887Schin 		if (c == quot)
7514887Schin 		{
7524887Schin #if PROTOMAIN
7534887Schin 			if (!(flags & DIRECTIVE))
7544887Schin 				qe = (c == '"') ? op : (char*)0;
7554887Schin #endif
7564887Schin 			PUTCHR(c);
7574887Schin #if PROTOMAIN
7584887Schin 			while (qn > 0)
7594887Schin 			{
7604887Schin 				qn--;
7614887Schin 				PUTCHR('\n');
7624887Schin 			}
7634887Schin #endif
7644887Schin 		}
7654887Schin 		else if (c != '\n' && c != EOF)
7664887Schin 		{
7674887Schin 			PUTCHR(c);
7684887Schin 			bp = ip;
7694887Schin 			goto fsm_get;
7704887Schin 		}
7714887Schin 		else
7724887Schin 		{
7734887Schin #if PROTOMAIN
7744887Schin 			while (qn > 0)
7754887Schin 			{
7764887Schin 				qn--;
7774887Schin 				PUTCHR('\n');
7784887Schin 			}
7794887Schin #endif
7804887Schin 			UNGETCHR();
7814887Schin 		}
7824887Schin 		c = T_INVALID;
7834887Schin 		break;
7844887Schin 
7854887Schin 	case S_LITESC:
7864887Schin #if PROTOMAIN
7874887Schin 		if (flags & CLASSIC) PUTCHR(c);
7884887Schin 		else
7894887Schin #endif
7904887Schin 		switch (c)
7914887Schin 		{
7924887Schin 		case 'a':
7934887Schin 			n = CC_bel;
7944887Schin 			goto fsm_oct;
7954887Schin 		case 'E':
7964887Schin 			n = CC_esc;
7974887Schin 			goto fsm_oct;
7984887Schin 		case 'v':
7994887Schin 			n = CC_vt;
8004887Schin 			goto fsm_oct;
8014887Schin 		case 'x':
8024887Schin 			SYNC();
8034887Schin 			lex(proto, (flags & GLOBAL) | RECURSIVE);
8044887Schin 			for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c)
8054887Schin 			{
8064887Schin 			case '0': case '1': case '2': case '3':
8074887Schin 			case '4': case '5': case '6': case '7':
8084887Schin 			case '8': case '9':
8094887Schin 				n = (n << 4) + c - '0';
8104887Schin 				break;
8114887Schin 			case 'a': case 'b': case 'c': case 'd':
8124887Schin 			case 'e': case 'f':
8134887Schin 				n = (n << 4) + c - 'a' + 10;
8144887Schin 				break;
8154887Schin 			case 'A': case 'B': case 'C': case 'D':
8164887Schin 			case 'E': case 'F':
8174887Schin 				n = (n << 4) + c - 'A' + 10;
8184887Schin 				break;
8194887Schin 			default:
8204887Schin 				goto fsm_hex;
8214887Schin 			}
8224887Schin  fsm_hex:
8234887Schin 			UNGETCHR();
8244887Schin  fsm_oct:
8254887Schin 			PUTCHR(((n >> 6) & 07) + '0');
8264887Schin 			PUTCHR(((n >> 3) & 07) + '0');
8274887Schin 			PUTCHR((n & 07) + '0');
8284887Schin 			break;
8294887Schin 		default:
8304887Schin 			PUTCHR(c);
8314887Schin 			break;
8324887Schin 		}
8334887Schin 		rp = fsm[LIT1];
8344887Schin 		bp = ip;
8354887Schin 		goto fsm_get;
8364887Schin 
8374887Schin 	case S_MACRO:
8384887Schin 		UNGETCHR();
8394887Schin #if PROTOMAIN
8404887Schin 		if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6))
8414887Schin 		{
8424887Schin 			c = T_EXTERN;
8434887Schin 			break;
8444887Schin 		}
8454887Schin #endif
8464887Schin 		if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#';
8474887Schin 		else c = T_ID;
8484887Schin 
8494887Schin 		break;
8504887Schin 
8514887Schin 	case S_NL:
8524887Schin  fsm_newline:
8534887Schin 		proto->line++;
8544887Schin #if PROTOMAIN
8554887Schin 		if (flags & EXTERN)
8564887Schin 		{
8574887Schin 			if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n')
8584887Schin 				PUTCHR(' ');
8594887Schin 		}
8604887Schin 		else
8614887Schin #endif
8624887Schin 		PUTCHR(c);
8634887Schin 		if (flags & DIRECTIVE)
8644887Schin 		{
8654887Schin #if PROTOMAIN
8664887Schin 			if (flags & CLASSIC)
8674887Schin 			{
8684887Schin 				if (flags & EXTERN) BACKOUT();
8694887Schin 				if (flags & JUNK)
8704887Schin 				{
8714887Schin 					*(ip - 1) = 0;
8724887Schin 					op = strcopy(om, "/* ");
8734887Schin 					op = strcopy(op, im);
8744887Schin 					op = strcopy(op, " */\n");
8754887Schin 				}
8764887Schin 				flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF);
8774887Schin 			}
8784887Schin 			else
8794887Schin #endif
8804887Schin 			{
8814887Schin 				if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP))
8824887Schin 				{
8834887Schin 					*(ip - 1) = 0;
8844887Schin 					op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
8854887Schin 					op = strcopy(op, im);
8864887Schin 					op = strcopy(op, "\n#else\n");
8874887Schin 					bp = ip;
8884887Schin 					ip = im;
8894887Schin 					*op++ = *ip++;
8904887Schin 					while (*op = *ip++)
8914887Schin 						if (*op++ == '#' && *ip != '(')
8924887Schin 						{
8934887Schin 							op--;
8944887Schin 							while (*--op == ' ' || *op == '\t');
8954887Schin 							if (*ip == '#')
8964887Schin 							{
8974887Schin 								op = strcopy(op + 1, "/**/");
8984887Schin 								while (*++ip == ' ' || *ip == '\t');
8994887Schin 							}
9004887Schin 							else
9014887Schin 							{
9024887Schin 								if (*op != '"') *++op = '"';
9034887Schin 								op++;
9044887Schin 								while (*ip == ' ' || *ip == '\t') ip++;
9054887Schin 								while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
9064887Schin 								while (*ip == ' ' || *ip == '\t') ip++;
9074887Schin 								if (*ip == '"') ip++;
9084887Schin 								else *op++ = '"';
9094887Schin 							}
9104887Schin 						}
9114887Schin 					ip = bp;
9124887Schin 					op = strcopy(op, "\n#endif\n");
9134887Schin 					op = linesync(proto, op, proto->line);
9144887Schin 				}
9154887Schin 				flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF);
9164887Schin 			}
9174887Schin 			call = 0;
9184887Schin 			group = 0;
9194887Schin 			paren = 0;
9204887Schin 			last = '\n';
9214887Schin 		}
9224887Schin 		if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE)
9234887Schin 		{
9244887Schin #if PROTOMAIN
9254887Schin 			if (flags & EXTERN) BACKOUT();
9264887Schin #endif
9274887Schin 			SYNC();
9284887Schin 			return 0;
9294887Schin 		}
9304887Schin 		goto fsm_start;
9314887Schin 
9324887Schin 	case S_QUAL:
9334887Schin 		PUTCHR(c);
9344887Schin 		rp = fsm[NEXT(state)];
9354887Schin 		bp = ip;
9364887Schin 		goto fsm_get;
9374887Schin 
9384887Schin 	case S_TOK:
9394887Schin 		PUTCHR(c);
9404887Schin 		c = TYPE(state);
9414887Schin 		break;
9424887Schin 
9434887Schin 	case S_TOKB:
9444887Schin 		UNGETCHR();
9454887Schin 		c = TYPE(state);
9464887Schin 		break;
9474887Schin 
9484887Schin 	case S_RESERVED:
9494887Schin 		UNGETCHR();
9504887Schin 		c = T_ID;
9514887Schin 		if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp))
9524887Schin 		{
9534887Schin 		case RESERVED('N', 'N', 3):
9544887Schin 			if (proto->tp[1] == 'o')
9554887Schin 				c = T_DO;
9564887Schin 			break;
9574887Schin 		case RESERVED('d', 'o', 2):
9584887Schin 			c = T_DO;
9594887Schin 			break;
9604887Schin 		case RESERVED('e', 'e', 4):
9614887Schin 			if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4))
9624887Schin 			{
9634887Schin 				c = T_ELSE;
9644887Schin 				goto fsm_id;
9654887Schin 			}
9664887Schin 			break;
9674887Schin 		case RESERVED('e', 'n', 6):
9684887Schin 			if (!strncmp(proto->tp, "extern", 6))
9694887Schin 				c = T_EXTERN;
9704887Schin 			break;
9714887Schin 		case RESERVED('f', 'r', 3):
9724887Schin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3))
9734887Schin 			{
9744887Schin 				c = T_FOR;
9754887Schin 				goto fsm_id;
9764887Schin 			}
9774887Schin 			break;
9784887Schin 		case RESERVED('i', 'f', 2):
9794887Schin 			c = T_IF;
9804887Schin 			break;
9814887Schin 		case RESERVED('i', 'e', 6):
9824887Schin 			if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
9834887Schin 			{
9844887Schin 				flags |= SKIP;
9854887Schin 				SYNC();
9864887Schin 				line = proto->line;
9874887Schin 				op = strcopy(op - 6, "__INLINE__");
9884887Schin 				SYNC();
9894887Schin 			}
9904887Schin 			break;
9914887Schin 		case RESERVED('r', 'n', 6):
9924887Schin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6))
9934887Schin 			{
9944887Schin 				c = T_RETURN;
9954887Schin 				goto fsm_id;
9964887Schin 			}
9974887Schin 			break;
9984887Schin 		case RESERVED('s', 'c', 6):
9994887Schin 			if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6))
10004887Schin 			{
10014887Schin 				proto->ox = op - 6;
10024887Schin 				flags |= EXTERNALIZE;
10034887Schin 			}
10044887Schin 			break;
10054887Schin 		case RESERVED('t', 'f', 7):
10064887Schin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7))
10074887Schin 			{
10084887Schin 				flags |= TYPEDEF;
10094887Schin 				c = T_EXTERN;
10104887Schin 			}
10114887Schin 			break;
10124887Schin 		case RESERVED('v', 't', 8):
10134887Schin 			if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START;
10144887Schin 			break;
10154887Schin 		case RESERVED('v', 'd', 4):
10164887Schin 			if (!strncmp(proto->tp, "void", 4))
10174887Schin 			{
10184887Schin 				if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID;
10194887Schin 				else
10204887Schin 				{
10214887Schin 					SYNC();
10224887Schin 					line = proto->line;
10234887Schin 					if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*')
10244887Schin 					{
10254887Schin 						memcopy(op - 4, "__V_", 4);
10264887Schin 						memcopy(ip - 4, "__V_", 4);
10274887Schin 					}
10284887Schin 					else c = T_VOID;
10294887Schin 					proto->line = line;
10304887Schin 					SYNC();
10314887Schin 					bp = ip;
10324887Schin 				}
10334887Schin 			}
10344887Schin 			break;
10354887Schin 		case RESERVED('w', 'e', 5):
10364887Schin 			if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5))
10374887Schin 			{
10384887Schin 				c = T_WHILE;
10394887Schin 				goto fsm_id;
10404887Schin 			}
10414887Schin 			break;
10424887Schin 		}
10434887Schin #if PROTOMAIN
10444887Schin 		if ((flags & CLASSIC) && c != T_EXTERN)
10454887Schin 			c = T_ID;
10464887Schin #endif
10474887Schin 		break;
10484887Schin 
10494887Schin 	case S_VS:
10504887Schin 		goto fsm_start;
10514887Schin 
10524887Schin 	case S_WS:
10534887Schin 		UNGETCHR();
10544887Schin #if PROTOMAIN
10554887Schin 		if ((flags & (EXTERN|MATCH)) == EXTERN)
10564887Schin 		{
10574887Schin 			while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
10584887Schin 				op--;
10594887Schin 			if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
10604887Schin 		}
10614887Schin #endif
10624887Schin 		goto fsm_start;
10634887Schin 
10644887Schin 	default:
10654887Schin 		if (state & SPLICE)
10664887Schin 		{
10674887Schin 			if (c == '\\')
10684887Schin 			{
10694887Schin 				if (!(n = GETCHR()))
10704887Schin 				{
10714887Schin 					goto fsm_eob;
10724887Schin  fsm_splice:
10734887Schin 					c = '\\';
10744887Schin 					n = GETCHR();
10754887Schin 				}
10764887Schin 				if (n == '\n')
10774887Schin 				{
10784887Schin 					proto->line++;
10794887Schin 					PUTCHR('\\');
10804887Schin 					PUTCHR('\n');
10814887Schin 					bp = ip;
10824887Schin 					goto fsm_get;
10834887Schin 				}
10844887Schin 				UNGETCHR();
10854887Schin 			}
10864887Schin 			state &= ~SPLICE;
10874887Schin 			if (state >= TERMINAL)
10884887Schin 				goto fsm_terminal;
10894887Schin 			rp = fsm[state];
10904887Schin 		}
10914887Schin 		PUTCHR(c);
10924887Schin 		bp = ip;
10934887Schin 		goto fsm_get;
10944887Schin 	}
10954887Schin 	if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE)))
10964887Schin 	{
10974887Schin 		if (!(flags & DIRECTIVE)) switch (c)
10984887Schin 		{
10994887Schin 		case '(':
11004887Schin #if PROTOMAIN
11014887Schin 			if (!(flags & CLASSIC) || proto->brace == 0)
11024887Schin #endif
11034887Schin 			{
11044887Schin 				if (paren++ == 0)
11054887Schin 				{
11064887Schin #if PROTOMAIN
11074887Schin 					if (!(flags & CLASSIC) || group <= 1)
11084887Schin #endif
11094887Schin 					{
11104887Schin #if PROTOMAIN
11114887Schin 						args = 0;
11124887Schin #endif
11134887Schin 						if (group++ == 0) group++;
11144887Schin 						else if (flags & INDIRECT) call++;
11154887Schin 						flags |= MATCH;
11164887Schin 						im = ip - 1;
11174887Schin 						om = op - 1;
11184887Schin 					}
11194887Schin 					sub = 0;
11204887Schin 				}
11214887Schin 				else if (paren == 2 && !aim)
11224887Schin 				{
11234887Schin 					sub++;
11244887Schin 					if (last == '(')
11254887Schin 					{
11264887Schin 						flags &= ~MATCH;
11274887Schin 						om = 0;
11284887Schin 					}
11294887Schin 					else if (flags & INDIRECT)
11304887Schin 					{
11314887Schin 						aim = ip - 1;
11324887Schin 						aom = op - 1;
11334887Schin 					}
11344887Schin 					else if ((flags & (MATCH|TOKENS)) == MATCH)
11354887Schin 					{
11364887Schin 						for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
11374887Schin 						if (m != im && sub == 1)
11384887Schin 						{
11394887Schin 							m = im + (*nns(ip) == '*');
11404887Schin 						}
11414887Schin 						if (m == im)
11424887Schin 						{
11434887Schin 							flags &= ~MATCH;
11444887Schin 							om = 0;
11454887Schin 						}
11464887Schin 					}
11474887Schin 					else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*')
11484887Schin 					{
11494887Schin 						flags &= ~MATCH;
11504887Schin 						om = 0;
11514887Schin 					}
11524887Schin 				}
11534887Schin 				flags &= ~TOKENS;
11544887Schin 			}
11554887Schin 			break;
11564887Schin 		case ')':
11574887Schin #if PROTOMAIN
11584887Schin 			if (!(flags & CLASSIC) || proto->brace == 0)
11594887Schin #endif
11604887Schin 			if (--paren == 0)
11614887Schin 			{
11624887Schin #if PROTOMAIN
11634887Schin 				if (flags & CLASSIC)
11644887Schin 				{
11654887Schin 					if (group != 2)
11664887Schin 					{
11674887Schin 						c = T_ID;
11684887Schin 						break;
11694887Schin 					}
11704887Schin 					group++;
11714887Schin 				}
11724887Schin #endif
11734887Schin 				ie = ip;
11744887Schin 			}
11754887Schin 			else if (paren == 1 && (flags & INDIRECT) && !aie)
11764887Schin 				aie = ip;
11774887Schin 			break;
11784887Schin 		case '*':
11794887Schin 			if (last == '(' && group == 2)
11804887Schin 			{
11814887Schin 				group--;
11824887Schin 				if (paren == 1)
11834887Schin 				{
11844887Schin 					flags |= INDIRECT;
11854887Schin 					aim = aie = 0;
11864887Schin 				}
11874887Schin 			}
11884887Schin 			break;
11894887Schin 		case '#':
11904887Schin 			dir = directive(ip, dir);
11914887Schin 			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))
11924887Schin 				flags |= DIRECTIVE;
11934887Schin 			else if (!(flags & (DECLARE|DIRECTIVE)))
11944887Schin 			{
11954887Schin 				flags |= DIRECTIVE;
11964887Schin 				if (!(flags & PLUSONLY))
11974887Schin 				{
11984887Schin 					bp = ip;
11994887Schin 					while (*ip == ' ' || *ip == '\t') ip++;
12004887Schin 					if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
12014887Schin 					{
12024887Schin 						if (*++ip == ' ' || *ip == '\t')
12034887Schin 						{
12044887Schin 							proto->line = 0;
12054887Schin 							while (*++ip >= '0' && *ip <= '9')
12064887Schin 								proto->line = proto->line * 10 + *ip - '0';
12074887Schin 							proto->line--;
12084887Schin 						}
12094887Schin 					}
12104887Schin #if PROTOMAIN
12114887Schin 					else if ((flags & (CLASSIC|EXTERN)) == CLASSIC)
12124887Schin 					{
12134887Schin 						n = 0;
12144887Schin 						t = ip + 6;
12154887Schin 						while (ip < t && *ip >= 'a' && *ip <= 'z')
12164887Schin 							n = HASHKEYPART(n, *ip++);
12174887Schin 						switch (n)
12184887Schin 						{
12194887Schin 						case HASHKEY4('e','l','s','e'):
12204887Schin 						case HASHKEY5('e','n','d','i','f'):
12214887Schin 							while (*ip == ' ' || *ip == '\t') ip++;
12224887Schin 							if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
12234887Schin 							{
12244887Schin 								flags |= JUNK|MATCH;
12254887Schin 								im = ip;
12264887Schin 								om = op + (ip - bp);
12274887Schin 							}
12284887Schin 							break;
12294887Schin 						case HASHKEY4('e','l','i','f'):
12304887Schin 						case HASHKEY5('e','r','r','o','r'):
12314887Schin 						case HASHKEY2('i','f'):
12324887Schin 						case HASHKEY5('i','f','d','e','f'):
12334887Schin 						case HASHKEY6('i','f','n','d','e','f'):
12344887Schin 						case HASHKEY5('u','n','d','e','f'):
12354887Schin 							break;
12364887Schin 						case HASHKEY6('i','n','c','l','u','d'):
12374887Schin 							if (*ip == 'e') ip++;
12384887Schin 							/*FALLTHROUGH*/
12394887Schin 						case HASHKEY6('d','e','f','i','n','e'):
12404887Schin 						case HASHKEY6('p','r','a','g','m','a'):
12414887Schin 							if (*ip < 'a' || *ip > 'z') break;
12424887Schin 							/*FALLTHROUGH*/
12434887Schin 						default:
12444887Schin 							flags |= JUNK|MATCH;
12454887Schin 							im = bp - 1;
12464887Schin 							om = op - 1;
12474887Schin 							break;
12484887Schin 						}
12494887Schin 					}
12504887Schin 					else
12514887Schin #endif
12524887Schin 					{
12534887Schin 						if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
12544887Schin 						{
12554887Schin 							while (*++ip == ' ' || *ip == '\t');
12564887Schin 							if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
12574887Schin 							{
12584887Schin 								op = strcopy(op, "\
12594887Schin if !defined(va_start)\n\
12604887Schin #if defined(__STDARG__)\n\
12614887Schin #include <stdarg.h>\n\
12624887Schin #else\n\
12634887Schin #include <varargs.h>\n\
12644887Schin #endif\n\
12654887Schin #endif\n\
12664887Schin ");
12674887Schin 								op = linesync(proto, op, proto->line);
12684887Schin 								break;
12694887Schin 							}
12704887Schin 						}
12714887Schin 						else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
12724887Schin 						{
12734887Schin 							while (*++ip == ' ' || *ip == '\t');
12744887Schin 							if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
12754887Schin 							{
12764887Schin 								t = ip;
12774887Schin 								while (*++t == ' ' || *t == '\t');
12784887Schin 								if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
12794887Schin 									ip = t;
12804887Schin 								t = ip;
12814887Schin 								while (*++t == ' ' || *t == '\t');
12824887Schin 								if (*t == '_' && *(t + 1) == '_')
12834887Schin 								{
12844887Schin 									op = strcopy(op, "undef __MANGLE__\n");
12854887Schin 									op = linesync(proto, op, proto->line);
12864887Schin 									op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
12874887Schin 									break;
12884887Schin 								}
12894887Schin 							}
12904887Schin 							flags |= DEFINE|MATCH;
12914887Schin 							im = bp - 1;
12924887Schin 							om = op - 1;
12934887Schin 						}
12944887Schin 						else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
12954887Schin 						{
12964887Schin 							while (*++ip == ' ' || *ip == '\t');
12974887Schin 							if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
12984887Schin 							{
12994887Schin 								op = strcopy(op, "undef __MANGLE__\n");
13004887Schin 								op = linesync(proto, op, proto->line);
13014887Schin 								op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
13024887Schin 								break;
13034887Schin 							}
13044887Schin 							flags |= DEFINE|MATCH;
13054887Schin 							im = bp - 1;
13064887Schin 							om = op - 1;
13074887Schin 						}
13084887Schin 					}
13094887Schin 					ip = bp;
13104887Schin 				}
13114887Schin 				break;
13124887Schin 			}
13134887Schin 			else
13144887Schin 				break;
13154887Schin 			/*FALLTHROUGH*/
13164887Schin 		case '{':
13174887Schin 			if (proto->brace++ == 0 && paren == 0)
13184887Schin 			{
13194887Schin 				if (last == '=') flags |= INIT;
13204887Schin #if PROTOMAIN
13214887Schin 				else if (flags & CLASSIC)
13224887Schin 				{
13234887Schin 					if ((flags & (MATCH|OTHER|SKIP)) == MATCH)
13244887Schin 					{
13254887Schin 						if (args)
13264887Schin 						{
13274887Schin 							v = number(op, args < 0 ? -args : args);
13284887Schin 							v = strcopy(v, " argument actual/formal mismatch");
13294887Schin 							*v++ = ' ';
13304887Schin 							v = memcopy(v, im, ie - im);
13314887Schin 							*v = 0;
13324887Schin 							proto_error((char*)proto + sizeof(struct proto), 2, op, NiL);
13334887Schin 						}
13344887Schin 						ip--;
13354887Schin 						/*UNDENT...*/
13364887Schin 	v = ie;
13374887Schin 	while (ie < ip)
13384887Schin 		if (*ie++ == '/' && *ie == '*')
13394887Schin 		{
13404887Schin 			e = ie - 1;
13414887Schin 			while (++ie < ip)
13424887Schin 			{
13434887Schin 				if (*ie == '*')
13444887Schin 				{
13454887Schin 					while (ie < ip && *ie == '*') ie++;
13464887Schin 					if (ie < ip && *ie == '/')
13474887Schin 					{
13484887Schin 						while (++ie < ip && (*ie == ' ' || *ie == '\t'));
13494887Schin 						while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
13504887Schin 						if (e > v && *e != '\n') *e++ = ' ';
13514887Schin 						t = ie;
13524887Schin 						while (--e >= v)
13534887Schin 							*--t = *e;
13544887Schin 						v = t;
13554887Schin 						break;
13564887Schin 					}
13574887Schin 				}
13584887Schin 			}
13594887Schin 		}
13604887Schin 	ie = v;
13614887Schin 						/*...INDENT*/
13624887Schin 						op = om++;
13634887Schin 						if (flags & EXTERN)
13644887Schin 						{
13654887Schin 							v = op;
13664887Schin 							while (v > ko && *--v != ' ');
13674887Schin 							if (*v != ' ')
13684887Schin 							{
13694887Schin 								om = (v = (op += 4)) + 1;
13704887Schin 								while (v >= ko + 4)
13714887Schin 								{
13724887Schin 									*v = *(v - 4);
13734887Schin 									v--;
13744887Schin 								}
13754887Schin 								memcopy(ko, "int ", 4);
13764887Schin 							}
13774887Schin 							if (*v == ' ')
13784887Schin 							{
13794887Schin 								while (*(v + 1) == '*')
13804887Schin 									*v++ = '*';
13814887Schin 								*v = '\t';
13824887Schin 								if ((v - ko) <= 8)
13834887Schin 								{
13844887Schin 									om = (e = ++op) + 1;
13854887Schin 									while (e > v)
13864887Schin 									{
13874887Schin 										*e = *(e - 1);
13884887Schin 										e--;
13894887Schin 									}
13904887Schin 								}
13914887Schin 							}
13924887Schin 							om = (v = (op += 7)) + 1;
13934887Schin 							while (v >= ko + 7)
13944887Schin 							{
13954887Schin 								*v = *(v - 7);
13964887Schin 								v--;
13974887Schin 							}
13984887Schin 							memcopy(ko, "extern ", 7);
13994887Schin 						}
14004887Schin 						PUTCHR('(');
14014887Schin 						t = op;
14024887Schin 						e = 0;
14034887Schin 						/*UNDENT...*/
14044887Schin 	while (ie < ip)
14054887Schin 	{
14064887Schin 		if ((c = *ie) == ' ' || c == '\t' || c == '\n')
14074887Schin 		{
14084887Schin 			while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
14094887Schin 			if (ie >= ip) break;
14104887Schin 			if (c != '*' && op > om) PUTCHR(' ');
14114887Schin 		}
14124887Schin 		if ((n = ((c = *ie) == ',')) || c == ';')
14134887Schin 		{
14144887Schin 			if (flags & EXTERN)
14154887Schin 			{
14164887Schin 				m = op;
14174887Schin 				while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
14184887Schin 					op--;
14194887Schin 				v = op;
14204887Schin 				while (op > om && (c = *(op - 1)) != ' ' && c != '*')
14214887Schin 					op--;
14224887Schin 				while (*(op - 1) == ' ')
14234887Schin 					op--;
14244887Schin 				if (!e)
14254887Schin 				{
14264887Schin 					e = op;
14274887Schin 					while (e > om && *(e - 1) == '*')
14284887Schin 						e--;
14294887Schin 				}
14304887Schin #if _s5r4_386_compiler_bug_fixed_
14314887Schin 				if (op <= om || *(op - 1) == ',' && (*op++ = ' '))
14324887Schin 					op = strcopy(op, "int");
14334887Schin #else
14344887Schin 				if (op <= om)
14354887Schin 					op = strcopy(op, "int");
14364887Schin 				else if (*(op - 1) == ',')
14374887Schin 					op = strcopy(op, " int");
14384887Schin #endif
14394887Schin 				while (v < m)
14404887Schin 					PUTCHR(*v++);
14414887Schin 			}
14424887Schin 			PUTCHR(',');
14434887Schin 			if (n)
14444887Schin 			{
14454887Schin 				if (x = !e) e = op - 1;
14464887Schin 				PUTCHR(' ');
14474887Schin 				m = t;
14484887Schin 				while (m < e)
14494887Schin 					PUTCHR(*m++);
14504887Schin 				if (x)
14514887Schin 				{
14524887Schin 					m = e;
14534887Schin 					while (*--e != ' ');
14544887Schin 					while (*(e - 1) == '*') e--;
14554887Schin 					op -= m - e;
14564887Schin 				}
14574887Schin 			}
14584887Schin 			while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
14594887Schin 			if (ie >= ip) UNPUTCHR();
14604887Schin 			else PUTCHR(' ');
14614887Schin 			if (!n)
14624887Schin 			{
14634887Schin 				t = op;
14644887Schin 				e = 0;
14654887Schin 			}
14664887Schin 		}
14674887Schin 		else if (*ie == '*')
14684887Schin 		{
14694887Schin 			if (op > om && (c = *(op - 1)) == ' ') op--;
14704887Schin 			while (*ie == '*') PUTCHR(*ie++);
14714887Schin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
14724887Schin 			if (c != '(') PUTCHR(' ');
14734887Schin 		}
14744887Schin 		else if (*ie == '(')
14754887Schin 		{
14764887Schin 			if (op > om && *(op - 1) == ' ') op--;
14774887Schin 			PUTCHR(*ie++);
14784887Schin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
14794887Schin 		}
14804887Schin 		else if (*ie == ')')
14814887Schin 		{
14824887Schin 			if (op > om && *(op - 1) == '(')
14834887Schin 				proto_error((char*)proto + sizeof(struct proto), 1, "function pointer argument prototype omitted", NiL);
14844887Schin 			PUTCHR(*ie++);
14854887Schin 			while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
14864887Schin 		}
14874887Schin 		else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
14884887Schin 		{
14894887Schin 			ie += 8;
14904887Schin 			if (op > om) UNPUTCHR();
14914887Schin 		}
14924887Schin 		else PUTCHR(*ie++);
14934887Schin 	}
14944887Schin 						/*...INDENT*/
14954887Schin 						if (op <= om) op = strcopy(op, "void");
14964887Schin 						PUTCHR(')');
14974887Schin 						if (flags & EXTERN)
14984887Schin 						{
14994887Schin 							PUTCHR(';');
15004887Schin 							PUTCHR('\n');
15014887Schin 							SYNCOUT();
15024887Schin 							KEEPOUT();
15034887Schin 						}
15044887Schin 						else
15054887Schin 						{
15064887Schin 							PUTCHR('\n');
15074887Schin 							PUTCHR(*ip);
15084887Schin 						}
15094887Schin 						ip++;
15104887Schin 						flags &= ~(MATCH|SKIP);
15114887Schin 					}
15124887Schin 				}
15134887Schin #endif
15144887Schin 				else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS))
15154887Schin 				{
15164887Schin 					line = proto->line;
15174887Schin 					op = strcopy(om, " __PARAM__(");
15184887Schin 					op = memcopy(op, im, ie - im);
15194887Schin 					PUTCHR(',');
15204887Schin 					PUTCHR(' ');
15214887Schin 					PUTCHR('(');
15224887Schin 					flags &= ~(MATCH|SKIP);
15234887Schin 					if (flags & VARIADIC)
15244887Schin 					{
15254887Schin 						if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
15264887Schin 						memcopy(proto->variadic, im, vc);
15274887Schin 						op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
15284887Schin 					}
15294887Schin 					else
15304887Schin 					{
15314887Schin 						flags |= SKIP;
15324887Schin 						proto->ip = im;
15334887Schin 						proto->op = op;
15344887Schin 						group = 0;
15354887Schin 						brack = 0;
15364887Schin 						for (;;)
15374887Schin 						{
15384887Schin 							switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
15394887Schin 							{
15404887Schin 							case '[':
15414887Schin 								brack++;
15424887Schin 								continue;
15434887Schin 							case ']':
15444887Schin 								brack--;
15454887Schin 								continue;
15464887Schin 							case '(':
15474887Schin 								if (paren++) group++;
15484887Schin 								continue;
15494887Schin 							case ')':
15504887Schin 								if (--paren == 0)
15514887Schin 								{
15524887Schin 									group = 0;
15534887Schin 									if (flags & MATCH)
15544887Schin 									{
15554887Schin 										flags &= ~(MATCH|SKIP);
15564887Schin 										op = memcopy(op, m, e - m);
15574887Schin 									}
15584887Schin 									break;
15594887Schin 								}
15604887Schin 								continue;
15614887Schin 							case ',':
15624887Schin 								if (paren == 1)
15634887Schin 								{
15644887Schin 									group = 0;
15654887Schin 									if (flags & MATCH)
15664887Schin 									{
15674887Schin 										flags &= ~(MATCH|SKIP);
15684887Schin 										op = memcopy(op, m, e - m);
15694887Schin 									}
15704887Schin 									PUTCHR(',');
15714887Schin 									PUTCHR(' ');
15724887Schin 									proto->op = op;
15734887Schin 								}
15744887Schin 								continue;
15754887Schin 							case T_ID:
15764887Schin 								if (group <= 1 && !brack)
15774887Schin 								{
15784887Schin 									flags |= MATCH;
15794887Schin 									m = proto->tp;
15804887Schin 									e = proto->ip;
15814887Schin 								}
15824887Schin 								continue;
15834887Schin 							default:
15844887Schin 								continue;
15854887Schin 							}
15864887Schin 							break;
15874887Schin 						}
15884887Schin 						PUTCHR(')');
15894887Schin 						PUTCHR(')');
15904887Schin 					}
15914887Schin 					if (!(flags & SKIP))
15924887Schin 					{
15934887Schin 						flags |= SKIP;
15944887Schin 						proto->op = strcopy(op, " __OTORP__(");
15954887Schin 						proto->ip = im + 1;
15964887Schin 						n = *(ie - 1);
15974887Schin 						*(ie - 1) = ';';
15984887Schin 						c = *ie;
15994887Schin 						*ie = 0;
16004887Schin 						lex(proto, (flags & GLOBAL) | DECLARE);
16014887Schin 						*(ie - 1) = n;
16024887Schin 						*ie = c;
16034887Schin 						proto->ip = ie;
16044887Schin 						op = proto->op;
16054887Schin 						PUTCHR(')');
16064887Schin 					}
16074887Schin 					if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
16084887Schin 					op = linesync(proto, op, proto->line = line);
16094887Schin 					if (flags & DIRECTIVE)
16104887Schin 					{
16114887Schin 						proto->brace = 0;
16124887Schin 						PUTCHR('\n');
16134887Schin 						PUTCHR('#');
16144887Schin 					}
16154887Schin 					else if (!(flags & VARIADIC)) PUTCHR('{');
16164887Schin 				}
16174887Schin 			}
16184887Schin 			flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
16194887Schin 			call = 0;
16204887Schin 			group = 0;
16214887Schin 			break;
16224887Schin 		case '}':
16234887Schin 			flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS);
16244887Schin 			if (--proto->brace == 0)
16254887Schin 			{
16264887Schin 				flags &= ~(INIT|VARIADIC|VARIADIC2);
16274887Schin #if PROTOMAIN
16284887Schin 				if (flags & EXTERN) BACKOUT();
16294887Schin #endif
16304887Schin 			}
16314887Schin 			call = 0;
16324887Schin 			group = 0;
16334887Schin 			paren = 0;
16344887Schin 			break;
16354887Schin 		case '=':
16364887Schin 			if (last == '?') flags |= DIRECTIVE;
16378462SApril.Chin@Sun.COM 			else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH)
16388462SApril.Chin@Sun.COM 			{
16398462SApril.Chin@Sun.COM 				if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= SKIP;
16408462SApril.Chin@Sun.COM 				else goto fsm_statement;
16418462SApril.Chin@Sun.COM 			}
16424887Schin 			goto fsm_other;
16434887Schin 		case ',':
16444887Schin #if PROTOMAIN
16454887Schin 			if (flags & CLASSIC)
16464887Schin 			{
16474887Schin 				if (paren == 1) args++;
16484887Schin 				else
16494887Schin 				{
16504887Schin 					args--;
16514887Schin 					flags &= ~MATCH;
16524887Schin 				}
16534887Schin 				break;
16544887Schin 			}
16554887Schin #endif
16564887Schin 			if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';';
16574887Schin 			/*FALLTHROUGH*/
16584887Schin 		case ';':
16594887Schin  fsm_statement:
16604887Schin 			if (flags & INIT) /* ignore */;
16614887Schin #if PROTOMAIN
16624887Schin 			else if (flags & CLASSIC)
16634887Schin 			{
16644887Schin 				if (paren == 0)
16654887Schin 				{
16664887Schin 					if ((flags & MATCH) && last == ')')
16674887Schin 						flags &= ~MATCH;
16684887Schin 					if (!(flags & MATCH))
16694887Schin 					{
16704887Schin 						call = 0;
16714887Schin 						group = 0;
16724887Schin 						flags &= ~SKIP;
16734887Schin 						if (flags & EXTERN) BACKOUT();
16744887Schin 						if (flags & SLIDE)
16754887Schin 						{
16764887Schin 							SYNC();
16774887Schin 							return 0;
16784887Schin 						}
16794887Schin 					}
16804887Schin 					else
16814887Schin 					{
16824887Schin 						args--;
16834887Schin 						if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP))
16844887Schin 							BACKOUT();
16854887Schin 					}
16864887Schin 				}
16874887Schin 			}
16884887Schin #endif
16894887Schin 			else if (paren == 0)
16904887Schin 			{
16914887Schin 				if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1)
16924887Schin 				{
16934887Schin 					if ((flags & MANGLE) && func)
16944887Schin 					{
16954887Schin 						func[0] = 'F';
16964887Schin 						func[1] = 'U';
16974887Schin 						func[2] = 'N';
16984887Schin 						func[3] = 'C';
16994887Schin 						func = 0;
17004887Schin 					}
17014887Schin 					if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im)
17024887Schin 					{
17034887Schin 						while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
17044887Schin 						v = aim;
17054887Schin 						while (v < aie)
17064887Schin 							if (*v++ == ')') break;
17074887Schin 						while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
17084887Schin 						if (v == aie || !(flags & PLUSPLUS))
17094887Schin 						{
17104887Schin 							if (flags & PLUSPLUS) n = 3;
17114887Schin 							else if (v == aie && *v == '(') n = 10;
17124887Schin 							else n = 11;
17134887Schin 							ko = op;
17144887Schin 							om += n;
17154887Schin 							v = op += n;
17164887Schin 							while (v >= ko + n)
17174887Schin 							{
17184887Schin 								*v = *(v - n);
17194887Schin 								v--;
17204887Schin 							}
17214887Schin 							if (flags & PLUSPLUS) memcopy(aom, "(...))", 6);
17224887Schin 							else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
17234887Schin 							else
17244887Schin 							{
17254887Schin 								ko = strcopy(aom, " __PROTO__(");
17264887Schin 								ko = memcopy(ko, aim, aie - aim);
17274887Schin 								*ko = ')';
17284887Schin 								if (++ko >= om)
17294887Schin 								{
17304887Schin 									*ko++ = ')';
17314887Schin 									om = ko;
17324887Schin 								}
17334887Schin 							}
17344887Schin 						}
17354887Schin 					}
17364887Schin 					else if (flags & TYPEDEF)
17374887Schin 					{
17384887Schin 						op = om;
17394887Schin 						while (*--op == ' ' || *op == '\t' || *op == '\n');
17404887Schin 						if (*op != ')')
17414887Schin 						{
17424887Schin 							op = om += 14;
17434887Schin 							*--op = ')';
17444887Schin 							while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
17454887Schin 								*--op = x;
17464887Schin 							memcopy(op - 13, "(__OTORP__(*)", 13);
17474887Schin 						}
17484887Schin 					}
17494887Schin 					if (flags & OTHER)
17504887Schin 						;
17514887Schin 					else if (flags & PLUSPLUS)
17524887Schin 					{
17534887Schin 						op = om;
17544887Schin 						if (!(flags & TOKENS)) op = strcopy(op, "(...)");
17554887Schin 						else op = memcopy(op, im, ie - im);
17564887Schin 						PUTCHR(c);
17574887Schin 					}
17584887Schin 					else
17594887Schin 					{
17604887Schin 						if (flags & DECLARE) op = strcopy(om, "()");
17614887Schin 						else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)");
17624887Schin 						else
17634887Schin 						{
17644887Schin 							op = strcopy(om, " __PROTO__(");
17654887Schin 							op = memcopy(op, im, ie - im);
17664887Schin 							PUTCHR(')');
17674887Schin 						}
17684887Schin 						if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
17694887Schin 						PUTCHR(c);
17704887Schin 					}
17714887Schin 					flags &= ~(MATCH|VARIADIC|VARIADIC2);
17724887Schin 					if (c == ',' && !(flags & INDIRECT))
17734887Schin 					{
17744887Schin 						call = 1;
17754887Schin 						group = 0;
17764887Schin 						break;
17774887Schin 					}
17784887Schin 				}
17794887Schin 				else if (flags & (OTHER|SKIP)) call = 0;
17804887Schin 				if (c == ';')
17814887Schin 				{
17824887Schin 					flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF);
17834887Schin 					call = 0;
17844887Schin 					if (flags & SLIDE)
17854887Schin 					{
17864887Schin 						SYNC();
17874887Schin 						return 0;
17884887Schin 					}
17894887Schin 				}
17904887Schin 				else call = call > 1 && c == ',';
17914887Schin 				group = 0;
17924887Schin 				flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
17934887Schin 			}
17944887Schin 			else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER;
17954887Schin 			break;
17964887Schin 		case T_DO:
17974887Schin 		case T_IF:
17984887Schin 			flags |= TOKENS|SKIP;
17994887Schin 			break;
18004887Schin 		case T_EXTERN:
18014887Schin #if PROTOMAIN
18024887Schin 			if (flags & CLASSIC)
18034887Schin 			{
18044887Schin 				if (proto->brace == 0)
18054887Schin 					flags |= SKIP;
18064887Schin 			}
18074887Schin 			else
18084887Schin #endif
18094887Schin 			if (paren == 0 && !(flags & TYPEDEF))
18104887Schin 			{
18114887Schin 				flags |= MANGLE;
18124887Schin 				if (!(flags & PLUSONLY) || proto->package)
18134887Schin 				{
18144887Schin 					op = strcopy(op, " __MANGLE__");
18154887Schin 					if (proto->package)
18164887Schin 					{
18174887Schin 						op = strcopy(op - 1, proto->package);
18184887Schin 						func = op + 1;
18194887Schin 						op = strcopy(op, "_DATA__");
18204887Schin 					}
18214887Schin 				}
18224887Schin 				else
18234887Schin 					func = 0;
18244887Schin 			}
18254887Schin 			break;
18264887Schin 		case T_VARIADIC:
18274887Schin 			if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE)
18284887Schin 			{
18294887Schin 				op -= 3;
18304887Schin 				SYNC();
18314887Schin 				return c;
18324887Schin 			}
18334887Schin 			if (paren == 1 && !(flags & SKIP))
18344887Schin 				flags |= VARIADIC;
18354887Schin 			flags |= TOKENS;
18364887Schin 			break;
18374887Schin 		case T_VOID:
18384887Schin 			goto fsm_id;
18394887Schin 		case T_VA_START:
18404887Schin 			if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC)
18414887Schin 			{
18424887Schin 				flags &= ~MATCH;
18434887Schin 				line = proto->line;
18444887Schin 				op = strcopy(op - 8, "__VA_START__");
18454887Schin 				SYNC();
18464887Schin 				for (;;)
18474887Schin 				{
18484887Schin 					switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
18494887Schin 					{
18504887Schin 					case 0:
18514887Schin 					case ';':
18524887Schin 						break;
18534887Schin 					case T_ID:
18544887Schin 						if (!(flags & MATCH))
18554887Schin 						{
18564887Schin 							flags |= MATCH;
18574887Schin 							m = proto->tp;
18584887Schin 							e = proto->ip;
18594887Schin 						}
18604887Schin 						continue;
18614887Schin 					default:
18624887Schin 						continue;
18634887Schin 					}
18644887Schin 					break;
18654887Schin 				}
18664887Schin 				CACHE();
18674887Schin 				if (flags & MATCH)
18684887Schin 				{
18694887Schin 					v = m;
18704887Schin 					n = e - m;
18714887Schin 				}
18724887Schin 				else
18734887Schin 				{
18744887Schin 					v = "ap";
18754887Schin 					n = 2;
18764887Schin 				}
18774887Schin 				op = strcopy(op, " __OTORP__(");
18784887Schin 				proto->ip = proto->variadic;
18794887Schin 				proto->op = op;
18804887Schin 				flags &= ~MATCH;
18814887Schin 				group = 0;
18824887Schin 				bp = proto->ip + 1;
18834887Schin 				if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
18844887Schin 				for (;;)
18854887Schin 				{
18864887Schin 					switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
18874887Schin 					{
18884887Schin 					case '(':
18894887Schin 						if (paren++) group++;
18904887Schin 						continue;
18914887Schin 					case ')':
18924887Schin 						if (--paren == 0)
18934887Schin 						{
18944887Schin 							if (flags & MATCH)
18954887Schin 							{
18964887Schin 								flags &= ~MATCH;
18974887Schin 								if (!(flags & VARIADIC2))
18984887Schin 								{
18994887Schin 									op = memcopy(op, m, e - m);
19004887Schin 									op = strcopy(op, " = ");
19014887Schin 								}
19024887Schin 								op = strcopy(op, "va_arg(");
19034887Schin 								op = memcopy(op, v, n);
19044887Schin 								PUTCHR(',');
19054887Schin 								PUTCHR(' ');
19064887Schin 								if (m > bp) op = memcopy(op, bp, m - bp);
19074887Schin 								else op = strcopy(op, "int ");
19084887Schin 								if (group > 1) op = strcopy(op, ")()");
19094887Schin 								else op = memcopy(op, e, proto->ip - e - 1);
19104887Schin 								PUTCHR(')');
19114887Schin 								PUTCHR(';');
19124887Schin 							}
19134887Schin 							group = 0;
19144887Schin 							break;
19154887Schin 						}
19164887Schin 						continue;
19174887Schin 					case ',':
19184887Schin 						if (paren == 1)
19194887Schin 						{
19204887Schin 							if (flags & MATCH)
19214887Schin 							{
19224887Schin 								flags &= ~MATCH;
19234887Schin 								if (!(flags & VARIADIC2))
19244887Schin 								{
19254887Schin 									op = memcopy(op, m, e - m);
19264887Schin 									op = strcopy(op, " = ");
19274887Schin 								}
19284887Schin 								op = strcopy(op, "va_arg(");
19294887Schin 								op = memcopy(op, v, n);
19304887Schin 								PUTCHR(',');
19314887Schin 								PUTCHR(' ');
19324887Schin 								if (m > bp) op = memcopy(op, bp, m - bp);
19334887Schin 								else op = strcopy(op, "int ");
19344887Schin 								if (group > 1) op = strcopy(op, ")()");
19354887Schin 								else op = memcopy(op, e, proto->ip - e - 1);
19364887Schin 								PUTCHR(')');
19374887Schin 								PUTCHR(';');
19384887Schin 								bp = proto->ip + 1;
19394887Schin 								if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
19404887Schin 							}
19414887Schin 							group = 0;
19424887Schin 							proto->op = op;
19434887Schin 						}
19444887Schin 						continue;
19454887Schin 					case T_ID:
19464887Schin 						if (group <= 1)
19474887Schin 						{
19484887Schin 							flags |= MATCH;
19494887Schin 							m = proto->tp;
19504887Schin 							e = proto->ip;
19514887Schin 						}
19524887Schin 						continue;
19534887Schin 					default:
19544887Schin 						continue;
19554887Schin 					}
19564887Schin 					break;
19574887Schin 				}
19584887Schin 				op = strcopy(op, ")");
19594887Schin 				flags |= VARIADIC2;
19604887Schin 				proto->line = line;
19614887Schin 				call = 0;
19624887Schin 				break;
19634887Schin 			}
19644887Schin 			/*FALLTHROUGH*/
19654887Schin 		case T_ID:
19664887Schin  fsm_id:
19674887Schin #if PROTOMAIN
19684887Schin 			if (flags & CLASSIC)
19694887Schin 			{
19704887Schin 				if (!args && paren == 1) args++;
19714887Schin 				break;
19724887Schin 			}
19734887Schin #endif
19744887Schin 			if (paren == 0)
19754887Schin 			{
19764887Schin 				if (last == ')')
19774887Schin 				{
19784887Schin 					if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP;
19794887Schin 					call = !call;
19804887Schin 				}
19814887Schin 				else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++;
19824887Schin 				else flags |= SKIP;
19834887Schin 				if (last == T_ID) flags |= IDID;
19844887Schin 			}
19854887Schin 			c = T_ID;
19864887Schin 			flags |= TOKENS;
19874887Schin 			break;
19884887Schin 		case T_INVALID:
19894887Schin 			if (*proto->tp >= '0' && *proto->tp <= '9')
19904887Schin 			{
19914887Schin 				n = 0;
19924887Schin 				for (;; op--)
19934887Schin 				{
19944887Schin 					switch (*(op - 1))
19954887Schin 					{
19964887Schin 					case 'f':
19974887Schin 					case 'F':
19984887Schin 						t = op;
19994887Schin 						while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
20004887Schin 						if (*t == '.')
20014887Schin 							op--;
20024887Schin 						n = 0;
20034887Schin 						break;
20044887Schin 					case 'l':
20054887Schin 					case 'L':
20064887Schin 						if (!(n & 01))
20074887Schin 						{
20084887Schin 							n |= 01;
20094887Schin 							t = op;
20104887Schin 							while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
20114887Schin 							if (*t == '.')
20124887Schin 							{
20134887Schin 								n = 0;
20144887Schin 								op--;
20154887Schin 								break;
20164887Schin 							}
20174887Schin 						}
20184887Schin 						continue;
20194887Schin 					case 'u':
20204887Schin 					case 'U':
20214887Schin 						n |= 02;
20224887Schin 						continue;
20234887Schin 					}
20244887Schin 					break;
20254887Schin 				}
20264887Schin 				if (n & 01)
20274887Schin 					*op++ = 'L';
20284887Schin 				if (n & 02)
20294887Schin 				{
20304887Schin 					m = op;
20314887Schin 					t = op = m + 10;
20324887Schin 					while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
20334887Schin 						*--t = c;
20344887Schin 					c = *t;
20354887Schin 					strcopy(m + 1, "(unsigned)");
20364887Schin 					*t = c;
20374887Schin 					break;
20384887Schin 				}
20394887Schin 			}
20404887Schin 			goto fsm_other;
20414887Schin #if PROTOMAIN
20424887Schin 		case '[':
20434887Schin 			if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP;
20444887Schin 			/*FALLTHROUGH*/
20454887Schin #endif
20464887Schin 		default:
20474887Schin  fsm_other:
20484887Schin #if PROTOMAIN
20494887Schin 			if (flags & CLASSIC) break;
20504887Schin #endif
20514887Schin 			flags |= TOKENS;
20524887Schin 			if (paren == 0) flags |= OTHER;
20534887Schin 			break;
20544887Schin 		}
20554887Schin 		else if (c == '#' && *ip != '(') flags |= SHARP;
20564887Schin 		last = c;
20574887Schin #if PROTOMAIN
20584887Schin 		if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID))
20594887Schin 			CACHEOUT();
20604887Schin 		else
20614887Schin #endif
20624887Schin 		SYNCOUT();
20634887Schin 		goto fsm_start;
20644887Schin 	}
20654887Schin 	else if (flags & (INIT_DEFINE|INIT_INCLUDE))
20664887Schin 	{
20674887Schin #if PROTOMAIN
20684887Schin 		if ((flags & YACC) && c == '%' && *ip == '{') t = 0;
20694887Schin 		else
20704887Schin #endif
20714887Schin 		{
20724887Schin 			if (c == '#') for (t = ip; *t == ' ' || *t == '\t'; t++);
20734887Schin 			else t = "";
20744887Schin 			if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
20754887Schin 			{
20764887Schin #if !PROTOMAIN
20774887Schin 				while (*t == ' ' || *t == '\t') t++;
20784887Schin 				if (*t != '_')
20794887Schin #endif
20804887Schin 					t = 0;
20814887Schin 			}
20824887Schin 		}
20834887Schin 		if (t)
20844887Schin 		{
20854887Schin 			ip = bp;
20864887Schin 			op = proto->op;
20874887Schin 		}
20884887Schin 		else while (*ip != '\n') *op++ = *ip++;
20894887Schin 		op = init(proto, op, flags);
20904887Schin 		op = linesync(proto, op, proto->line);
20914887Schin 		flags &= ~(INIT_DEFINE|INIT_INCLUDE);
20924887Schin 		proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE);
20934887Schin 		goto fsm_start;
20944887Schin 	}
20954887Schin 	SYNC();
20964887Schin 	return c;
20974887Schin }
20984887Schin 
20994887Schin /*
21004887Schin  * close a proto buffer stream
21014887Schin  */
21024887Schin 
21034887Schin void
pppclose(char * iob)21044887Schin pppclose(char* iob)
21054887Schin {
21064887Schin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
21074887Schin 
21084887Schin 	if (proto->flags & MORE) close(proto->fd);
21094887Schin 	free((char*)proto); /* some ANSI cc's botch the free() prototype */
21104887Schin }
21114887Schin 
21124887Schin /*
21134887Schin  * open a new proto buffer stream
21144887Schin  * read buffer pointer returned
21154887Schin  * 0 returned on error or if no magic
21164887Schin  *
21174887Schin  *	file	!=0	file path to open, otherwise use fd
21184887Schin  *	fd		open file fd if file==0
21194887Schin  *	notice	!=0	copyright notice info commented at the top
21204887Schin  *	options	!=0	additional notice name=value pairs, space or ; separated
21214887Schin  *	package	!=0	generate header for this package
21224887Schin  */
21234887Schin 
21244887Schin char*
pppopen(char * file,int fd,char * notice,char * options,char * package,char * comment,int flags)21254887Schin pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags)
21264887Schin {
21274887Schin 	register struct proto*	proto;
21284887Schin 	register char*		iob;
21294887Schin 	register long		n;
21304887Schin 	register char*		s;
21314887Schin 	int			pragma;
21324887Schin 	char*			b;
21334887Schin #if PROTOMAIN
21344887Schin 	int			comlen;
21354887Schin 	char			com[80];
21364887Schin #endif
21374887Schin 	int			m = 0;
21384887Schin 
21394887Schin 	static int		retain;
21404887Schin 
21414887Schin 	/*
21424887Schin 	 * initialize proto
21434887Schin 	 */
21444887Schin 
21454887Schin #if PROTOMAIN
21464887Schin 	if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE;
21474887Schin #endif
21484887Schin 	if (flags & PROTO_RETAIN) flags &= ~retain;
21494887Schin 	else retain &= PROTO_INITIALIZED;
21504887Schin 	if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
21514887Schin #if !PROTOMAIN
21524887Schin 	if ((n = lseek(fd, 0L, 2)) > 0)
21534887Schin 	{
21544887Schin 		if (lseek(fd, 0L, 0)) return 0;
21554887Schin 		if (n < CHUNK) n = CHUNK;
21564887Schin 		else if (n > 2 * BLOCK) n = 0;
21574887Schin 		m = 1;
21584887Schin 	}
21594887Schin 	if (n > 0)
21604887Schin 	{
21614887Schin 		/*
21624887Schin 		 * file read in one chunk
21634887Schin 		 */
21644887Schin 
21654887Schin 		if (!(proto = newof(0, struct proto, 1, 4 * n + 2)))
21664887Schin 			return 0;
21674887Schin 		proto->iz = n;
21684887Schin 		proto->oz = 3 * n;
21694887Schin 		n = 0;
21704887Schin 	}
21714887Schin 	else
21724887Schin #endif
21734887Schin 	{
21744887Schin 		/*
21754887Schin 		 * file read in BLOCK chunks
21764887Schin 		 */
21774887Schin 
21784887Schin 		n = BLOCK;
21794887Schin 		if (!(proto = newof(0, struct proto, 1, 5 * n + 2)))
21804887Schin 			return 0;
21814887Schin 		proto->iz = n;
21824887Schin 		proto->oz = 3 * n;
21834887Schin 		proto->flags |= MORE;
21844887Schin 	}
21854887Schin 	proto->fd = fd;
21864887Schin 	proto->package = package;
21874887Schin 	iob = (char*)proto + sizeof(struct proto);
21884887Schin 	proto->op = proto->ob = iob;
21894887Schin 	proto->ip = proto->ib = iob + proto->oz + n;
21904887Schin 	if (m) proto->options |= REGULAR;
21914887Schin 	if (!comment)
21924887Schin 		comment = "/*";
21934887Schin 	if (!(proto->cc[0] = comment[0]))
21944887Schin 		notice = options = 0;
21954887Schin 	else if (comment[1])
21964887Schin 	{
21974887Schin 		proto->cc[1] = comment[1];
21984887Schin 		proto->cc[2] = comment[2] ? comment[2] : comment[0];
21994887Schin 	}
22004887Schin 	else
22014887Schin 		proto->cc[1] = proto->cc[2] = comment[0];
22024887Schin 
22034887Schin 	/*
22044887Schin 	 * read the first chunk
22054887Schin 	 */
22064887Schin 
22074887Schin 	n = read(fd, proto->ip, proto->iz);
22084887Schin 	if (!(proto->flags & MORE))
22094887Schin 		close(fd);
22104887Schin 	if (n < 0)
22114887Schin 	{
22124887Schin 		pppclose(iob);
22134887Schin 		return 0;
22144887Schin 	}
22154887Schin 	*(proto->ip + n) = 0;
22164887Schin 
22174887Schin 	/*
22184887Schin 	 * check for proto pragma in first block of lines
22194887Schin 	 * pragma blanked out if found
22204887Schin 	 *
22214887Schin 	 *	-1	no pragma
22224887Schin 	 *	 0	#pragma noprototyped
22234887Schin 	 *	 1	#pragma prototyped
22244887Schin 	 *
22254887Schin 	 * NOTE: matches may occur inside comments and quotes
22264887Schin 	 */
22274887Schin 
22284887Schin #if PROTOMAIN
22294887Schin 	if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
22304887Schin 		*com = 0;
22314887Schin #endif
22324887Schin 	pragma = -1;
22334887Schin 	s = proto->ip;
22344887Schin 	m = MAGICTOP;
22354887Schin 	while (m-- > 0 && *s)
22364887Schin 	{
22374887Schin 		while (*s == ' ' || *s == '\t') s++;
22384887Schin 		if (*s == '#')
22394887Schin 		{
22404887Schin 			b = s++;
22414887Schin 			while (*s == ' ' || *s == '\t') s++;
22424887Schin 			if (!strncmp(s, MAGICDIR, sizeof(MAGICDIR) - 1) && (*(s += sizeof(MAGICDIR) - 1) == ' ' || *s == '\t'))
22434887Schin 			{
22444887Schin 				while (*s == ' ' || *s == '\t') s++;
22454887Schin 				if (*s == 'n' && *(s + 1) == 'o')
22464887Schin 				{
22474887Schin 					s += 2;
22484887Schin 					pragma = -2;
22494887Schin 				}
22504887Schin 				if (!strncmp(s, MAGICARG, sizeof(MAGICARG) - 1) && (*(s += sizeof(MAGICARG) - 1) == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
22514887Schin 					while (*s)
22524887Schin 					{
22534887Schin 						if ((*(s - 1) == ' ' || *(s - 1) == '\t') && *s == *MAGICOFF && !strncmp(s, MAGICOFF, sizeof(MAGICOFF) - 1))
22544887Schin 							notice = options = 0;
22554887Schin 						if (*s++ == '\n')
22564887Schin 						{
22574887Schin 							pragma += 2;
22584887Schin #if PROTOMAIN
22594887Schin 							if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA))
22604887Schin #endif
22614887Schin 							for (s--; b < s; *b++ = ' ');
22624887Schin 							goto magic;
22634887Schin 						}
22644887Schin 					}
22654887Schin 				pragma = -1;
22664887Schin 			}
22674887Schin 		}
22684887Schin 		else if (*s == '/' && !strncmp(s, MAGICGEN, sizeof(MAGICGEN) - 1))
22694887Schin 		{
22704887Schin 			pragma = 0;
22714887Schin 			break;
22724887Schin 		}
22734887Schin #if PROTOMAIN
22744887Schin 		else if (*s == '%' && *(s + 1) == '{')
22754887Schin 			proto->flags |= YACC;
22764887Schin 		if (notice || options)
22774887Schin 		{
22784887Schin 			if (*s == *com && !strncmp(s, com, comlen))
22794887Schin 				notice = options = 0;
22804887Schin 			else
22814887Schin 				while (*s)
22824887Schin 				{
22834887Schin 					if (*s == *NOTICED && !strncmp(s, NOTICED, sizeof(NOTICED) - 1))
22844887Schin 					{
22854887Schin 						s += sizeof(NOTICED) - 1;
22864887Schin 						while (*s == ' ' || *s == '\t')
22874887Schin 							s++;
22884887Schin 						if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
22894887Schin 						{
22904887Schin 							notice = options = 0;
22914887Schin 							break;
22924887Schin 						}
22934887Schin 					}
22948462SApril.Chin@Sun.COM 					if (*s == *PUBLICDOMAIN && !strncmp(s, PUBLICDOMAIN, sizeof(PUBLICDOMAIN) - 1))
22958462SApril.Chin@Sun.COM 					{
22968462SApril.Chin@Sun.COM 						notice = options = 0;
22978462SApril.Chin@Sun.COM 						break;
22988462SApril.Chin@Sun.COM 					}
22994887Schin 					else if (*s++ == '\n')
23004887Schin 					{
23014887Schin 						s--;
23024887Schin 						break;
23034887Schin 					}
23044887Schin 				}
23054887Schin 		}
23064887Schin #endif
23074887Schin 		while (*s && *s++ != '\n');
23084887Schin 	}
23094887Schin  magic:
23104887Schin 	if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS;
23114887Schin 	if (flags & PROTO_TEST) proto->test = 1;
23124887Schin 	if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE;
23134887Schin #if PROTOMAIN
23144887Schin 	if (flags & PROTO_CLASSIC) pragma = -pragma;
23154887Schin 	if (flags & PROTO_DISABLE) pragma = 0;
23164887Schin 	if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC;
23174887Schin 	if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.')
23184887Schin 		proto->flags |= YACC;
23194887Schin #endif
23204887Schin 	if (pragma <= 0)
23214887Schin 	{
23224887Schin 		if (flags & PROTO_PLUSPLUS)
23234887Schin 		{
23244887Schin 			flags &= ~(PROTO_HEADER|PROTO_INCLUDE);
23254887Schin 			proto->flags |= PLUSONLY;
23264887Schin 		}
23274887Schin 		else if (!(flags & (PROTO_FORCE|PROTO_PASS)))
23284887Schin 		{
23294887Schin 			pppclose(iob);
23304887Schin 			return 0;
23314887Schin 		}
23324887Schin 		else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma)
23334887Schin 		{
23344887Schin 			proto->flags |= PASS;
23354887Schin 			if (proto->flags & MORE)
23364887Schin 				proto->oz += proto->iz;
23374887Schin 			proto->iz = n;
23384887Schin 			if (notice || options)
23394887Schin 			{
23404887Schin 				if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
23414887Schin 				{
23424887Schin 					s = proto->ip;
23434887Schin 					while (*s && *s++ != '\n');
23444887Schin 					m = s - proto->ip;
23454887Schin 					proto->op = memcopy(proto->op, proto->ip, m);
23464887Schin 					proto->ip = s;
23474887Schin 					proto->iz = n -= m;
23484887Schin 				}
23494887Schin #if PROTOMAIN
23504887Schin 				if (proto->cc[0])
23514887Schin 				{
23524887Schin 					if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
23534887Schin 						proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
23544887Schin 					else
23554887Schin 						proto->op += comlen;
23564887Schin 				}
23574887Schin 				if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC))
23584887Schin #endif
23594887Schin 				proto->op = linesync(proto, proto->op, 1);
23604887Schin 				proto->iz += proto->op - proto->ob;
23614887Schin 			}
23624887Schin 			memcopy(proto->op, proto->ip, n);
23634887Schin 			return iob;
23644887Schin 		}
23654887Schin 	}
23664887Schin #if PROTOMAIN
23674887Schin 	if (!(retain & PROTO_INITIALIZED))
23684887Schin 	{
23694887Schin 		retain |= PROTO_INITIALIZED;
23704887Schin 		ppfsm(FSM_INIT, NiL);
23714887Schin 	}
23724887Schin #endif
23734887Schin 	proto->line = 1;
23744887Schin #if CHUNK >= 512
23754887Schin 	if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE)))
23764887Schin 	{
23774887Schin #if PROTOMAIN
23784887Schin 		if (notice || options)
23794887Schin 		{
23804887Schin 			if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
23814887Schin 				proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
23824887Schin 			else
23834887Schin 				proto->op += comlen;
23844887Schin 		}
23854887Schin #endif
23864887Schin 		if (flags & PROTO_INCLUDE)
23874887Schin 		{
23884887Schin 			proto->flags |= INIT_INCLUDE;
23894887Schin 			if (flags & PROTO_RETAIN)
23904887Schin 				retain |= PROTO_INCLUDE;
23914887Schin 		}
23924887Schin 		else if (flags & PROTO_HEADER)
23934887Schin 		{
23944887Schin 			if (flags & PROTO_RETAIN) retain |= PROTO_HEADER;
23954887Schin #if PROTOMAIN
23964887Schin 			if (flags & PROTO_CLASSIC)
23974887Schin 			{
23984887Schin 				*proto->op++ = '#';
23994887Schin 				proto->op = strcopy(proto->op, MAGICDIR);
24004887Schin 				*proto->op++ = ' ';
24014887Schin 				proto->op = strcopy(proto->op, MAGICARG);
24024887Schin 				*proto->op++ = '\n';
24034887Schin 			}
24044887Schin 			else
24054887Schin #endif
24064887Schin 			proto->flags |= INIT_DEFINE;
24074887Schin 		}
24084887Schin #if PROTOMAIN
24094887Schin 		if (!(flags & PROTO_CLASSIC))
24104887Schin 		{
24114887Schin 			if (proto->flags & YACC)
24124887Schin 			{
24134887Schin 				proto->op = strcopy(proto->op, "\n%{\n" + !notice);
24144887Schin 				proto->op = strcopy(proto->op, MAGICGEN);
24154887Schin 				proto->op = strcopy(proto->op, "%}\n");
24164887Schin 			}
24174887Schin 			else
24184887Schin 			{
24194887Schin 				if (n || notice || options)
24204887Schin 					*proto->op++ = '\n';
24214887Schin 				proto->op = strcopy(proto->op, MAGICGEN);
24224887Schin 				if (n)
24234887Schin 					proto->op = linesync(proto, proto->op, proto->line);
24244887Schin 				else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE))
24254887Schin 					proto->op = init(proto, proto->op, proto->flags);
24264887Schin 			}
24274887Schin 		}
24284887Schin #endif
24294887Schin 	}
24304887Schin #endif
24314887Schin #if PROTOMAIN
24324887Schin 	proto->file = file;
24334887Schin 	if (flags & PROTO_CLASSIC)
24344887Schin 	{
24354887Schin 		proto->flags |= CLASSIC;
24364887Schin 		if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN;
24374887Schin 	}
24384887Schin #endif
24394887Schin 	return iob;
24404887Schin }
24414887Schin 
24424887Schin /*
24434887Schin  * read next proto'd chunk into iob
24444887Schin  * the chunk is 0 terminated and its size is returned
24454887Schin  */
24464887Schin 
24474887Schin int
pppread(char * iob)24484887Schin pppread(char* iob)
24494887Schin {
24504887Schin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
24514887Schin 	register int		n;
24524887Schin 
24534887Schin 	if (proto->flags & PASS)
24544887Schin 	{
24554887Schin 		if (proto->iz)
24564887Schin 		{
24574887Schin 			n = proto->iz;
24584887Schin 			proto->iz = 0;
24594887Schin 		}
24604887Schin 		else if (!(proto->flags & MORE)) n = 0;
24614887Schin 		else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz)
24624887Schin 		{
24634887Schin 			proto->flags &= ~MORE;
24644887Schin 			close(proto->fd);
24654887Schin 		}
24664887Schin 	}
24674887Schin 	else
24684887Schin 	{
24694887Schin 		if (proto->op == proto->ob)
24704887Schin 		{
24714887Schin 			if (proto->flags & ERROR) return -1;
24724887Schin #if PROTOMAIN
24734887Schin 			if (proto->flags & YACC)
24744887Schin 			{
24754887Schin 				register char*	ip = proto->ip;
24764887Schin 				register char*	op = proto->ob;
24774887Schin 				register char*	ep = proto->ob + proto->oz - 2;
24784887Schin 
24794887Schin 				if (!*ip)
24804887Schin 				{
24814887Schin 					ip = proto->ip = proto->ib;
24824887Schin 					if (!(proto->flags & MORE)) n = 0;
24834887Schin 					else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz)
24844887Schin 					{
24854887Schin 						if (n < 0) n = 0;
24864887Schin 						proto->flags &= ~MORE;
24874887Schin 						close(proto->fd);
24884887Schin 					}
24894887Schin 					ip[n] = 0;
24904887Schin 				}
24914887Schin 				if (proto->flags & YACCSPLIT)
24924887Schin 				{
24934887Schin 					proto->flags &= ~YACCSPLIT;
24944887Schin 					if (*ip == '%')
24954887Schin 					{
24964887Schin 						*op++ = *ip++;
24974887Schin 						if (proto->flags & YACC2) proto->flags &= ~YACC;
24984887Schin 						else proto->flags |= YACC2;
24994887Schin 					}
25004887Schin 				}
25014887Schin 				if (proto->flags & YACC)
25024887Schin 					while (op < ep && (n = *op++ = *ip))
25034887Schin 					{
25044887Schin 						ip++;
25054887Schin 						if (n == '%')
25064887Schin 						{
25074887Schin 							if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
25084887Schin 							{
25094887Schin 								*op++ = *ip++;
25104887Schin 								if (proto->flags & YACC2) proto->flags &= ~YACC;
25114887Schin 								else proto->flags |= YACC2;
25124887Schin 								break;
25134887Schin 							}
25144887Schin 							if (!*ip)
25154887Schin 							{
25164887Schin 								*op++ = '%';
25174887Schin 								proto->flags |= YACCSPLIT;
25184887Schin 								break;
25194887Schin 							}
25204887Schin 						}
25214887Schin 						else if (n == '\n') proto->line++;
25224887Schin 					}
25234887Schin 				proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
25244887Schin 				proto->ip = ip;
25254887Schin 			}
25264887Schin 			else
25274887Schin #endif
25284887Schin 			lex(proto, proto->flags);
25294887Schin 			if ((proto->flags & (ERROR|MORE)) == ERROR)
25304887Schin 				proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
25314887Schin 		}
25324887Schin 		n = proto->op - proto->ob;
25334887Schin 		proto->op = proto->ob;
25344887Schin 	}
25354887Schin 	return n;
25364887Schin }
25374887Schin 
25384887Schin #if !PROTOMAIN
25394887Schin 
25404887Schin /*
25414887Schin  * drop control of iob after first pppread()
25424887Schin  * return value is input fd
25434887Schin  * if fd<0 then all data in iob
25444887Schin  */
25454887Schin 
25464887Schin int
pppdrop(char * iob)25474887Schin pppdrop(char* iob)
25484887Schin {
25494887Schin 	register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
25504887Schin 
25514887Schin 	if (proto->flags & MORE)
25524887Schin 	{
25534887Schin 		proto->flags &= ~MORE;
25544887Schin 		return proto->fd;
25554887Schin 	}
25564887Schin 	return -1;
25574887Schin }
25584887Schin 
25594887Schin #endif
2560