1da2e3ebchin/***********************************************************************
2da2e3ebchin*                                                                      *
3da2e3ebchin*               This software is part of the ast package               *
434f9b3eRoland Mainz*          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebchin*                      and is licensed under the                       *
6da2e3ebchin*                  Common Public License, Version 1.0                  *
77c2fbfbApril Chin*                    by AT&T Intellectual Property                     *
8da2e3ebchin*                                                                      *
9da2e3ebchin*                A copy of the License is available at                 *
10da2e3ebchin*            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebchin*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebchin*                                                                      *
13da2e3ebchin*              Information and Software Systems Research               *
14da2e3ebchin*                            AT&T Research                             *
15da2e3ebchin*                           Florham Park NJ                            *
16da2e3ebchin*                                                                      *
17da2e3ebchin*                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebchin*                                                                      *
19da2e3ebchin***********************************************************************/
20da2e3ebchin#pragma prototyped
21da2e3ebchin/*
22da2e3ebchin * Glenn Fowler
23da2e3ebchin * AT&T Research
24da2e3ebchin *
25da2e3ebchin * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
26da2e3ebchin * slips into the pp block read
27da2e3ebchin *
28da2e3ebchin * define PROTOMAIN for standalone proto
29da2e3ebchin * PROTOMAIN is coded for minimal library support
30da2e3ebchin */
31da2e3ebchin
32da2e3ebchin#if PROTOMAIN
33da2e3ebchin
34da2e3ebchin#include "ppfsm.c"
35da2e3ebchin
36da2e3ebchin#include <hashkey.h>
37da2e3ebchin
38da2e3ebchin#if PROTO_STANDALONE
39da2e3ebchin#undef	O_RDONLY
40da2e3ebchin#endif
41da2e3ebchin
42da2e3ebchin#else
43da2e3ebchin
44da2e3ebchin#include "pplib.h"
45da2e3ebchin#include "ppfsm.h"
46da2e3ebchin
47da2e3ebchin#endif
48da2e3ebchin
49da2e3ebchin#define MAGICGEN	"/* : : generated by proto : : */\n"
50da2e3ebchin
51da2e3ebchin#define MAGICDIR	"pragma"	/* proto magic directive	*/
52da2e3ebchin#define MAGICARG	"prototyped"	/* proto magic directive arg	*/
53da2e3ebchin#define MAGICOFF	"noticed"	/* no notice if found in pragma	*/
54da2e3ebchin#define MAGICTOP	64		/* must be in these top lines	*/
55da2e3ebchin#define NOTICED		"Copyright"	/* no notice if found in magic	*/
567c2fbfbApril Chin#define PUBLICDOMAIN	"Public Domain"	/* no notice if found in magic	*/
57da2e3ebchin
58da2e3ebchinstruct proto				/* proto buffer state		*/
59da2e3ebchin{
60da2e3ebchin	int		brace;		/* {..} level			*/
61da2e3ebchin	int		call;		/* call level			*/
62da2e3ebchin	int		fd;		/* input file descriptor	*/
63da2e3ebchin	char*		file;		/* input file name		*/
64da2e3ebchin	long		flags;		/* coupled flags		*/
65da2e3ebchin	long		options;	/* uncoupled flags		*/
66da2e3ebchin	char*		package;	/* header package		*/
67da2e3ebchin	int		line;		/* input line count		*/
68da2e3ebchin	int		test;		/* testing			*/
69da2e3ebchin
70da2e3ebchin	char*		tp;		/* input token base		*/
71da2e3ebchin
72da2e3ebchin	int		iz;		/* input buffer size		*/
73da2e3ebchin	char*		ib;		/* input buffer base		*/
74da2e3ebchin	char*		ip;		/* input buffer pointer		*/
75da2e3ebchin
76da2e3ebchin	int		oz;		/* output buffer size		*/
77da2e3ebchin	char*		ob;		/* output buffer base		*/
78da2e3ebchin	char*		op;		/* output buffer pointer	*/
79da2e3ebchin	char*		ox;		/* output buffer externalize	*/
80da2e3ebchin
81da2e3ebchin	char		cc[3];		/* beg mid end comment char	*/
82da2e3ebchin	char		pushback[4];	/* pushback area for caller	*/
83da2e3ebchin
84da2e3ebchin	char		variadic[256];	/* variadic args buffer		*/
85da2e3ebchin
86da2e3ebchin	/* output buffer */
87da2e3ebchin	/* slide buffer */
88da2e3ebchin	/* input buffer */
89da2e3ebchin};
90da2e3ebchin
91da2e3ebchin/*
92da2e3ebchin * proto is separate from pp so these undef's are ok
93da2e3ebchin */
94da2e3ebchin
95da2e3ebchin#undef	CLASSIC
96da2e3ebchin#define CLASSIC		(1L<<0)
97da2e3ebchin#undef	DECLARE
98da2e3ebchin#define DECLARE		(1L<<1)
99da2e3ebchin#undef	DEFINE
100da2e3ebchin#define DEFINE		(1L<<2)
101da2e3ebchin#undef	DIRECTIVE
102da2e3ebchin#define DIRECTIVE	(1L<<3)
103da2e3ebchin#undef	ERROR
104da2e3ebchin#define ERROR		(1L<<4)
105da2e3ebchin#undef	EXTERN
106da2e3ebchin#define EXTERN		(1L<<5)
107da2e3ebchin#undef	EXTERNALIZE
108da2e3ebchin#define EXTERNALIZE	(1L<<6)
109da2e3ebchin#undef	IDID
110da2e3ebchin#define IDID		(1L<<7)
111da2e3ebchin#undef	INDIRECT
112da2e3ebchin#define INDIRECT	(1L<<8)
113da2e3ebchin#undef	INIT
114da2e3ebchin#define INIT		(1L<<9)
115da2e3ebchin#undef	INIT_DEFINE
116da2e3ebchin#define INIT_DEFINE	(1L<<10)
117da2e3ebchin#undef	INIT_INCLUDE
118da2e3ebchin#define INIT_INCLUDE	(1L<<11)
119da2e3ebchin#undef	JUNK
120da2e3ebchin#define JUNK		(1L<<12)
121da2e3ebchin#undef	LINESYNC
122da2e3ebchin#define LINESYNC	(1L<<13)
123da2e3ebchin#undef	MANGLE
124da2e3ebchin#define MANGLE		(1L<<14)
125da2e3ebchin#undef	MATCH
126da2e3ebchin#define MATCH		(1L<<15)
127da2e3ebchin#undef	MORE
128da2e3ebchin#define MORE		(1L<<16)
129da2e3ebchin#undef	OTHER
130da2e3ebchin#define OTHER		(1L<<17)
131da2e3ebchin#undef	PASS
132da2e3ebchin#define PASS		(1L<<18)
133da2e3ebchin#undef	PLUSONLY
134da2e3ebchin#define PLUSONLY	(1L<<19)
135da2e3ebchin#undef	PLUSPLUS
136da2e3ebchin#define PLUSPLUS	(1L<<20)
137da2e3ebchin#undef	RECURSIVE
138da2e3ebchin#define RECURSIVE	(1L<<21)
139da2e3ebchin#undef	SHARP
140da2e3ebchin#define SHARP		(1L<<22)
141da2e3ebchin#undef	SKIP
142da2e3ebchin#define SKIP		(1L<<23)
143da2e3ebchin#undef	SLIDE
144da2e3ebchin#define SLIDE		(1L<<24)
145da2e3ebchin#undef	TOKENS
146da2e3ebchin#define TOKENS		(1L<<25)
147da2e3ebchin#undef	TYPEDEF
148da2e3ebchin#define TYPEDEF		(1L<<26)
149da2e3ebchin#undef	VARIADIC
150da2e3ebchin#define VARIADIC	(1L<<27)
151da2e3ebchin#undef	VARIADIC2
152da2e3ebchin#define VARIADIC2	(1L<<28)
153da2e3ebchin#undef	YACC
154da2e3ebchin#define YACC		(1L<<29)
155da2e3ebchin#undef	YACCSPLIT
156da2e3ebchin#define YACCSPLIT	(1L<<30)
157da2e3ebchin#undef	YACC2
158da2e3ebchin#define YACC2		(1L<<31)
159da2e3ebchin
160da2e3ebchin#undef	GLOBAL
161da2e3ebchin#define GLOBAL		(MORE)
162da2e3ebchin
163da2e3ebchin#undef	REGULAR
164da2e3ebchin#define REGULAR		(1L<<0)
165da2e3ebchin
166da2e3ebchin#ifndef CHUNK
167da2e3ebchin#define CHUNK		1024
168da2e3ebchin#endif
169da2e3ebchin#define BLOCK		(8*CHUNK)
170da2e3ebchin
171da2e3ebchin#define T_VA_START	(N_TOKEN+1)
172da2e3ebchin
173da2e3ebchin#define RESERVED(b,e,n)	((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
174da2e3ebchin
175da2e3ebchin/*
176da2e3ebchin * generate integer
177da2e3ebchin * pointer to end returned
178da2e3ebchin */
179da2e3ebchin
180da2e3ebchinstatic char*
181da2e3ebchinnumber(register char* p, register long n)
182da2e3ebchin{
183da2e3ebchin	register long	d;
184da2e3ebchin
185da2e3ebchin	for (d = 1000000; d > 1; d /= 10)
186da2e3ebchin		if (n >= d) *p++ = '0' + (n / d) % 10;
187da2e3ebchin	*p++ = '0' + n % 10;
188da2e3ebchin	return p;
189da2e3ebchin}
190da2e3ebchin
191da2e3ebchin#if PROTOMAIN
192da2e3ebchin
193da2e3ebchinstatic int		errors;
194da2e3ebchin
195da2e3ebchin#if PROTO_STANDALONE
196da2e3ebchin
197da2e3ebchin/*
198da2e3ebchin * namespace pollution forces us to claim parts of libc
199da2e3ebchin */
200da2e3ebchin
201da2e3ebchin#undef	memcpy
202da2e3ebchin#define memcpy(t,f,n)	memcopy(t,f,n)
203da2e3ebchin#undef	strcpy
204da2e3ebchin#define strcpy(t,f)	strcopy(t,f)
205da2e3ebchin#undef	strlen
206da2e3ebchin#define strlen(s)	sstrlen(s)
207da2e3ebchin#undef	strncmp
208da2e3ebchin#define strncmp(s,t,n)	sstrncmp(s,t,n)
209da2e3ebchin
210da2e3ebchin/*
211da2e3ebchin * environmentally safe strlen()
212da2e3ebchin */
213da2e3ebchin
214da2e3ebchinstatic int
215da2e3ebchinsstrlen(register const char* s)
216da2e3ebchin{
217da2e3ebchin	register const char*	b;
218da2e3ebchin
219da2e3ebchin	for (b = s; *s; s++);
220da2e3ebchin	return s - b;
221da2e3ebchin}
222da2e3ebchin
223da2e3ebchin/*
224da2e3ebchin * environmentally safe strncmp()
225da2e3ebchin */
226da2e3ebchin
227da2e3ebchinstatic int
228da2e3ebchinsstrncmp(register const char* s, register char* t, register int n)
229da2e3ebchin{
230da2e3ebchin	register const char*	e = s + n;
231da2e3ebchin
232da2e3ebchin	while (s < e)
233da2e3ebchin	{
234da2e3ebchin		if (*s != *t || !*s)
235da2e3ebchin			return *s - *t;
236da2e3ebchin		s++;
237da2e3ebchin		t++;
238da2e3ebchin	}
239da2e3ebchin	return 0;
240da2e3ebchin}
241da2e3ebchin
242da2e3ebchin/*
243da2e3ebchin * strcpy() except pointer to end returned
244da2e3ebchin */
245da2e3ebchin
246da2e3ebchinstatic char*
247da2e3ebchinstrcopy(register char* s, register const char* t)
248da2e3ebchin{
249da2e3ebchin	while (*s++ = *t++);
250da2e3ebchin	return s - 1;
251da2e3ebchin}
252da2e3ebchin
253da2e3ebchin#endif
254da2e3ebchin
255da2e3ebchinstatic void
256da2e3ebchinproto_error(char* iob, int level, char* msg, char* arg)
257da2e3ebchin{
258da2e3ebchin	register char*	p;
259da2e3ebchin	char		buf[1024];
260da2e3ebchin
261da2e3ebchin	p = strcopy(buf, "proto: ");
262da2e3ebchin	if (iob)
263da2e3ebchin	{
264da2e3ebchin		register struct proto*	proto = (struct proto*)(iob - sizeof(struct proto));
265da2e3ebchin
266da2e3ebchin		if (proto->line)
267da2e3ebchin		{
268da2e3ebchin			if (proto->file)
269da2e3ebchin			{
270da2e3ebchin				*p++ = '"';
271da2e3ebchin				p = strcopy(p, proto->file);
272da2e3ebchin				*p++ = '"';
273da2e3ebchin				*p++ = ',';
274da2e3ebchin				*p++ = ' ';
275da2e3ebchin			}
276da2e3ebchin			p = strcopy(p, "line ");
277da2e3ebchin			p = number(p, proto->line);
278da2e3ebchin		}
279da2e3ebchin		else if (proto->file)
280da2e3ebchin			p = strcopy(p, proto->file);
281da2e3ebchin	}
282da2e3ebchin	else
283da2e3ebchin	{
284da2e3ebchin		p = strcopy(p, msg);
285da2e3ebchin		msg = arg;
286da2e3ebchin		arg = 0;
287da2e3ebchin	}
288da2e3ebchin	if (*(p - 1) != ' ')
289da2e3ebchin	{
290da2e3ebchin		*p++ = ':';
291da2e3ebchin		*p++ = ' ';
292da2e3ebchin	}
293da2e3ebchin	if (level == 1)
294da2e3ebchin		p = strcopy(p, "warning: ");
295da2e3ebchin	p = strcopy(p, msg);
296da2e3ebchin	if (arg)
297da2e3ebchin	{
298da2e3ebchin		*p++ = ' ';
299da2e3ebchin		p = strcopy(p, arg);
300da2e3ebchin	}
301da2e3ebchin	*p++ = '\n';
302da2e3ebchin	write(2, buf, p - buf);
303da2e3ebchin	if (level >= 3)
304da2e3ebchin		exit(level - 2);
305da2e3ebchin	if (level >= 2)
306da2e3ebchin		errors++;
307da2e3ebchin}
308da2e3ebchin
309da2e3ebchin/*
310da2e3ebchin * memcpy() but pointer to end returned
311da2e3ebchin */
312da2e3ebchin
313da2e3ebchinstatic char*
314da2e3ebchinmemcopy(register char* s, register char* t, int n)
315da2e3ebchin{
316da2e3ebchin	register char*	e = t + n;
317da2e3ebchin
318da2e3ebchin	while (t < e) *s++ = *t++;
319da2e3ebchin	return s;
320da2e3ebchin}
321da2e3ebchin
322da2e3ebchin#include "../libast/port/astlicense.c"
323da2e3ebchin
324da2e3ebchin#else
325da2e3ebchin
326da2e3ebchin#define memcopy(s,t,n)	(((char*)memcpy(s,t,n))+(n))
327da2e3ebchin
328da2e3ebchin#endif
329da2e3ebchin
330da2e3ebchin/*
331da2e3ebchin * generate line sync
332da2e3ebchin * pointer to end returned
333da2e3ebchin */
334da2e3ebchin
335da2e3ebchinstatic char*
336da2e3ebchinlinesync(register struct proto* proto, register char* p, register long n)
337da2e3ebchin{
338da2e3ebchin#if PROTOMAIN
339da2e3ebchin	if (proto->flags & LINESYNC)
340da2e3ebchin#endif
341da2e3ebchin	{
342da2e3ebchin#if PROTOMAIN
343da2e3ebchin		p = strcopy(p, "\n#line ");
344da2e3ebchin#else
345da2e3ebchin		p = strcopy(p, "\n# ");
346da2e3ebchin#endif
347da2e3ebchin		p = number(p, n);
348da2e3ebchin		*p++ = '\n';
349da2e3ebchin	}
350da2e3ebchin	return p;
351da2e3ebchin}
352da2e3ebchin
353da2e3ebchin/*
354da2e3ebchin * output init header
355da2e3ebchin * pointer to end returned
356da2e3ebchin */
357da2e3ebchin
358da2e3ebchinstatic char*
359da2e3ebchininit(struct proto* proto, char* op, int flags)
360da2e3ebchin{
361da2e3ebchin	register char*	s;
362da2e3ebchin
363da2e3ebchin	if (flags & INIT_DEFINE)
364da2e3ebchin	{
365da2e3ebchin		op = strcopy(op, "\
366da2e3ebchin\n\
367da2e3ebchin#if !defined(__PROTO__)\n\
368da2e3ebchin#  if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
369da2e3ebchin#    if defined(__cplusplus)\n\
370da2e3ebchin#      define __LINKAGE__	\"C\"\n\
371da2e3ebchin#    else\n\
372da2e3ebchin#      define __LINKAGE__\n\
373da2e3ebchin#    endif\n\
374da2e3ebchin#    define __STDARG__\n\
375da2e3ebchin#    define __PROTO__(x)	x\n\
376da2e3ebchin#    define __OTORP__(x)\n\
377da2e3ebchin#    define __PARAM__(n,o)	n\n\
378da2e3ebchin#    if !defined(__STDC__) && !defined(__cplusplus)\n\
379da2e3ebchin#      if !defined(c_plusplus)\n\
380da2e3ebchin#      	define const\n\
381da2e3ebchin#      endif\n\
382da2e3ebchin#      define signed\n\
383da2e3ebchin#      define void		int\n\
384da2e3ebchin#      define volatile\n\
385da2e3ebchin#      define __V_		char\n\
386da2e3ebchin#    else\n\
387da2e3ebchin#      define __V_		void\n\
388da2e3ebchin#    endif\n\
389da2e3ebchin#  else\n\
390da2e3ebchin#    define __PROTO__(x)	()\n\
391da2e3ebchin#    define __OTORP__(x)	x\n\
392da2e3ebchin#    define __PARAM__(n,o)	o\n\
393da2e3ebchin#    define __LINKAGE__\n\
394da2e3ebchin#    define __V_		char\n\
395da2e3ebchin#    define const\n\
396da2e3ebchin#    define signed\n\
397da2e3ebchin#    define void		int\n\
398da2e3ebchin#    define volatile\n\
399da2e3ebchin#  endif\n\
400da2e3ebchin#  define __MANGLE__	__LINKAGE__\n\
401da2e3ebchin#  if defined(__cplusplus) || defined(c_plusplus)\n\
402da2e3ebchin#    define __VARARG__	...\n\
403da2e3ebchin#  else\n\
404da2e3ebchin#    define __VARARG__\n\
405da2e3ebchin#  endif\n\
406da2e3ebchin#  if defined(__STDARG__)\n\
407da2e3ebchin#    define __VA_START__(p,a)	va_start(p,a)\n\
408da2e3ebchin#  else\n\
409da2e3ebchin#    define __VA_START__(p,a)	va_start(p)\n\
410da2e3ebchin#  endif\n\
411da2e3ebchin#  if !defined(__INLINE__)\n\
412da2e3ebchin#    if defined(__cplusplus)\n\
413da2e3ebchin#      define __INLINE__	extern __MANGLE__ inline\n\
414da2e3ebchin#    else\n\
415da2e3ebchin#      if defined(_WIN32) && !defined(__GNUC__)\n\
416da2e3ebchin#      	define __INLINE__	__inline\n\
417da2e3ebchin#      endif\n\
418da2e3ebchin#    endif\n\
419da2e3ebchin#  endif\n\
420da2e3ebchin#endif\n\
421da2e3ebchin#if !defined(__LINKAGE__)\n\
422da2e3ebchin#define __LINKAGE__		/* 2004-08-11 transition */\n\
423da2e3ebchin#endif\n\
424da2e3ebchin");
425da2e3ebchin	}
426da2e3ebchin	else
427da2e3ebchin		op = strcopy(op, "\
428da2e3ebchin\n\
429da2e3ebchin#if !defined(__PROTO__)\n\
430da2e3ebchin#include <prototyped.h>\n\
431da2e3ebchin#endif\n\
432da2e3ebchin#if !defined(__LINKAGE__)\n\
433da2e3ebchin#define __LINKAGE__		/* 2004-08-11 transition */\n\
434da2e3ebchin#endif\n\
435da2e3ebchin");
436da2e3ebchin	if (proto->package)
437da2e3ebchin	{
438da2e3ebchin		s = "\
439da2e3ebchin#ifndef	__MANGLE_%_DATA__\n\
440da2e3ebchin#  ifdef _BLD_%\n\
441da2e3ebchin#    ifdef __EXPORT__\n\
442da2e3ebchin#      define	__MANGLE_%_DATA__	__MANGLE__ __EXPORT__\n\
443da2e3ebchin#    else\n\
444da2e3ebchin#      define	__MANGLE_%_DATA__	__MANGLE__\n\
445da2e3ebchin#    endif\n\
446da2e3ebchin#    define	__MANGLE_%_FUNC__	__MANGLE__\n\
447da2e3ebchin#  else\n\
448da2e3ebchin#    ifdef __IMPORT__\n\
449da2e3ebchin#      define	__MANGLE_%_DATA__	__MANGLE__ __IMPORT__\n\
450da2e3ebchin#    else\n\
451da2e3ebchin#      define	__MANGLE_%_DATA__	__MANGLE__\n\
452da2e3ebchin#    endif\n\
453da2e3ebchin#    define	__MANGLE_%_FUNC__	__MANGLE__\n\
454da2e3ebchin#  endif\n\
455da2e3ebchin#endif\n\
456da2e3ebchin";
457da2e3ebchin		for (;;)
458da2e3ebchin		{
459da2e3ebchin			switch (*op++ = *s++)
460da2e3ebchin			{
461da2e3ebchin			case 0:
462da2e3ebchin				op--;
463da2e3ebchin				break;
464da2e3ebchin			case '%':
465da2e3ebchin				op = strcopy(op - 1, proto->package);
466da2e3ebchin				continue;
467da2e3ebchin			default:
468da2e3ebchin				continue;
469da2e3ebchin			}
470da2e3ebchin			break;
471da2e3ebchin		}
472da2e3ebchin	}
473da2e3ebchin	return op;
474da2e3ebchin}
475da2e3ebchin
476da2e3ebchin#define BACKOUT()	(op=ko)
477da2e3ebchin#define CACHE()		do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
478da2e3ebchin#define CACHEIN()	(ip=proto->ip)
479da2e3ebchin#define CACHEOUT()	(op=proto->op)
480da2e3ebchin#define GETCHR()	(*(unsigned char*)ip++)
481da2e3ebchin#define KEEPOUT()	(ko=op)
482da2e3ebchin#define LASTOUT()	(*(op-1))
483da2e3ebchin#define PUTCHR(c)	(*op++=(c))
484da2e3ebchin#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)
485da2e3ebchin#define SYNCIN()	(proto->ip=ip)
486da2e3ebchin#define SYNCOUT()	(proto->op=op)
487da2e3ebchin#define UNGETCHR()	(ip--)
488da2e3ebchin#define UNPUTCHR()	(op--)
489da2e3ebchin
490da2e3ebchin/*
491da2e3ebchin * advance to the next non-space character
492da2e3ebchin */
493da2e3ebchin
494da2e3ebchinstatic char*
495da2e3ebchinnns(register char* s)
496da2e3ebchin{
497da2e3ebchin	while (*s == ' ' || *s == '\t' || *s == '\n')
498da2e3ebchin		s++;
499da2e3ebchin	return s;
500da2e3ebchin}
501da2e3ebchin
502da2e3ebchin#define DIR_if	01
503da2e3ebchin#define DIR_el	02
504da2e3ebchin#define DIR_en	03
505da2e3ebchin#define DIR	03
506da2e3ebchin
507da2e3ebchin/*
508da2e3ebchin * update directive mask
509da2e3ebchin */
510da2e3ebchin
511da2e3ebchinstatic int
512da2e3ebchindirective(register char* s, int dir)
513da2e3ebchin{
514da2e3ebchin	switch (*(s = nns(s)))
515da2e3ebchin	{
516da2e3ebchin	case 'e':
517da2e3ebchin	case 'i':
518da2e3ebchin		dir <<= 2;
519da2e3ebchin		switch (*++s)
520da2e3ebchin		{
521da2e3ebchin		case 'f':
522da2e3ebchin			dir |= DIR_if;
523da2e3ebchin			break;
524da2e3ebchin		case 'l':
525da2e3ebchin			dir |= DIR_el;
526da2e3ebchin			break;
527da2e3ebchin		case 'n':
528da2e3ebchin			dir |= DIR_en;
529da2e3ebchin			break;
530da2e3ebchin		}
531da2e3ebchin		break;
532da2e3ebchin	}
533da2e3ebchin	return dir;
534da2e3ebchin}
535da2e3ebchin
536da2e3ebchin/*
537da2e3ebchin * the tokenizer
538da2e3ebchin * top level calls loop until EOB
539da2e3ebchin * recursive calls just return the next token
540da2e3ebchin */
541da2e3ebchin
542da2e3ebchinstatic int
543da2e3ebchinlex(register struct proto* proto, register long flags)
544da2e3ebchin{
545da2e3ebchin	register char*		ip;
546da2e3ebchin	register char*		op;
547da2e3ebchin	register int		c;
548da2e3ebchin	register int		state;
549da2e3ebchin	register short*		rp;
550da2e3ebchin	char*			m;
551da2e3ebchin	char*			e;
552da2e3ebchin	char*			t;
553da2e3ebchin	char*			bp;
554da2e3ebchin	char*			v;
555da2e3ebchin	char*			im;
556da2e3ebchin	char*			ko;
557da2e3ebchin	char*			aom;
558da2e3ebchin	int			n;
559da2e3ebchin	int			line;
560da2e3ebchin	int			quot;
561da2e3ebchin	int			brack;
562da2e3ebchin	int			sub;
563da2e3ebchin	int			x;
564da2e3ebchin	int			vc;
565da2e3ebchin
566da2e3ebchin	char*			ie = 0;
567da2e3ebchin	char*			om = 0;
568da2e3ebchin	char*			aim = 0;
569da2e3ebchin	char*			aie = 0;
570da2e3ebchin	char*			func = 0;
571da2e3ebchin	int			call = 0;
572da2e3ebchin	int			dir = 0;
573da2e3ebchin	int			group = 0;
574da2e3ebchin	int			last = 0;
575da2e3ebchin	int			paren = 0;
576da2e3ebchin#if PROTOMAIN
577da2e3ebchin	char*			qe = 0;
578da2e3ebchin	int			qn = 0;
579da2e3ebchin	int			args = 0;
580da2e3ebchin#endif
581da2e3ebchin
582da2e3ebchin	CACHE();
583da2e3ebchin#if PROTOMAIN
584da2e3ebchin	if (flags & EXTERN) KEEPOUT();
585da2e3ebchin#endif
586da2e3ebchin fsm_start:
587da2e3ebchin	proto->tp = ip;
588da2e3ebchin	state = PROTO;
589da2e3ebchin	bp = ip;
590da2e3ebchin	do
591da2e3ebchin	{
592da2e3ebchin		rp = fsm[state];
593da2e3ebchin fsm_get:
594da2e3ebchin		while (!(state = rp[c = GETCHR()]));
595da2e3ebchin fsm_next:
596da2e3ebchin		;
597da2e3ebchin	} while (state > 0);
598da2e3ebchin	if ((n = ip - bp - 1) > 0)
599da2e3ebchin	{
600da2e3ebchin		ip = bp;
601da2e3ebchin		MEMCPY(op, ip, n);
602da2e3ebchin		ip++;
603da2e3ebchin	}
604da2e3ebchin	state = ~state;
605da2e3ebchin fsm_terminal:
606da2e3ebchin	switch (TERM(state))
607da2e3ebchin	{
608da2e3ebchin	case S_CHR:
609da2e3ebchin		if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
610da2e3ebchin		{
611da2e3ebchin		case '+':
612da2e3ebchin		case '-':
613da2e3ebchin		case '*':
614da2e3ebchin		case '&':
615da2e3ebchin			PUTCHR(' ');
616da2e3ebchin			break;
617da2e3ebchin		}
618da2e3ebchin		PUTCHR(c);
619da2e3ebchin		break;
620da2e3ebchin
621da2e3ebchin	case S_CHRB:
622da2e3ebchin		UNGETCHR();
623da2e3ebchin		c = LASTOUT();
624da2e3ebchin		break;
625da2e3ebchin
626da2e3ebchin	case S_COMMENT:
627da2e3ebchin		switch (c)
628da2e3ebchin		{
629da2e3ebchin		case '\n':
630da2e3ebchin			if (INCOMMENTXX(rp)) goto fsm_newline;
631da2e3ebchin			PUTCHR(c);
632da2e3ebchin			proto->line++;
633da2e3ebchin			rp = fsm[COM2];
634da2e3ebchin			break;
635da2e3ebchin		case '/':
636da2e3ebchin#if PROTOMAIN
637da2e3ebchin			if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
638da2e3ebchin			else
639da2e3ebchin#endif
640da2e3ebchin			PUTCHR(c);
641