xref: /titanic_44/usr/src/lib/libpp/common/ppfsm.c (revision 34f9b3eef6fdadbda0a846aa4d68691ac40eace5)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*34f9b3eeSRoland Mainz *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * preprocessor and proto lexical analyzer fsm
26da2e3ebdSchin  * define PROTOMAIN for standalone proto
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin #include "pplib.h"
30da2e3ebdSchin #include "ppfsm.h"
31da2e3ebdSchin 
32da2e3ebdSchin /*
33da2e3ebdSchin  * lexical FSM encoding
34da2e3ebdSchin  * derived from a standalone ansi cpp by Dennis Ritchie
35da2e3ebdSchin  * modified for libpp by Glenn Fowler
36da2e3ebdSchin  *
37da2e3ebdSchin  *   fsm[] is initialized from fsminit[].  The encoding is blown out into
38da2e3ebdSchin  *   fsm[] for time efficiency.  When in state state, and one of the
39da2e3ebdSchin  *   characters in ch arrives, enter nextstate.  States >= TERMINAL are
40da2e3ebdSchin  *   either final, or at least require special action.  In fsminit[] there
41da2e3ebdSchin  *   is a line for each <state,charset,nextstate>.  Early entries are
42da2e3ebdSchin  *   overwritten by later ones.  C_XXX is the universal set and should
43da2e3ebdSchin  *   always be first.  Some of the fsminit[] entries are templates for
44da2e3ebdSchin  *   groups of states.  The OP entries trigger the state copies.  States
45da2e3ebdSchin  *   above TERMINAL are represented in fsm[] as negative values.  S_TOK and
46da2e3ebdSchin  *   S_TOKB encode the resulting token type in the upper bits.  These actions
47da2e3ebdSchin  *   differ in that S_TOKB has a lookahead char.
48da2e3ebdSchin  *
49da2e3ebdSchin  *   fsm[] has three start states:
50da2e3ebdSchin  *
51da2e3ebdSchin  *	PROTO	proto (ANSI -> K&R,C++,ANSI)
52da2e3ebdSchin  *	QUICK	standalone ppcpp()
53da2e3ebdSchin  *	TOKEN	tokenizing pplex()
54da2e3ebdSchin  *
55da2e3ebdSchin  *   If the next state remains the same then the fsm[] transition value is 0.
56da2e3ebdSchin  *   MAX+1 is a power of 2 so that fsm[state][EOF==MAX+1] actually accesses
57da2e3ebdSchin  *   fsm[state+1][0] which is ~S_EOB for all states.  This preserves the
58da2e3ebdSchin  *   power of 2 fsm[] row size for efficient array indexing.  Thanks to
59da2e3ebdSchin  *   D. G. Korn for the last two observations.  The pseudo non-terminal state
60da2e3ebdSchin  *   fsm[TERMINAL][state+1] is used to differentiate EOB from EOF.
61da2e3ebdSchin  *
62da2e3ebdSchin  *   The bit layout is:
63da2e3ebdSchin  *
64da2e3ebdSchin  *	TERM	arg	SPLICE	next
65da2e3ebdSchin  *	15	14-8	7	6-0
66da2e3ebdSchin  */
67da2e3ebdSchin 
68da2e3ebdSchin /*
69da2e3ebdSchin  * NOTE: these must be `control' characters for all native codesets
70da2e3ebdSchin  *       currently ok for {ascii,ebcdic1,ebcdic2,ebcdic3}
71da2e3ebdSchin  */
72da2e3ebdSchin 
73da2e3ebdSchin #define C_DEC		001
74da2e3ebdSchin #define C_EOF		002
75da2e3ebdSchin #define C_HEX		003
76da2e3ebdSchin #define C_LET		021
77da2e3ebdSchin #define C_OCT		022
78da2e3ebdSchin #define C_XXX		023
79da2e3ebdSchin 
80da2e3ebdSchin #define OP		(-1)
81da2e3ebdSchin #define END		0
82da2e3ebdSchin #define COPY		1
83da2e3ebdSchin 
84da2e3ebdSchin #define copy(t,f)	(memcpy(&fsm[t][1],&fsm[f][1],(MAX+1)*sizeof(short)),fsm[TERMINAL][(t)+1]=fsm[TERMINAL][(f)+1])
85da2e3ebdSchin 
86da2e3ebdSchin struct fsminit				/* fsm initialization row	*/
87da2e3ebdSchin {
88da2e3ebdSchin 	int		state;		/* if in this state		*/
89da2e3ebdSchin 	unsigned char	ch[4];		/* and see one of these		*/
90da2e3ebdSchin 	int		nextstate;	/* enter this state if <TERMINAL*/
91da2e3ebdSchin };
92da2e3ebdSchin 
93da2e3ebdSchin static struct fsminit	fsminit[] =
94da2e3ebdSchin {
95da2e3ebdSchin 	/* proto start state */
96da2e3ebdSchin 	{	PROTO,	{ C_XXX },		S_CHR,			},
97da2e3ebdSchin 	{	PROTO,	{ C_EOF },		S_EOF,			},
98da2e3ebdSchin 	{	PROTO,	{ C_DEC },		BAD1,			},
99da2e3ebdSchin 	{	PROTO,	{ '.' },		DOT,			},
100da2e3ebdSchin 	{	PROTO,	{ C_LET },		NID,			},
101da2e3ebdSchin 	{	PROTO,	{ 'L' },		LIT,			},
102da2e3ebdSchin 	{	PROTO,	{ 'd', 'e', 'f', 'i' },	RES1,			},
103da2e3ebdSchin 	{	PROTO,	{ 'r', 's', 't', 'v' },	RES1,			},
104da2e3ebdSchin 	{	PROTO,	{ 'w', 'N' },		RES1,			},
105da2e3ebdSchin 	{	PROTO,	{ '"', '\'' },		S_LITBEG,		},
106da2e3ebdSchin 	{	PROTO,	{ '/' },		COM1,			},
107da2e3ebdSchin 	{	PROTO,	{ '\n' },		S_NL,			},
108da2e3ebdSchin 	{	PROTO,	{ ' ','\t','\f','\v' },	WS1,			},
109da2e3ebdSchin 
110da2e3ebdSchin /* proto {do,else,extern,for,if,inline,return,static,typedef,va_start,void,while,NoN} */
111da2e3ebdSchin 	{	RES1,	{ C_XXX },		S_MACRO,		},
112da2e3ebdSchin 	{	RES1,	{ C_LET, C_DEC },	NID,			},
113da2e3ebdSchin 	{	RES1,	{ 'a' },		RES1a,			},
114da2e3ebdSchin 	{	RES1,	{ 'e' },		RES1e,			},
115da2e3ebdSchin 	{	RES1,	{ 'f' },		RES1f,			},
116da2e3ebdSchin 	{	RES1,	{ 'h' },		RES1h,			},
117da2e3ebdSchin 	{	RES1,	{ 'l' },		RES1l,			},
118da2e3ebdSchin 	{	RES1,	{ 'n' },		RES1n,			},
119da2e3ebdSchin 	{	RES1,	{ 'o' },		RES1o,			},
120da2e3ebdSchin 	{	RES1,	{ 't' },		RES1t,			},
121da2e3ebdSchin 	{	RES1,	{ 'x' },		RES1x,			},
122da2e3ebdSchin 	{	RES1,	{ 'y' },		RES1y,			},
123da2e3ebdSchin 
124da2e3ebdSchin 	/* proto reserved {va_start} */
125da2e3ebdSchin 	{	RES1a,	{ C_XXX },		S_RESERVED,		},
126da2e3ebdSchin 	{	RES1a,	{ C_LET, C_DEC },	NID,			},
127da2e3ebdSchin 	{	RES1a,	{ '_','s','t','a' },	RES1a,			},
128da2e3ebdSchin 	{	RES1a,	{ 'r' },		RES1a,			},
129da2e3ebdSchin 
130da2e3ebdSchin 	/* proto reserved {return} */
131da2e3ebdSchin 	{	RES1e,	{ C_XXX },		S_RESERVED,		},
132da2e3ebdSchin 	{	RES1e,	{ C_LET, C_DEC },	NID,			},
133da2e3ebdSchin 	{	RES1e,	{ 't','u','r','n' },	RES1e,			},
134da2e3ebdSchin 
135da2e3ebdSchin 	/* proto reserved {if} */
136da2e3ebdSchin 	{	RES1f,	{ C_XXX },		S_RESERVED,		},
137da2e3ebdSchin 	{	RES1f,	{ C_LET, C_DEC },	NID,			},
138da2e3ebdSchin 
139da2e3ebdSchin 	/* proto reserved {while} */
140da2e3ebdSchin 	{	RES1h,	{ C_XXX },		S_RESERVED,		},
141da2e3ebdSchin 	{	RES1h,	{ C_LET, C_DEC },	NID,			},
142da2e3ebdSchin 	{	RES1h,	{ 'i','l','e' },	RES1h,			},
143da2e3ebdSchin 
144da2e3ebdSchin 	/* proto reserved {else} */
145da2e3ebdSchin 	{	RES1l,	{ C_XXX },		S_RESERVED,		},
146da2e3ebdSchin 	{	RES1l,	{ C_LET, C_DEC },	NID,			},
147da2e3ebdSchin 	{	RES1l,	{ 's','e' },		RES1l,			},
148da2e3ebdSchin 
149da2e3ebdSchin 	/* proto reserved {inline} */
150da2e3ebdSchin 	{	RES1n,	{ C_XXX },		S_RESERVED,		},
151da2e3ebdSchin 	{	RES1n,	{ C_LET, C_DEC },	NID,			},
152da2e3ebdSchin 	{	RES1n,	{ 'l','i','n','e' },	RES1n,			},
153da2e3ebdSchin 
154da2e3ebdSchin 	/* proto reserved {do,for,void} */
155da2e3ebdSchin 	{	RES1o,	{ C_XXX },		S_RESERVED,		},
156da2e3ebdSchin 	{	RES1o,	{ C_LET, C_DEC },	NID,			},
157da2e3ebdSchin 	{	RES1o,	{ 'r','i','d','N' },	RES1o,			},
158da2e3ebdSchin 
159da2e3ebdSchin 	/* proto reserved {static} */
160da2e3ebdSchin 	{	RES1t,	{ C_XXX },		S_RESERVED,		},
161da2e3ebdSchin 	{	RES1t,	{ C_LET, C_DEC },	NID,			},
162da2e3ebdSchin 	{	RES1t,	{ 'a','t','i','c' },	RES1t,			},
163da2e3ebdSchin 
164da2e3ebdSchin 	/* proto reserved {extern} */
165da2e3ebdSchin 	{	RES1x,	{ C_XXX },		S_RESERVED,		},
166da2e3ebdSchin 	{	RES1x,	{ C_LET, C_DEC },	NID,			},
167da2e3ebdSchin 	{	RES1x,	{ 't','e','r','n' },	RES1x,			},
168da2e3ebdSchin 
169da2e3ebdSchin 	/* proto reserved {typedef} */
170da2e3ebdSchin 	{	RES1y,	{ C_XXX },		S_RESERVED,		},
171da2e3ebdSchin 	{	RES1y,	{ C_LET, C_DEC },	NID,			},
172da2e3ebdSchin 	{	RES1y,	{ 'p','e','d','f' },	RES1y,			},
173da2e3ebdSchin 
174da2e3ebdSchin 	/* saw /, perhaps start of comment */
175da2e3ebdSchin 	{	COM1,	{ C_XXX },		S_CHRB,			},
176da2e3ebdSchin 	{	COM1,	{ '*' },		COM2,			},
177da2e3ebdSchin #if PROTOMAIN
178da2e3ebdSchin 	{	COM1,	{ '/' },		COM5,			},
179da2e3ebdSchin #endif
180da2e3ebdSchin 
181da2e3ebdSchin 	/* saw / *, start of comment */
182da2e3ebdSchin 	{	COM2,	{ C_XXX },		COM2,			},
183da2e3ebdSchin 	{	COM2,	{ '\n', C_EOF },	S_COMMENT,		},
184da2e3ebdSchin 	{	COM2,	{ '/' },		COM4,			},
185da2e3ebdSchin 	{	COM2,	{ '*' },		COM3,			},
186da2e3ebdSchin 	{	COM2,	{ '#', ';', ')' },	QUAL(COM2),		},
187da2e3ebdSchin 
188da2e3ebdSchin 	/* saw the * possibly ending a comment */
189da2e3ebdSchin 	{	COM3,	{ C_XXX },		COM2,			},
190da2e3ebdSchin 	{	COM3,	{ '\n', C_EOF },	S_COMMENT,		},
191da2e3ebdSchin 	{	COM3,	{ '#', ';', ')' },	QUAL(COM2),		},
192da2e3ebdSchin 	{	COM3,	{ '*' },		COM3,			},
193da2e3ebdSchin 	{	COM3,	{ '/' },		S_COMMENT,		},
194da2e3ebdSchin 
195da2e3ebdSchin 	/* saw / in / * comment, possible malformed nest */
196da2e3ebdSchin 	{	COM4,	{ C_XXX },		COM2,			},
197da2e3ebdSchin 	{	COM4,	{ '*', '\n', C_EOF },	S_COMMENT,		},
198da2e3ebdSchin 	{	COM4,	{ '/' },		COM4,			},
199da2e3ebdSchin 
200da2e3ebdSchin 	/* saw / /, start of comment */
201da2e3ebdSchin 	{	COM5,	{ C_XXX },		COM5,			},
202da2e3ebdSchin 	{	COM5,	{ '\n', C_EOF },	S_COMMENT,		},
203da2e3ebdSchin 	{	COM5,	{ '/' },		COM6,			},
204da2e3ebdSchin 	{	COM5,	{ '*' },		COM7,			},
205da2e3ebdSchin 
206da2e3ebdSchin 	/* saw / in / / comment, possible malformed nest */
207da2e3ebdSchin 	{	COM6,	{ C_XXX },		COM5,			},
208da2e3ebdSchin 	{	COM6,	{ '*', '\n', C_EOF },	S_COMMENT,		},
209da2e3ebdSchin 	{	COM6,	{ '/' },		COM6,			},
210da2e3ebdSchin 
211da2e3ebdSchin 	/* saw * in / /, possible malformed nest */
212da2e3ebdSchin 	{	COM7,	{ C_XXX },		COM5,			},
213da2e3ebdSchin 	{	COM7,	{ '\n', C_EOF },	S_COMMENT,		},
214da2e3ebdSchin 	{	COM7,	{ '*' },		COM7,			},
215da2e3ebdSchin 	{	COM7,	{ '/' },		S_COMMENT,		},
216da2e3ebdSchin 
217da2e3ebdSchin 	/* normal identifier -- always a macro candidate */
218da2e3ebdSchin 	{	NID,	{ C_XXX },		S_MACRO,		},
219da2e3ebdSchin 	{	NID,	{ C_LET, C_DEC },	NID,			},
220da2e3ebdSchin 
221da2e3ebdSchin 	/* saw ., operator or dbl constant */
222da2e3ebdSchin 	{	DOT,	{ C_XXX },		S_CHRB,			},
223da2e3ebdSchin 	{	DOT,	{ '.' },		DOT2,			},
224da2e3ebdSchin 	{	DOT,	{ C_DEC },		BAD1,			},
225da2e3ebdSchin 
226da2e3ebdSchin 	/* saw .., possible ... */
227da2e3ebdSchin 	{	DOT2,	{ C_XXX },		BACK(T_INVALID),	},
228da2e3ebdSchin 	{	DOT2,	{ '.' },		KEEP(T_VARIADIC),	},
229da2e3ebdSchin 
230da2e3ebdSchin 	/* saw L (possible start of normal wide literal) */
231da2e3ebdSchin 	{	LIT,	{ C_XXX },		S_MACRO,		},
232da2e3ebdSchin 	{	LIT,	{ C_LET, C_DEC },	NID,			},
233da2e3ebdSchin 	{	LIT,	{ '"', '\'' },		QUAL(LIT1),		},
234da2e3ebdSchin 
235da2e3ebdSchin 	/* saw " or ' beginning literal */
236da2e3ebdSchin 	{	LIT1,	{ C_XXX },		LIT1,			},
237da2e3ebdSchin 	{	LIT1,	{ '"', '\'' },		S_LITEND,		},
238da2e3ebdSchin 	{	LIT1,	{ '\n', C_EOF },	S_LITEND,		},
239da2e3ebdSchin 	{	LIT1,	{ '\\' },		LIT2,			},
240da2e3ebdSchin 
241da2e3ebdSchin 	/* saw \ in literal */
242da2e3ebdSchin 	{	LIT2,	{ C_XXX },		S_LITESC,		},
243da2e3ebdSchin 	{	LIT2,	{ '\n', C_EOF },	S_LITEND,		},
244da2e3ebdSchin 
245da2e3ebdSchin 	/* eat malformed numeric constant */
246da2e3ebdSchin 	{	BAD1,	{ C_XXX },		BACK(T_INVALID),	},
247da2e3ebdSchin 	{	BAD1,	{ C_LET, C_DEC, '.' },	BAD1,			},
248da2e3ebdSchin 	{	BAD1,	{ 'e', 'E' },		BAD2,			},
249da2e3ebdSchin 
250da2e3ebdSchin 	/* eat malformed numeric fraction|exponent */
251da2e3ebdSchin 	{	BAD2,	{ C_XXX },		BACK(T_INVALID),	},
252da2e3ebdSchin 	{	BAD2,	{ C_LET, C_DEC, '.' },	BAD1,			},
253da2e3ebdSchin 	{	BAD2,	{ '+', '-' },		BAD1,			},
254da2e3ebdSchin 
255da2e3ebdSchin 	/* saw white space, eat it up */
256da2e3ebdSchin 	{	WS1,	{ C_XXX },		S_WS,			},
257da2e3ebdSchin 	{	WS1,	{ ' ', '\t' },		WS1,			},
258da2e3ebdSchin 	{	WS1,	{ '\f', '\v' },		S_VS,			},
259da2e3ebdSchin 
260da2e3ebdSchin #if !PROTOMAIN
261da2e3ebdSchin 
262da2e3ebdSchin 	/* quick template */
263da2e3ebdSchin 	{	QUICK,	{ C_XXX },		QTOK,			},
264da2e3ebdSchin 	{	QUICK,	{ C_EOF, MARK },	S_CHRB,			},
265da2e3ebdSchin 	{	QUICK,	{ C_LET, C_DEC },	QID,			},
266da2e3ebdSchin 	{	QUICK,	{ 'L' },		LIT0,			},
267da2e3ebdSchin 	{	QUICK,	{ '"', '\'' },		S_LITBEG,		},
268da2e3ebdSchin 	{	QUICK,	{ '/' },		S_CHRB,			},
269da2e3ebdSchin 	{	QUICK,	{ '*' },		QCOM,			},
270da2e3ebdSchin 	{	QUICK,	{ '#' },		SHARP1,			},
271da2e3ebdSchin 	{	QUICK,	{ '\n' },		S_NL,			},
272da2e3ebdSchin 	{	QUICK,	{ '\f', '\v' },		S_VS,			},
273da2e3ebdSchin 
274da2e3ebdSchin 	/* copy QUICK to QUICK+1 through MAC0+1 */
275da2e3ebdSchin 	{	OP,	{QUICK,QUICK+1,MAC0+1},	COPY,			},
276da2e3ebdSchin 
277da2e3ebdSchin 	/* quick start state */
278da2e3ebdSchin 	{	QUICK,	{ C_EOF },		S_EOF,			},
279da2e3ebdSchin 	{	QUICK,	{ C_DEC },		QNUM,			},
280da2e3ebdSchin 	{	QUICK,	{ MARK },		QTOK,			},
281da2e3ebdSchin 	{	QUICK,	{ '/' },		COM1,			},
282da2e3ebdSchin 	{	QUICK,	{ ' ', '\t' },		QUICK,			},
283da2e3ebdSchin 
284da2e3ebdSchin 	/* grab non-macro tokens */
285da2e3ebdSchin 	{	QTOK,	{ C_DEC },		QNUM,			},
286da2e3ebdSchin 
287da2e3ebdSchin 	/* grab numeric and invalid tokens */
288da2e3ebdSchin 	{	QNUM,	{ C_LET, C_DEC, '.' },	QNUM,			},
289da2e3ebdSchin 	{	QNUM,	{ 'e', 'E' },		QEXP,			},
290da2e3ebdSchin 
291da2e3ebdSchin 	/* grab exponent token */
292da2e3ebdSchin 	{	QEXP,	{ C_LET, C_DEC, '.' },	QNUM,			},
293da2e3ebdSchin 	{	QEXP,	{ '+', '-' },		QNUM,			},
294da2e3ebdSchin 
295da2e3ebdSchin 	/* saw *, grab possible bad comment terminator */
296da2e3ebdSchin 	{	QCOM,	{ C_DEC },		QNUM,			},
297da2e3ebdSchin 	{	QCOM,	{ '/' },		S_COMMENT,		},
298da2e3ebdSchin 
299da2e3ebdSchin 	/* saw L (possible start of wide string or first macro char) */
300da2e3ebdSchin 	{	MAC0,	{ 'L' },		QID,			},
301da2e3ebdSchin 	{	MAC0,	{ '"', '\'' },		QUAL(LIT1),		},
302da2e3ebdSchin 
303da2e3ebdSchin 	/* macro candidate template */
304da2e3ebdSchin 	{	MAC0+1,	{ 'L' },		QID,			},
305da2e3ebdSchin 
306da2e3ebdSchin 	/* copy MAC0+1 to MAC0+2 through MACN */
307da2e3ebdSchin 	{	OP,	{MAC0+1,MAC0+2,MACN},	COPY			},
308da2e3ebdSchin 
309da2e3ebdSchin 	/* saw L (possible start of wide string or macro L) */
310da2e3ebdSchin 	{	HIT0,	{ C_XXX },		S_MACRO,		},
311da2e3ebdSchin 	{	HIT0,	{ C_LET, C_DEC },	QID,			},
312da2e3ebdSchin 	{	HIT0,	{ '"', '\'' },		QUAL(LIT1),		},
313da2e3ebdSchin 
314da2e3ebdSchin 	/* macro hit template */
315da2e3ebdSchin 	{	HIT0+1,	{ C_XXX },		S_MACRO,		},
316da2e3ebdSchin 	{	HIT0+1,	{ C_LET, C_DEC },	QID,			},
317da2e3ebdSchin 
318da2e3ebdSchin 	/* copy HIT0+1 to HIT0+2 through HITN */
319da2e3ebdSchin 	{	OP,	{HIT0+1,HIT0+2,HITN},	COPY			},
320da2e3ebdSchin 
321da2e3ebdSchin 	/* saw L (possible start of wide literal) */
322da2e3ebdSchin 	{	LIT0,	{ C_XXX },		S_MACRO,		},
323da2e3ebdSchin 	{	LIT0,	{ C_LET, C_DEC },	QID,			},
324da2e3ebdSchin 	{	LIT0,	{ '"', '\'' },		QUAL(LIT1),		},
325da2e3ebdSchin 
326da2e3ebdSchin 	/* (!PROTOMAIN COM1) saw /, perhaps start of comment or /= */
327da2e3ebdSchin 	{	COM1,	{ '=' },		KEEP(T_DIVEQ),		},
328da2e3ebdSchin 
329da2e3ebdSchin 	/* normal start state */
330da2e3ebdSchin 	{	TOKEN,	{ C_XXX },		S_HUH,			},
331da2e3ebdSchin 	{	TOKEN,	{ C_EOF },		S_EOF,			},
332da2e3ebdSchin 	{	TOKEN,	{ C_DEC },		DEC1,			},
333da2e3ebdSchin 	{	TOKEN,	{ '0' },		OCT1,			},
334da2e3ebdSchin 	{	TOKEN,	{ '.' },		DOT1,			},
335da2e3ebdSchin 	{	TOKEN,	{ C_LET },		NID,			},
336da2e3ebdSchin 	{	TOKEN,	{ 'L' },		LIT,			},
337da2e3ebdSchin 	{	TOKEN,	{ '"', '\'', '<' },	S_LITBEG,		},
338da2e3ebdSchin 	{	TOKEN,	{ '/' },		COM1,			},
339da2e3ebdSchin 	{	TOKEN,	{ '\n' },		S_NL,			},
340da2e3ebdSchin 	{	TOKEN,	{ ' ', '\t' },		WS1,			},
341da2e3ebdSchin 	{	TOKEN,	{ '\f', '\v' },		S_VS,			},
342da2e3ebdSchin 	{	TOKEN,	{ '#' },		SHARP1,			},
343da2e3ebdSchin 	{	TOKEN,	{ ':' },		COLON1,			},
344da2e3ebdSchin 	{	TOKEN,	{ '%' },		PCT1,			},
345da2e3ebdSchin 	{	TOKEN,	{ '&' },		AND1,			},
346da2e3ebdSchin 	{	TOKEN,	{ '*' },		STAR1,			},
347da2e3ebdSchin 	{	TOKEN,	{ '+' },		PLUS1,			},
348da2e3ebdSchin 	{	TOKEN,	{ '-' },		MINUS1,			},
349da2e3ebdSchin 	{	TOKEN,	{ '=' },		EQ1,			},
350da2e3ebdSchin 	{	TOKEN,	{ '!' },		NOT1,			},
351da2e3ebdSchin 	{	TOKEN,	{ '>' },		GT1,			},
352da2e3ebdSchin 	{	TOKEN,	{ '^' },		CIRC1,			},
353da2e3ebdSchin 	{	TOKEN,	{ '|' },		OR1,			},
354da2e3ebdSchin 	{	TOKEN,	{ '(', ')', '[', ']' },	S_CHR,			},
355da2e3ebdSchin 	{	TOKEN,	{ '{', '}', ',', ';' },	S_CHR,			},
356da2e3ebdSchin 	{	TOKEN,	{ '~', '?' },		S_CHR,			},
357da2e3ebdSchin 
358da2e3ebdSchin 	/* saw 0, possible oct|hex|dec|dbl constant */
359da2e3ebdSchin 	{	OCT1,	{ C_XXX },		BACK(T_DECIMAL),	},
360da2e3ebdSchin 	{	OCT1,	{ C_LET, C_DEC },	BAD1,			},
361da2e3ebdSchin 	{	OCT1,	{ C_OCT },		OCT2,			},
362da2e3ebdSchin 	{	OCT1,	{ 'e', 'E' },		DBL2,			},
363da2e3ebdSchin 	{	OCT1,	{ 'l', 'L', 'u', 'U' },	QUAL(DEC2),		},
364da2e3ebdSchin 	{	OCT1,	{ 'x', 'X' },		HEX1,			},
365da2e3ebdSchin 	{	OCT1,	{ '.' },		DBL1,			},
366da2e3ebdSchin 
367da2e3ebdSchin 	/* saw 0<oct>, oct constant */
368da2e3ebdSchin 	{	OCT2,	{ C_XXX },		BACK(T_OCTAL),		},
369da2e3ebdSchin 	{	OCT2,	{ C_LET, C_DEC },	BAD1,			},
370da2e3ebdSchin 	{	OCT2,	{ C_OCT },		OCT2,			},
371da2e3ebdSchin 	{	OCT2,	{ 'e', 'E' },		DBL2,			},
372da2e3ebdSchin 	{	OCT2,	{ 'l', 'L', 'u', 'U' },	QUAL(OCT3),		},
373da2e3ebdSchin 	{	OCT2,	{ '.' },		DBL1,			},
374da2e3ebdSchin 
375da2e3ebdSchin 	/* oct constant qualifier */
376da2e3ebdSchin 	{	OCT3,	{ C_XXX },		BACK(T_OCTAL),		},
377da2e3ebdSchin 	{	OCT3,	{ C_LET, C_DEC, '.' },	BAD1,			},
378da2e3ebdSchin 	{	OCT3,	{ 'l', 'L', 'u', 'U' },	QUAL(OCT3),		},
379da2e3ebdSchin 
380da2e3ebdSchin 	/* saw 0 [xX], hex constant */
381da2e3ebdSchin 	{	HEX1,	{ C_XXX },		BACK(T_HEXADECIMAL),	},
382da2e3ebdSchin 	{	HEX1,	{ C_LET },		BAD1,			},
383da2e3ebdSchin 	{	HEX1,	{ C_HEX },		HEX1,			},
384da2e3ebdSchin 	{	HEX1,	{ 'e', 'E' },		HEX3,			},
385da2e3ebdSchin 	{	HEX1,	{ 'l', 'L', 'u', 'U' },	QUAL(HEX2),		},
386da2e3ebdSchin 	{	HEX1,	{ '.' },		HEX4,			},
387da2e3ebdSchin 	{	HEX1,	{ 'p', 'P' },		HEX5,			},
388da2e3ebdSchin 
389da2e3ebdSchin 	/* hex constant qualifier */
390da2e3ebdSchin 	{	HEX2,	{ C_XXX },		BACK(T_HEXADECIMAL),	},
391da2e3ebdSchin 	{	HEX2,	{ C_LET, C_DEC, '.' },	BAD1,			},
392da2e3ebdSchin 	{	HEX2,	{ 'l', 'L', 'u', 'U' },	QUAL(HEX2),		},
393da2e3ebdSchin 
394da2e3ebdSchin 	/* hex [eE][-+] botch */
395da2e3ebdSchin 	{	HEX3,	{ C_XXX },		BACK(T_HEXADECIMAL),	},
396da2e3ebdSchin 	{	HEX3,	{ C_LET, '.', '-', '+'},BAD1,			},
397da2e3ebdSchin 	{	HEX3,	{ C_HEX },		HEX1,			},
398da2e3ebdSchin 	{	HEX3,	{ 'e', 'E' },		HEX3,			},
399da2e3ebdSchin 	{	HEX3,	{ 'l', 'L', 'u', 'U' },	QUAL(HEX2),		},
400da2e3ebdSchin 
401da2e3ebdSchin 	/* hex dbl fraction */
402da2e3ebdSchin 	{	HEX4,	{ C_XXX },		BACK(T_HEXDOUBLE),	},
403da2e3ebdSchin 	{	HEX4,	{ C_LET, '.' },		BAD1,			},
404da2e3ebdSchin 	{	HEX4,	{ C_HEX },		HEX4,			},
405da2e3ebdSchin 	{	HEX4,	{ 'p', 'P' },		HEX5,			},
406da2e3ebdSchin 	{	HEX4,	{ 'f', 'F', 'l', 'L' },	QUAL(HEX8),		},
407da2e3ebdSchin 
408da2e3ebdSchin 	/* optional hex dbl exponent sign */
409da2e3ebdSchin 	{	HEX5,	{ C_XXX },		BACK(T_INVALID),	},
410da2e3ebdSchin 	{	HEX5,	{ C_LET, '.' },		BAD1,			},
411da2e3ebdSchin 	{	HEX5,	{ '+', '-' },		HEX6,			},
412da2e3ebdSchin 	{	HEX5,	{ C_DEC },		HEX7,			},
413da2e3ebdSchin 
414da2e3ebdSchin 	/* mandatory hex dbl exponent first digit */
415da2e3ebdSchin 	{	HEX6,	{ C_XXX },		BACK(T_INVALID),	},
416da2e3ebdSchin 	{	HEX6,	{ C_LET, '.' },		BAD1,			},
417da2e3ebdSchin 	{	HEX6,	{ C_DEC },		HEX7,			},
418da2e3ebdSchin 
419da2e3ebdSchin 	/* hex dbl exponent digits */
420da2e3ebdSchin 	{	HEX7,	{ C_XXX },		BACK(T_HEXDOUBLE),	},
421da2e3ebdSchin 	{	HEX7,	{ C_LET, '.' },		BAD1,			},
422da2e3ebdSchin 	{	HEX7,	{ C_DEC },		HEX7,			},
423da2e3ebdSchin 	{	HEX7,	{ 'f', 'F', 'l', 'L' },	QUAL(HEX8),		},
424da2e3ebdSchin 
425da2e3ebdSchin 	/* hex dbl constant qualifier */
426da2e3ebdSchin 	{	HEX8,	{ C_XXX },		BACK(T_HEXDOUBLE),	},
427da2e3ebdSchin 	{	HEX8,	{ C_LET, '.' },		BAD1,			},
428da2e3ebdSchin 	{	HEX8,	{ 'f', 'F', 'l', 'L' },	QUAL(HEX8),		},
429da2e3ebdSchin 
430da2e3ebdSchin 	/* saw <dec>, dec constant */
431da2e3ebdSchin 	{	DEC1,	{ C_XXX },		BACK(T_DECIMAL),	},
432da2e3ebdSchin 	{	DEC1,	{ C_LET },		BAD1,			},
433da2e3ebdSchin 	{	DEC1,	{ C_DEC },		DEC1,			},
434da2e3ebdSchin 	{	DEC1,	{ 'e', 'E' },		DBL2,			},
435da2e3ebdSchin 	{	DEC1,	{ 'l', 'L', 'u', 'U' },	QUAL(DEC2),		},
436da2e3ebdSchin 	{	DEC1,	{ '.' },		DBL1,			},
437da2e3ebdSchin 
438da2e3ebdSchin 	/* dec constant qualifier */
439da2e3ebdSchin 	{	DEC2,	{ C_XXX },		BACK(T_DECIMAL),	},
440da2e3ebdSchin 	{	DEC2,	{ C_LET, C_DEC },	BAD1,			},
441da2e3ebdSchin 	{	DEC2,	{ 'l', 'L', 'u', 'U' },	QUAL(DEC2),		},
442da2e3ebdSchin 
443da2e3ebdSchin 	/* saw ., operator or dbl constant */
444da2e3ebdSchin 	{	DOT1,	{ C_XXX },		S_CHRB,			},
445da2e3ebdSchin 	{	DOT1,	{ '.' },		DOT2,			},
446da2e3ebdSchin 	{	DOT1,	{ C_DEC },		DBL1,			},
447da2e3ebdSchin 
448da2e3ebdSchin 	/* dbl fraction */
449da2e3ebdSchin 	{	DBL1,	{ C_XXX },		BACK(T_DOUBLE),		},
450da2e3ebdSchin 	{	DBL1,	{ C_LET, '.' },		BAD1,			},
451da2e3ebdSchin 	{	DBL1,	{ C_DEC },		DBL1,			},
452da2e3ebdSchin 	{	DBL1,	{ 'e', 'E' },		DBL2,			},
453da2e3ebdSchin 	{	DBL1,	{ 'f', 'F', 'l', 'L' },	QUAL(DBL5),		},
454da2e3ebdSchin 
455da2e3ebdSchin 	/* optional dbl exponent sign */
456da2e3ebdSchin 	{	DBL2,	{ C_XXX },		BACK(T_INVALID),	},
457da2e3ebdSchin 	{	DBL2,	{ C_LET, '.' },		BAD1,			},
458da2e3ebdSchin 	{	DBL2,	{ '+', '-' },		DBL3,			},
459da2e3ebdSchin 	{	DBL2,	{ C_DEC },		DBL4,			},
460da2e3ebdSchin 
461da2e3ebdSchin 	/* mandatory dbl exponent first digit */
462da2e3ebdSchin 	{	DBL3,	{ C_XXX },		BACK(T_INVALID),	},
463da2e3ebdSchin 	{	DBL3,	{ C_LET, '.' },		BAD1,			},
464da2e3ebdSchin 	{	DBL3,	{ C_DEC },		DBL4,			},
465da2e3ebdSchin 
466da2e3ebdSchin 	/* dbl exponent digits */
467da2e3ebdSchin 	{	DBL4,	{ C_XXX },		BACK(T_DOUBLE),		},
468da2e3ebdSchin 	{	DBL4,	{ C_LET, '.' },		BAD1,			},
469da2e3ebdSchin 	{	DBL4,	{ C_DEC },		DBL4,			},
470da2e3ebdSchin 	{	DBL4,	{ 'f', 'F', 'l', 'L' },	QUAL(DBL5),		},
471da2e3ebdSchin 
472da2e3ebdSchin 	/* dbl constant qualifier */
473da2e3ebdSchin 	{	DBL5,	{ C_XXX },		BACK(T_DOUBLE),		},
474da2e3ebdSchin 	{	DBL5,	{ C_LET, '.' },		BAD1,			},
475da2e3ebdSchin 	{	DBL5,	{ 'f', 'F', 'l', 'L' },	QUAL(DBL5),		},
476da2e3ebdSchin 
477da2e3ebdSchin 	/* saw < starting include header */
478da2e3ebdSchin 	{	HDR1,	{ C_XXX },		HDR1,			},
479da2e3ebdSchin 	{	HDR1,	{ '>', '\n', C_EOF },	S_LITEND,		},
480da2e3ebdSchin 
481da2e3ebdSchin 	/* saw <binop><space> expecting = */
482da2e3ebdSchin 	{	BIN1,	{ C_XXX },		S_HUH,			},
483da2e3ebdSchin 	{	BIN1,	{ ' ', '\t' },		BIN1,			},
484da2e3ebdSchin 
485da2e3ebdSchin 	/* 2-char ops */
486da2e3ebdSchin 
487da2e3ebdSchin 	{	SHARP1,	{ C_XXX },		S_SHARP,		},
488da2e3ebdSchin 
489da2e3ebdSchin 	{	PCT1,	{ C_XXX },		S_CHRB,			},
490da2e3ebdSchin 	{	PCT1,	{ '=' },		KEEP(T_MODEQ),		},
491da2e3ebdSchin 
492da2e3ebdSchin 	{	AND1,	{ C_XXX },		S_CHRB,			},
493da2e3ebdSchin 	{	AND1,	{ '=' },		KEEP(T_ANDEQ),		},
494da2e3ebdSchin 	{	AND1,	{ '&' },		KEEP(T_ANDAND),		},
495da2e3ebdSchin 
496da2e3ebdSchin 	{	STAR1,	{ C_XXX },		S_CHRB,			},
497da2e3ebdSchin 	{	STAR1,	{ '=' },		KEEP(T_MPYEQ),		},
498da2e3ebdSchin 	{	STAR1,	{ '/' },		S_COMMENT,		},
499da2e3ebdSchin 
500da2e3ebdSchin 	{	PLUS1,	{ C_XXX },		S_CHRB,			},
501da2e3ebdSchin 	{	PLUS1,	{ '=' },		KEEP(T_ADDEQ),		},
502da2e3ebdSchin 	{	PLUS1,	{ '+' },		KEEP(T_ADDADD),		},
503da2e3ebdSchin 
504da2e3ebdSchin 	{	MINUS1,	{ C_XXX },		S_CHRB,			},
505da2e3ebdSchin 	{	MINUS1,	{ '=' },		KEEP(T_SUBEQ),		},
506da2e3ebdSchin 	{	MINUS1,	{ '-' },		KEEP(T_SUBSUB),		},
507da2e3ebdSchin 	{	MINUS1,	{ '>' },		KEEP(T_PTRMEM),		},
508da2e3ebdSchin 
509da2e3ebdSchin 	{	COLON1,	{ C_XXX },		S_CHRB,			},
510da2e3ebdSchin 	{	COLON1,	{ '=', '>' },		S_HUH,			},
511da2e3ebdSchin 
512da2e3ebdSchin 	{	LT1,	{ C_XXX },		S_CHRB,			},
513da2e3ebdSchin 	{	LT1,	{ '=' },		KEEP(T_LE),		},
514da2e3ebdSchin 	{	LT1,	{ '<' },		LSH1,			},
515da2e3ebdSchin 
516da2e3ebdSchin 	{	EQ1,	{ C_XXX },		S_CHRB,			},
517da2e3ebdSchin 	{	EQ1,	{ '=' },		KEEP(T_EQ),		},
518da2e3ebdSchin 
519da2e3ebdSchin 	{	NOT1,	{ C_XXX },		S_CHRB,			},
520da2e3ebdSchin 	{	NOT1,	{ '=' },		KEEP(T_NE),		},
521da2e3ebdSchin 
522da2e3ebdSchin 	{	GT1,	{ C_XXX },		S_CHRB,			},
523da2e3ebdSchin 	{	GT1,	{ '=' },		KEEP(T_GE),		},
524da2e3ebdSchin 	{	GT1,	{ '>' },		RSH1,			},
525da2e3ebdSchin 
526da2e3ebdSchin 	{	CIRC1,	{ C_XXX },		S_CHRB,			},
527da2e3ebdSchin 	{	CIRC1,	{ '=' },		KEEP(T_XOREQ),		},
528da2e3ebdSchin 
529da2e3ebdSchin 	{	OR1,	{ C_XXX },		S_CHRB,			},
530da2e3ebdSchin 	{	OR1,	{ '=' },		KEEP(T_OREQ),		},
531da2e3ebdSchin 	{	OR1,	{ '|' },		KEEP(T_OROR),		},
532da2e3ebdSchin 
533da2e3ebdSchin 	/* 3-char ops */
534da2e3ebdSchin 
535da2e3ebdSchin 	{	ARROW1,	{ C_XXX },		BACK(T_PTRMEM),		},
536da2e3ebdSchin 	{	ARROW1,	{ '*' },		KEEP(T_PTRMEMREF),	},
537da2e3ebdSchin 
538da2e3ebdSchin 	{	LSH1,	{ C_XXX },		BACK(T_LSHIFT),		},
539da2e3ebdSchin 	{	LSH1,	{ '=' },		KEEP(T_LSHIFTEQ),	},
540da2e3ebdSchin 
541da2e3ebdSchin 	{	RSH1,	{ C_XXX },		BACK(T_RSHIFT),		},
542da2e3ebdSchin 	{	RSH1,	{ '=' },		KEEP(T_RSHIFTEQ),	},
543da2e3ebdSchin 
544da2e3ebdSchin #endif
545da2e3ebdSchin 
546da2e3ebdSchin 	/* end */
547da2e3ebdSchin 	{	OP,	{ 0 },			END,			}
548da2e3ebdSchin };
549da2e3ebdSchin 
550da2e3ebdSchin short		fsm[TERMINAL+1][MAX+1];
551da2e3ebdSchin 
552da2e3ebdSchin char		trigraph[MAX+1];
553da2e3ebdSchin 
554da2e3ebdSchin #if PROTOMAIN
555da2e3ebdSchin static char	spl[] = { '\\', '\r', 0 };
556da2e3ebdSchin static char	aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$@";
557da2e3ebdSchin #else
558da2e3ebdSchin static char	spl[] = { MARK, '?', '\\', '\r', CC_sub, 0 };
559da2e3ebdSchin static char	aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
560da2e3ebdSchin #endif
561da2e3ebdSchin static char*	let = &aln[10];
562da2e3ebdSchin static char	hex[] = "fedcbaFEDCBA9876543210";
563da2e3ebdSchin static char*	dec = &hex[12];
564da2e3ebdSchin static char*	oct = &hex[14];
565da2e3ebdSchin 
566da2e3ebdSchin /*
567da2e3ebdSchin  * runtime FSM modifications
568da2e3ebdSchin  * ppfsm(FSM_INIT,0) must be called first
569da2e3ebdSchin  */
570da2e3ebdSchin 
571da2e3ebdSchin void
ppfsm(int op,register char * s)572da2e3ebdSchin ppfsm(int op, register char* s)
573da2e3ebdSchin {
574da2e3ebdSchin 	register int			c;
575da2e3ebdSchin 	register int			n;
576da2e3ebdSchin 	register int			i;
577da2e3ebdSchin 	register short*			rp;
578da2e3ebdSchin 	register struct fsminit*	fp;
579da2e3ebdSchin #if !PROTOMAIN
580da2e3ebdSchin 	char*				t;
581da2e3ebdSchin 	int				x;
582da2e3ebdSchin #endif
583da2e3ebdSchin 
584da2e3ebdSchin 	switch (op)
585da2e3ebdSchin 	{
586da2e3ebdSchin 
587da2e3ebdSchin #if !PROTOMAIN
588da2e3ebdSchin 
589da2e3ebdSchin 	case FSM_IDADD:
590da2e3ebdSchin 		while (c = *s++)
591da2e3ebdSchin 			if (!ppisid(c))
592da2e3ebdSchin 			{
593da2e3ebdSchin 				if (fsm[TOKEN][c] == ~S_HUH)
594da2e3ebdSchin 				{
595da2e3ebdSchin 					setid(c);
596da2e3ebdSchin 					for (i = 0; i < TERMINAL; i++)
597da2e3ebdSchin 						fsm[i][c] = IDSTATE(fsm[i]['_']);
598da2e3ebdSchin 				}
599da2e3ebdSchin 				else error(2, "%c: cannot add to identifier set", c);
600da2e3ebdSchin 			}
601da2e3ebdSchin 		break;
602da2e3ebdSchin 
603da2e3ebdSchin 	case FSM_IDDEL:
604da2e3ebdSchin 		while (c = *s++)
605da2e3ebdSchin 			if (ppisid(c))
606da2e3ebdSchin 			{
607da2e3ebdSchin 				clrid(c);
608da2e3ebdSchin 				for (i = 0; i < TERMINAL; i++)
609da2e3ebdSchin 					fsm[i][c] = ~S_HUH;
610da2e3ebdSchin 			}
611da2e3ebdSchin 		break;
612da2e3ebdSchin 
613da2e3ebdSchin #endif
614da2e3ebdSchin 
615da2e3ebdSchin 	case FSM_INIT:
616da2e3ebdSchin 		for (fp = fsminit;; fp++)
617da2e3ebdSchin 		{
618da2e3ebdSchin 			if ((n = fp->nextstate) >= TERMINAL) n = ~n;
619da2e3ebdSchin 			if (fp->state == OP)
620da2e3ebdSchin 			{
621da2e3ebdSchin #if !PROTOMAIN
622da2e3ebdSchin 				switch (n)
623da2e3ebdSchin 				{
624da2e3ebdSchin 				case COPY:
625da2e3ebdSchin 					c = fp->ch[0];
626da2e3ebdSchin 					n = fp->ch[2];
627da2e3ebdSchin 					for (i = fp->ch[1]; i <= n; i++)
628da2e3ebdSchin 						copy(i, c);
629da2e3ebdSchin 					continue;
630da2e3ebdSchin 				default:
631da2e3ebdSchin 					break;
632da2e3ebdSchin 				}
633da2e3ebdSchin #endif
634da2e3ebdSchin 				break;
635da2e3ebdSchin 			}
636da2e3ebdSchin 			rp = fsm[fp->state];
637da2e3ebdSchin 			for (i = 0; i < sizeof(fp->ch) && (c = fp->ch[i]); i++)
638da2e3ebdSchin 			{
639da2e3ebdSchin 				switch (c)
640da2e3ebdSchin 				{
641da2e3ebdSchin 				case C_XXX:
642da2e3ebdSchin 					for (c = 0; c <= MAX; c++)
643da2e3ebdSchin 						rp[c] = n;
644da2e3ebdSchin 					/*FALLTHROUGH*/
645da2e3ebdSchin 
646da2e3ebdSchin 				case C_EOF:
647da2e3ebdSchin 					fsm[TERMINAL][fp->state+1] = n < 0 ? ~n : n;
648da2e3ebdSchin 					continue;
649da2e3ebdSchin 
650da2e3ebdSchin 				case C_LET:
651da2e3ebdSchin 					s = let;
652da2e3ebdSchin 					break;
653da2e3ebdSchin 
654da2e3ebdSchin 				case C_HEX:
655da2e3ebdSchin 					s = hex;
656da2e3ebdSchin 					break;
657da2e3ebdSchin 
658da2e3ebdSchin 				case C_DEC:
659da2e3ebdSchin 					s = dec;
660da2e3ebdSchin 					break;
661da2e3ebdSchin 
662da2e3ebdSchin 				case C_OCT:
663da2e3ebdSchin 					s = oct;
664da2e3ebdSchin 					break;
665da2e3ebdSchin 
666da2e3ebdSchin 				default:
667da2e3ebdSchin 					rp[c] = n;
668da2e3ebdSchin 					continue;
669da2e3ebdSchin 				}
670da2e3ebdSchin 				while (c = *s++)
671da2e3ebdSchin 					rp[c] = n;
672da2e3ebdSchin 			}
673da2e3ebdSchin 		}
674da2e3ebdSchin 
675da2e3ebdSchin 		/*
676da2e3ebdSchin 		 * install splice special cases
677da2e3ebdSchin 		 * and same non-terminal transitions
678da2e3ebdSchin 		 */
679da2e3ebdSchin 
680da2e3ebdSchin 		for (i = 0; i < TERMINAL; i++)
681da2e3ebdSchin 		{
682da2e3ebdSchin 			rp = fsm[i];
683da2e3ebdSchin 			s = spl;
684da2e3ebdSchin 			while (c = *s++)
685da2e3ebdSchin 				if (c != MARK || !INCOMMENT(rp))
686da2e3ebdSchin 				{
687da2e3ebdSchin 					if (rp[c] >= 0) rp[c] = ~rp[c];
688da2e3ebdSchin 					rp[c] &= ~SPLICE;
689da2e3ebdSchin 				}
690da2e3ebdSchin 			rp[EOB] = ~S_EOB;
691da2e3ebdSchin 			for (c = 0; c <= MAX; c++)
692da2e3ebdSchin 				if (rp[c] == i)
693da2e3ebdSchin 					rp[c] = 0;
694da2e3ebdSchin 		}
695da2e3ebdSchin 		fsm[TERMINAL][0] = ~S_EOB;
696da2e3ebdSchin 
697da2e3ebdSchin #if !PROTOMAIN
698da2e3ebdSchin 
699da2e3ebdSchin 		/*
700da2e3ebdSchin 		 * default character types
701da2e3ebdSchin 		 */
702da2e3ebdSchin 
703da2e3ebdSchin 		s = let;
704da2e3ebdSchin 		while (c = *s++)
705da2e3ebdSchin 			setid(c);
706da2e3ebdSchin 		s = dec;
707da2e3ebdSchin 		while (c = *s++)
708da2e3ebdSchin 			setdig(c);
709da2e3ebdSchin 		s = spl;
710da2e3ebdSchin 		do setsplice(c = *s++); while (c);
711da2e3ebdSchin 
712da2e3ebdSchin 		/*
713da2e3ebdSchin 		 * trigraph map
714da2e3ebdSchin 		 */
715da2e3ebdSchin 
716da2e3ebdSchin 		trigraph['='] = '#';
717da2e3ebdSchin 		trigraph['('] = '[';
718da2e3ebdSchin 		trigraph['/'] = '\\';
719da2e3ebdSchin 		trigraph[')'] = ']';
720da2e3ebdSchin 		trigraph['\''] = '^';
721da2e3ebdSchin 		trigraph['<'] = '{';
722da2e3ebdSchin 		trigraph['!'] = '|';
723da2e3ebdSchin 		trigraph['>'] = '}';
724da2e3ebdSchin 		trigraph['-'] = '~';
725da2e3ebdSchin #endif
726da2e3ebdSchin 		break;
727da2e3ebdSchin 
728da2e3ebdSchin #if !PROTOMAIN
729da2e3ebdSchin 
730da2e3ebdSchin 	case FSM_PLUSPLUS:
731da2e3ebdSchin 		if (pp.option & PLUSPLUS)
732da2e3ebdSchin 		{
733da2e3ebdSchin 			fsm[COLON1][':'] = ~KEEP(T_SCOPE);
734da2e3ebdSchin 			fsm[DOT1]['*'] = ~KEEP(T_DOTREF);
735da2e3ebdSchin 			fsm[MINUS1]['>'] = ARROW1;
736da2e3ebdSchin 			fsm[COM1]['/'] = COM5;
737da2e3ebdSchin 			t = "%<:";
738da2e3ebdSchin 			for (i = 0; i < TERMINAL; i++)
739da2e3ebdSchin 			{
740da2e3ebdSchin 				rp = fsm[i];
741da2e3ebdSchin 				if (!INCOMMENT(rp) && !INQUOTE(rp))
742da2e3ebdSchin 				{
743da2e3ebdSchin 					s = t;
744da2e3ebdSchin 					while (c = *s++)
745da2e3ebdSchin 					{
746da2e3ebdSchin 						if (rp[c] > 0) rp[c] = ~rp[c];
747da2e3ebdSchin 						else if (!rp[c]) rp[c] = ~i;
748da2e3ebdSchin 						rp[c] &= ~SPLICE;
749da2e3ebdSchin 					}
750da2e3ebdSchin 				}
751da2e3ebdSchin 			}
752da2e3ebdSchin 			s = t;
753da2e3ebdSchin 			while (c = *s++) setsplice(c);
754da2e3ebdSchin 		}
755da2e3ebdSchin 		else
756da2e3ebdSchin 		{
757da2e3ebdSchin 			fsm[COLON1][':'] = ~S_CHRB;
758da2e3ebdSchin 			fsm[DOT1]['*'] = ~S_CHRB;
759da2e3ebdSchin 			fsm[MINUS1]['>'] = ~KEEP(T_PTRMEM);
760da2e3ebdSchin 			fsm[COM1]['/'] = (pp.option & PLUSCOMMENT) ? COM5 : ~S_CHRB;
761da2e3ebdSchin 		}
762da2e3ebdSchin 		break;
763da2e3ebdSchin 
764da2e3ebdSchin #if COMPATIBLE
765da2e3ebdSchin 
766da2e3ebdSchin 	case FSM_COMPATIBILITY:
767da2e3ebdSchin 		if (pp.state & COMPATIBILITY)
768da2e3ebdSchin 		{
769da2e3ebdSchin 			fsm[HEX1]['e'] = HEX1;
770da2e3ebdSchin 			fsm[HEX1]['E'] = HEX1;
771da2e3ebdSchin 			fsm[QNUM]['e'] = QNUM;
772da2e3ebdSchin 			fsm[QNUM]['E'] = QNUM;
773da2e3ebdSchin 			fsm[QNUM]['u'] = ~QUAL(QNUM);
774da2e3ebdSchin 			fsm[QNUM]['U'] = ~QUAL(QNUM);
775da2e3ebdSchin 		}
776da2e3ebdSchin 		else
777da2e3ebdSchin 		{
778da2e3ebdSchin 			fsm[HEX1]['e'] = HEX3;
779da2e3ebdSchin 			fsm[HEX1]['E'] = HEX3;
780da2e3ebdSchin 			fsm[QNUM]['e'] = QEXP;
781da2e3ebdSchin 			fsm[QNUM]['E'] = QEXP;
782da2e3ebdSchin 			fsm[QNUM]['u'] = QNUM;
783da2e3ebdSchin 			fsm[QNUM]['U'] = QNUM;
784da2e3ebdSchin 		}
785da2e3ebdSchin 		break;
786da2e3ebdSchin 
787da2e3ebdSchin #endif
788da2e3ebdSchin 
789da2e3ebdSchin 	case FSM_QUOTADD:
790da2e3ebdSchin 		while (c = *s++)
791da2e3ebdSchin 			if (fsm[TOKEN][c] == ~S_HUH)
792da2e3ebdSchin 				for (i = 0; i < TERMINAL; i++)
793da2e3ebdSchin 					fsm[i][c] = fsm[i]['"'];
794da2e3ebdSchin 			else error(2, "%c: cannot add to quote set", c);
795da2e3ebdSchin 		break;
796da2e3ebdSchin 
797da2e3ebdSchin 	case FSM_QUOTDEL:
798da2e3ebdSchin 		while (c = *s++)
799da2e3ebdSchin 			if (c != '"' && fsm[TOKEN][c] == fsm[TOKEN]['"'])
800da2e3ebdSchin 				for (i = 0; i < TERMINAL; i++)
801da2e3ebdSchin 					fsm[i][c] = fsm[i]['_'];
802da2e3ebdSchin 		break;
803da2e3ebdSchin 
804da2e3ebdSchin 	case FSM_OPSPACE:
805da2e3ebdSchin 		n = s ? BIN1 : ~S_CHRB;
806da2e3ebdSchin 		fsm[COM1][' '] = fsm[COM1]['\t'] = n;
807da2e3ebdSchin 		fsm[AND1][' '] = fsm[AND1]['\t'] = n;
808da2e3ebdSchin 		fsm[STAR1][' '] = fsm[STAR1]['\t'] = n;
809da2e3ebdSchin 		fsm[PCT1][' '] = fsm[PCT1]['\t'] = n;
810da2e3ebdSchin 		fsm[PLUS1][' '] = fsm[PLUS1]['\t'] = n;
811da2e3ebdSchin 		fsm[MINUS1][' '] = fsm[MINUS1]['\t'] = n;
812da2e3ebdSchin 		fsm[CIRC1][' '] = fsm[CIRC1]['\t'] = n;
813da2e3ebdSchin 		fsm[OR1][' '] = fsm[OR1]['\t'] = n;
814da2e3ebdSchin 		fsm[LSH1][' '] = fsm[LSH1]['\t'] = s ? BIN1 : ~BACK(T_LSHIFT);
815da2e3ebdSchin 		fsm[RSH1][' '] = fsm[RSH1]['\t'] = s ? BIN1 : ~BACK(T_RSHIFT);
816da2e3ebdSchin 		break;
817da2e3ebdSchin 
818da2e3ebdSchin 	case FSM_MACRO:
819da2e3ebdSchin 		if (pp.truncate && strlen(s) >= pp.truncate)
820da2e3ebdSchin 		{
821da2e3ebdSchin 			x = s[pp.truncate];
822da2e3ebdSchin 			s[pp.truncate] = 0;
823da2e3ebdSchin 		}
824da2e3ebdSchin 		else x = -1;
825da2e3ebdSchin 		i = MAC0 + ((c = *s++) != 'L');
826da2e3ebdSchin 		if ((n = fsm[QUICK][c]) != (i + NMAC))
827da2e3ebdSchin 		{
828da2e3ebdSchin 			n = i;
829da2e3ebdSchin 			if (!*s) n += NMAC;
830da2e3ebdSchin 		}
831da2e3ebdSchin 		if (fsm[QUICK][c] != n)
832da2e3ebdSchin 			fsm[QUICK][c] = fsm[QCOM][c] = fsm[QTOK][c] = n;
833da2e3ebdSchin 		if (c = *s++)
834da2e3ebdSchin 		{
835da2e3ebdSchin 			for (;;)
836da2e3ebdSchin 			{
837da2e3ebdSchin 				if ((i = n) < HIT0)
838da2e3ebdSchin 				{
839da2e3ebdSchin 					if (n < MACN) n++;
840da2e3ebdSchin 					if (!*s)
841da2e3ebdSchin 					{
842da2e3ebdSchin 						n += NMAC;
843da2e3ebdSchin 						break;
844da2e3ebdSchin 					}
845da2e3ebdSchin 					if (fsm[i][c] < HIT0)
846da2e3ebdSchin 						fsm[i][c] = n;
847da2e3ebdSchin 					if (fsm[i + NMAC][c] < HIT0)
848da2e3ebdSchin 						fsm[i + NMAC][c] = n;
849da2e3ebdSchin 				}
850da2e3ebdSchin 				else
851da2e3ebdSchin 				{
852da2e3ebdSchin 					if (n < HITN) n++;
853da2e3ebdSchin 					if (!*s) break;
854da2e3ebdSchin 					if (fsm[i][c] < HIT0)
855da2e3ebdSchin 					{
856da2e3ebdSchin 						n -= NMAC;
857da2e3ebdSchin 						fsm[i][c] = n;
858da2e3ebdSchin 					}
859da2e3ebdSchin 				}
860da2e3ebdSchin 				c = *s++;
861da2e3ebdSchin 			}
862da2e3ebdSchin 			if (x >= 0)
863da2e3ebdSchin 			{
864da2e3ebdSchin 				*s = x;
865da2e3ebdSchin 				for (n = CHAR_MIN; n <= CHAR_MAX; n++)
866da2e3ebdSchin 					if (ppisidig(n))
867da2e3ebdSchin 						fsm[HITN][n] = HITN;
868da2e3ebdSchin 				n = HITN;
869da2e3ebdSchin 			}
870da2e3ebdSchin 			if (fsm[i][c] < n)
871da2e3ebdSchin 				fsm[i][c] = n;
872da2e3ebdSchin 			if (i < HIT0 && fsm[i + NMAC][c] < n)
873da2e3ebdSchin 				fsm[i + NMAC][c] = n;
874da2e3ebdSchin 		}
875da2e3ebdSchin 		break;
876da2e3ebdSchin 
877da2e3ebdSchin #endif
878da2e3ebdSchin 
879da2e3ebdSchin 	}
880da2e3ebdSchin }
881da2e3ebdSchin 
882da2e3ebdSchin #if !PROTOMAIN
883da2e3ebdSchin 
884da2e3ebdSchin /*
885da2e3ebdSchin  * file buffer refill
886da2e3ebdSchin  * c is current input char
887da2e3ebdSchin  */
888da2e3ebdSchin 
889da2e3ebdSchin void
refill(register int c)890da2e3ebdSchin refill(register int c)
891da2e3ebdSchin {
892da2e3ebdSchin 	if (pp.in->flags & IN_eof)
893da2e3ebdSchin 	{
894da2e3ebdSchin 		pp.in->nextchr--;
895da2e3ebdSchin 		c = 0;
896da2e3ebdSchin 	}
897da2e3ebdSchin 	else
898da2e3ebdSchin 	{
899da2e3ebdSchin 		*((pp.in->nextchr = pp.in->buffer + PPBAKSIZ) - 1) = c;
900da2e3ebdSchin 		c =
901da2e3ebdSchin #if PROTOTYPE
902da2e3ebdSchin 		(pp.in->flags & IN_prototype) ? pppread(pp.in->nextchr) :
903da2e3ebdSchin #endif
904da2e3ebdSchin 		read(pp.in->fd, pp.in->nextchr, PPBUFSIZ);
905da2e3ebdSchin 	}
906da2e3ebdSchin 	if (c > 0)
907da2e3ebdSchin 	{
908da2e3ebdSchin 		if (pp.in->nextchr[c - 1] == '\n') pp.in->flags |= IN_newline;
909da2e3ebdSchin 		else pp.in->flags &= ~IN_newline;
910da2e3ebdSchin #if PROTOTYPE
911da2e3ebdSchin 		if (!(pp.in->flags & IN_prototype))
912da2e3ebdSchin #endif
913da2e3ebdSchin 		if (c < PPBUFSIZ && (pp.in->flags & IN_regular))
914da2e3ebdSchin 		{
915da2e3ebdSchin 			pp.in->flags |= IN_eof;
916da2e3ebdSchin 			close(pp.in->fd);
917da2e3ebdSchin 			pp.in->fd = -1;
918da2e3ebdSchin 		}
919da2e3ebdSchin 	}
920da2e3ebdSchin 	else
921da2e3ebdSchin 	{
922da2e3ebdSchin 		if (c < 0)
923da2e3ebdSchin 		{
924da2e3ebdSchin 			error(ERROR_SYSTEM|3, "read error");
925da2e3ebdSchin 			c = 0;
926da2e3ebdSchin 		}
927da2e3ebdSchin 		else if ((pp.in->flags ^ pp.in->prev->flags) & IN_c)
928da2e3ebdSchin 		{
929da2e3ebdSchin 			static char	ket[] = { 0, '}', '\n', 0 };
930da2e3ebdSchin 
931da2e3ebdSchin 			pp.in->flags ^= IN_c;
932da2e3ebdSchin 			pp.in->nextchr = ket + 1;
933da2e3ebdSchin 			c = 2;
934da2e3ebdSchin 		}
935da2e3ebdSchin 		pp.in->flags |= IN_eof;
936da2e3ebdSchin 	}
937da2e3ebdSchin #if CHECKPOINT
938da2e3ebdSchin 	pp.in->buflen = c;
939da2e3ebdSchin #endif
940da2e3ebdSchin 	pp.in->nextchr[c] = 0;
941da2e3ebdSchin 	debug((-7, "refill(\"%s\") = %d = \"%-.*s%s\"", error_info.file, c, (c > 32 ? 32 : c), pp.in->nextchr, c > 32 ? "..." : ""));
942da2e3ebdSchin 	if (pp.test & 0x0080)
943da2e3ebdSchin 		sfprintf(sfstderr, "===== refill(\"%s\") = %d =====\n%s\n===== eob(\"%s\") =====\n", error_info.file, c, pp.in->nextchr, error_info.file);
944da2e3ebdSchin }
945da2e3ebdSchin 
946da2e3ebdSchin #endif
947