xref: /onnv-gate/usr/src/tools/cscope-fast/scanner.l (revision 0:68f95e015346)
1*0Sstevel@tonic-gate %{
2*0Sstevel@tonic-gate /*
3*0Sstevel@tonic-gate  * CDDL HEADER START
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
6*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
7*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
8*0Sstevel@tonic-gate  * with the License.
9*0Sstevel@tonic-gate  *
10*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
12*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
13*0Sstevel@tonic-gate  * and limitations under the License.
14*0Sstevel@tonic-gate  *
15*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
16*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
18*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
19*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
20*0Sstevel@tonic-gate  *
21*0Sstevel@tonic-gate  * CDDL HEADER END
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
28*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /*
33*0Sstevel@tonic-gate  *	cscope - interactive C symbol cross-reference
34*0Sstevel@tonic-gate  *
35*0Sstevel@tonic-gate  *
36*0Sstevel@tonic-gate  *	C symbol scanner
37*0Sstevel@tonic-gate  */
38*0Sstevel@tonic-gate #ident	"@(#)scanner.l	1.2	93/06/07 SMI"
39*0Sstevel@tonic-gate #include "global.h"
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /* the line counting has been moved from character reading for speed */
42*0Sstevel@tonic-gate /* comments are discarded */
43*0Sstevel@tonic-gate #undef	input
44*0Sstevel@tonic-gate #define	input() \
45*0Sstevel@tonic-gate 	((yytchar = (yytchar = yysptr > yysbuf ? \
46*0Sstevel@tonic-gate 	    *--yysptr : getc(yyin)) == '/' ? comment() : yytchar) == \
47*0Sstevel@tonic-gate 	    EOF ? 0 : toascii(yytchar))
48*0Sstevel@tonic-gate #define	noncommentinput() \
49*0Sstevel@tonic-gate 	((yytchar = yysptr > yysbuf ? *--yysptr : getc(yyin)) == \
50*0Sstevel@tonic-gate 	    EOF ? 0 : yytchar)
51*0Sstevel@tonic-gate #undef	unput
52*0Sstevel@tonic-gate #define	unput(c) (*yysptr++ = (c))
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /* not a preprocessor line (allow Ingres(TM) "## char var;" lines) */
55*0Sstevel@tonic-gate #define	notpp()	(ppdefine == NO && (*yytext != '#' || yytext[1] == '#'))
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate #define	IFLEVELINC	5	/* #if nesting level size increment */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /* keyword text for fast testing of keywords in the scanner */
60*0Sstevel@tonic-gate extern	char	externtext[];
61*0Sstevel@tonic-gate extern	char	typedeftext[];
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate int	first;	/* buffer index for first char of symbol */
64*0Sstevel@tonic-gate int	last;	/* buffer index for last char of symbol */
65*0Sstevel@tonic-gate int	lineno;	/* symbol line number */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static	BOOL	arraydimension;		/* inside array dimension declaration */
68*0Sstevel@tonic-gate static	BOOL	bplisting;		/* breakpoint listing */
69*0Sstevel@tonic-gate static	int	braces;			/* unmatched left brace count */
70*0Sstevel@tonic-gate static	int	cesudeftoken;		/* class/enum/struct/union definition */
71*0Sstevel@tonic-gate static	BOOL	classdef;		/* c++ class definition */
72*0Sstevel@tonic-gate static	BOOL	elseelif;		/* #else or #elif found */
73*0Sstevel@tonic-gate static	BOOL	esudef;			/* enum/struct/union definition */
74*0Sstevel@tonic-gate static	int	esubraces;		/* outermost enum/struct/union */
75*0Sstevel@tonic-gate 					/* brace count */
76*0Sstevel@tonic-gate static	BOOL	externdec;		/* extern declaration */
77*0Sstevel@tonic-gate static	BOOL	fcndef;			/* function definition */
78*0Sstevel@tonic-gate static	BOOL	globalscope;		/* file global scope */
79*0Sstevel@tonic-gate 					/* (outside functions) */
80*0Sstevel@tonic-gate static	int	iflevel;		/* #if nesting level */
81*0Sstevel@tonic-gate static	BOOL	initializer;		/* data initializer */
82*0Sstevel@tonic-gate static	int	initializerbraces;	/* data initializer outer brace count */
83*0Sstevel@tonic-gate static	BOOL	lex;			/* lex file */
84*0Sstevel@tonic-gate static	BOOL	localdef;		/* function/block local definition */
85*0Sstevel@tonic-gate static	int	miflevel = IFLEVELINC;	/* maximum #if nesting level */
86*0Sstevel@tonic-gate static	int	*maxifbraces;		/* maximum brace count within #if */
87*0Sstevel@tonic-gate static	int	*preifbraces;		/* brace count before #if */
88*0Sstevel@tonic-gate static	int	parens;			/* unmatched left parenthesis count */
89*0Sstevel@tonic-gate static	BOOL	ppdefine;		/* preprocessor define statement */
90*0Sstevel@tonic-gate static	BOOL	psuedoelif;		/* psuedo-#elif */
91*0Sstevel@tonic-gate static	BOOL	oldtype;		/* next identifier is an old type */
92*0Sstevel@tonic-gate static	BOOL	rules;			/* lex/yacc rules */
93*0Sstevel@tonic-gate static	BOOL	sdl;			/* SDL file */
94*0Sstevel@tonic-gate static	BOOL	structfield;		/* structure field declaration */
95*0Sstevel@tonic-gate static	BOOL	template;		/* function template */
96*0Sstevel@tonic-gate static	int	templateparens;	/* function template outer parentheses count */
97*0Sstevel@tonic-gate static	BOOL	typedefdef;	/* typedef name definition */
98*0Sstevel@tonic-gate static	BOOL	typedefname;	/* typedef name use */
99*0Sstevel@tonic-gate static	int	token;		/* token found */
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate static	BOOL	asy;			/* assembly file */
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate void multicharconstant(char terminator);
104*0Sstevel@tonic-gate int do_assembly(int token);
105*0Sstevel@tonic-gate %}
106*0Sstevel@tonic-gate identifier	[a-zA-Z_][a-zA-Z_0-9]*
107*0Sstevel@tonic-gate number		\.?[0-9][.0-9a-fA-FlLuUxX]*
108*0Sstevel@tonic-gate %start SDL
109*0Sstevel@tonic-gate %a 6000
110*0Sstevel@tonic-gate %o 11000
111*0Sstevel@tonic-gate %p 3000
112*0Sstevel@tonic-gate %%
113*0Sstevel@tonic-gate %\{		{	/* lex/yacc C declarations/definitions */
114*0Sstevel@tonic-gate 			globalscope = YES;
115*0Sstevel@tonic-gate 			goto more;
116*0Sstevel@tonic-gate 			/* NOTREACHED */
117*0Sstevel@tonic-gate 		}
118*0Sstevel@tonic-gate %\}		{
119*0Sstevel@tonic-gate 			globalscope = NO;
120*0Sstevel@tonic-gate 			goto more;
121*0Sstevel@tonic-gate 			/* NOTREACHED */
122*0Sstevel@tonic-gate 		}
123*0Sstevel@tonic-gate ^%%		{	/* lex/yacc rules delimiter */
124*0Sstevel@tonic-gate 			braces = 0;
125*0Sstevel@tonic-gate 			if (rules == NO) {
126*0Sstevel@tonic-gate 				rules = YES;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 				/* simulate a yylex() or yyparse() definition */
129*0Sstevel@tonic-gate 				(void) strcat(yytext, " /* ");
130*0Sstevel@tonic-gate 				first = strlen(yytext);
131*0Sstevel@tonic-gate 				if (lex == YES) {
132*0Sstevel@tonic-gate 					(void) strcat(yytext, "yylex");
133*0Sstevel@tonic-gate 				} else {
134*0Sstevel@tonic-gate 					/*
135*0Sstevel@tonic-gate 					 * yacc: yyparse implicitly calls yylex
136*0Sstevel@tonic-gate 					 */
137*0Sstevel@tonic-gate 					char *s = " yylex()";
138*0Sstevel@tonic-gate 					char *cp = s + strlen(s);
139*0Sstevel@tonic-gate 					while (--cp >= s) {
140*0Sstevel@tonic-gate 						unput(*cp);
141*0Sstevel@tonic-gate 					}
142*0Sstevel@tonic-gate 					(void) strcat(yytext, "yyparse");
143*0Sstevel@tonic-gate 				}
144*0Sstevel@tonic-gate 				last = strlen(yytext);
145*0Sstevel@tonic-gate 				(void) strcat(yytext, " */");
146*0Sstevel@tonic-gate 				yyleng = strlen(yytext);
147*0Sstevel@tonic-gate 				yymore();
148*0Sstevel@tonic-gate 				return (FCNDEF);
149*0Sstevel@tonic-gate 			} else {
150*0Sstevel@tonic-gate 				rules = NO;
151*0Sstevel@tonic-gate 				globalscope = YES;
152*0Sstevel@tonic-gate 				last = first;
153*0Sstevel@tonic-gate 				yymore();
154*0Sstevel@tonic-gate 				return (FCNEND);
155*0Sstevel@tonic-gate 			}
156*0Sstevel@tonic-gate 			/* NOTREACHED */
157*0Sstevel@tonic-gate 		}
158*0Sstevel@tonic-gate <SDL>(PROCEDURE|STATE)[ \t]+({identifier}|\*)	{ /* SDL procedure or state */
159*0Sstevel@tonic-gate 			braces = 1;
160*0Sstevel@tonic-gate 			fcndef = YES;	/* treat as function definition */
161*0Sstevel@tonic-gate 			token = FCNDEF;
162*0Sstevel@tonic-gate 			globalscope = NO;
163*0Sstevel@tonic-gate 			goto findident;
164*0Sstevel@tonic-gate 			/* NOTREACHED */
165*0Sstevel@tonic-gate 		}
166*0Sstevel@tonic-gate <SDL>(CALL|NEXTSTATE)[ \t]+({identifier}|\*)	{ /* SDL call or nextstate */
167*0Sstevel@tonic-gate 			token = FCNCALL;
168*0Sstevel@tonic-gate 			goto findident;	/* treat as function call */
169*0Sstevel@tonic-gate 			/* NOTREACHED */
170*0Sstevel@tonic-gate 		}
171*0Sstevel@tonic-gate <SDL>END(PROCEDURE|STATE)[ \t]+({identifier}|\*)	{
172*0Sstevel@tonic-gate 			/* end of an SDL procedure or state */
173*0Sstevel@tonic-gate 			goto endstate;	/* treat as the end of a function */
174*0Sstevel@tonic-gate 			/* NOTREACHED */
175*0Sstevel@tonic-gate 		}
176*0Sstevel@tonic-gate \{		{
177*0Sstevel@tonic-gate 			/* count unmatched left braces for fcn def detection */
178*0Sstevel@tonic-gate 			++braces;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 			/*
181*0Sstevel@tonic-gate 			 * mark an untagged enum/struct/union so its beginning
182*0Sstevel@tonic-gate 			 * can be found
183*0Sstevel@tonic-gate 			 */
184*0Sstevel@tonic-gate 			if (cesudeftoken) {
185*0Sstevel@tonic-gate 				last = first;
186*0Sstevel@tonic-gate 				savesymbol(cesudeftoken);
187*0Sstevel@tonic-gate 				cesudeftoken = '\0';
188*0Sstevel@tonic-gate 			}
189*0Sstevel@tonic-gate 			goto more;
190*0Sstevel@tonic-gate 			/* NOTREACHED */
191*0Sstevel@tonic-gate 		}
192*0Sstevel@tonic-gate \#[ \t]*endif/.*[\n\r][ \t\n\r]*#[ \t]*if	{
193*0Sstevel@tonic-gate 			/*
194*0Sstevel@tonic-gate 			 * attempt to correct erroneous brace count caused by:
195*0Sstevel@tonic-gate 			 *
196*0Sstevel@tonic-gate 			 * #if ...
197*0Sstevel@tonic-gate 			 * 	... {
198*0Sstevel@tonic-gate 			 * #endif
199*0Sstevel@tonic-gate 			 * #if ...
200*0Sstevel@tonic-gate 			 * 	... {
201*0Sstevel@tonic-gate 			 * #endif
202*0Sstevel@tonic-gate 			 */
203*0Sstevel@tonic-gate 			/* the current #if must not have an #else or #elif */
204*0Sstevel@tonic-gate 			if (elseelif == YES) {
205*0Sstevel@tonic-gate 				goto endif;
206*0Sstevel@tonic-gate 			}
207*0Sstevel@tonic-gate 			psuedoelif = YES;
208*0Sstevel@tonic-gate 			goto more;
209*0Sstevel@tonic-gate 			/* NOTREACHED */
210*0Sstevel@tonic-gate 		}
211*0Sstevel@tonic-gate \#[ \t]*ifn?(def)?	{ /* #if, #ifdef or #ifndef */
212*0Sstevel@tonic-gate 			elseelif = NO;
213*0Sstevel@tonic-gate 			if (psuedoelif == YES) {
214*0Sstevel@tonic-gate 				psuedoelif = NO;
215*0Sstevel@tonic-gate 				goto elif;
216*0Sstevel@tonic-gate 			}
217*0Sstevel@tonic-gate 			/*
218*0Sstevel@tonic-gate 			 * make sure there is room for the current brace count
219*0Sstevel@tonic-gate 			 */
220*0Sstevel@tonic-gate 			if (iflevel == miflevel) {
221*0Sstevel@tonic-gate 				miflevel += IFLEVELINC;
222*0Sstevel@tonic-gate 				maxifbraces = myrealloc(maxifbraces,
223*0Sstevel@tonic-gate 				    miflevel * sizeof (int));
224*0Sstevel@tonic-gate 				preifbraces = myrealloc(preifbraces,
225*0Sstevel@tonic-gate 				    miflevel * sizeof (int));
226*0Sstevel@tonic-gate 			}
227*0Sstevel@tonic-gate 			/* push the current brace count */
228*0Sstevel@tonic-gate 			preifbraces[iflevel] = braces;
229*0Sstevel@tonic-gate 			maxifbraces[iflevel++] = 0;
230*0Sstevel@tonic-gate 			goto more;
231*0Sstevel@tonic-gate 			/* NOTREACHED */
232*0Sstevel@tonic-gate 		}
233*0Sstevel@tonic-gate \#[ \t]*el(se|if)	{ /* #elif or #else */
234*0Sstevel@tonic-gate 			elseelif = YES;
235*0Sstevel@tonic-gate 		elif:
236*0Sstevel@tonic-gate 			if (iflevel > 0) {
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 				/* save the maximum brace count for this #if */
239*0Sstevel@tonic-gate 				if (braces > maxifbraces[iflevel]) {
240*0Sstevel@tonic-gate 					maxifbraces[iflevel - 1] = braces;
241*0Sstevel@tonic-gate 				}
242*0Sstevel@tonic-gate 				/* restore the brace count to before the #if */
243*0Sstevel@tonic-gate 				braces = preifbraces[iflevel - 1];
244*0Sstevel@tonic-gate 			}
245*0Sstevel@tonic-gate 			goto more;
246*0Sstevel@tonic-gate 			/* NOTREACHED */
247*0Sstevel@tonic-gate 		}
248*0Sstevel@tonic-gate \#[ \t]*endif	{	/* #endif */
249*0Sstevel@tonic-gate 		endif:
250*0Sstevel@tonic-gate 			if (iflevel > 0) {
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 				/* get the maximum brace count for this #if */
253*0Sstevel@tonic-gate 				if (braces < maxifbraces[--iflevel]) {
254*0Sstevel@tonic-gate 					braces = maxifbraces[iflevel];
255*0Sstevel@tonic-gate 				}
256*0Sstevel@tonic-gate 			}
257*0Sstevel@tonic-gate 			goto more;
258*0Sstevel@tonic-gate 			/* NOTREACHED */
259*0Sstevel@tonic-gate 		}
260*0Sstevel@tonic-gate \}		{
261*0Sstevel@tonic-gate 			/* could be the last enum member initializer */
262*0Sstevel@tonic-gate 			if (braces == initializerbraces) {
263*0Sstevel@tonic-gate 				initializerbraces = -1;
264*0Sstevel@tonic-gate 				initializer = NO;
265*0Sstevel@tonic-gate 			}
266*0Sstevel@tonic-gate 			if (--braces <= 0) {
267*0Sstevel@tonic-gate 		endstate:
268*0Sstevel@tonic-gate 				braces = 0;
269*0Sstevel@tonic-gate 				classdef = NO;
270*0Sstevel@tonic-gate 			}
271*0Sstevel@tonic-gate 			/*
272*0Sstevel@tonic-gate 			 * if the end of an outermost enum/struct/union
273*0Sstevel@tonic-gate 			 * definition
274*0Sstevel@tonic-gate 			 */
275*0Sstevel@tonic-gate 			if (esudef == YES && braces == esubraces) {
276*0Sstevel@tonic-gate 				esudef = NO;
277*0Sstevel@tonic-gate 				esubraces = -1;
278*0Sstevel@tonic-gate 				last = first;
279*0Sstevel@tonic-gate 				yymore();
280*0Sstevel@tonic-gate 				return (ESUEND);
281*0Sstevel@tonic-gate 			}
282*0Sstevel@tonic-gate 			/* if the end of a function */
283*0Sstevel@tonic-gate 			if ((braces == 0 || braces == 1 && classdef == YES) &&
284*0Sstevel@tonic-gate 			    fcndef == YES) {
285*0Sstevel@tonic-gate 				fcndef = NO;
286*0Sstevel@tonic-gate 				globalscope = YES;
287*0Sstevel@tonic-gate 				last = first;
288*0Sstevel@tonic-gate 				yymore();
289*0Sstevel@tonic-gate 				return (FCNEND);
290*0Sstevel@tonic-gate 			}
291*0Sstevel@tonic-gate 			goto more;
292*0Sstevel@tonic-gate 			/* NOTREACHED */
293*0Sstevel@tonic-gate 		}
294*0Sstevel@tonic-gate \(		{
295*0Sstevel@tonic-gate 			/*
296*0Sstevel@tonic-gate 			 * count unmatched left parentheses for function
297*0Sstevel@tonic-gate 			 * templates
298*0Sstevel@tonic-gate 			 */
299*0Sstevel@tonic-gate 			++parens;
300*0Sstevel@tonic-gate 			goto more;
301*0Sstevel@tonic-gate 			/* NOTREACHED */
302*0Sstevel@tonic-gate 		}
303*0Sstevel@tonic-gate \)		{
304*0Sstevel@tonic-gate 			if (--parens <= 0) {
305*0Sstevel@tonic-gate 				parens = 0;
306*0Sstevel@tonic-gate 			}
307*0Sstevel@tonic-gate 			/* if the end of a function template */
308*0Sstevel@tonic-gate 			if (parens == templateparens) {
309*0Sstevel@tonic-gate 				templateparens = -1;
310*0Sstevel@tonic-gate 				template = NO;
311*0Sstevel@tonic-gate 			}
312*0Sstevel@tonic-gate 			goto more;
313*0Sstevel@tonic-gate 			/* NOTREACHED */
314*0Sstevel@tonic-gate 		}
315*0Sstevel@tonic-gate =		{	/* if a global definition initializer */
316*0Sstevel@tonic-gate 			if ((globalscope == YES || localdef == YES) &&
317*0Sstevel@tonic-gate 			    notpp()) {
318*0Sstevel@tonic-gate 				initializerbraces = braces;
319*0Sstevel@tonic-gate 				initializer = YES;
320*0Sstevel@tonic-gate 			}
321*0Sstevel@tonic-gate 			goto more;
322*0Sstevel@tonic-gate 			/* NOTREACHED */
323*0Sstevel@tonic-gate 		}
324*0Sstevel@tonic-gate :		{	/* if a structure field */
325*0Sstevel@tonic-gate 			/* note: a pr header has a colon in the date */
326*0Sstevel@tonic-gate 			if (esudef == YES && notpp()) {
327*0Sstevel@tonic-gate 				structfield = YES;
328*0Sstevel@tonic-gate 			}
329*0Sstevel@tonic-gate 			goto more;
330*0Sstevel@tonic-gate 			/* NOTREACHED */
331*0Sstevel@tonic-gate 		}
332*0Sstevel@tonic-gate \,		{
333*0Sstevel@tonic-gate 			if (braces == initializerbraces) {
334*0Sstevel@tonic-gate 				initializerbraces = -1;
335*0Sstevel@tonic-gate 				initializer = NO;
336*0Sstevel@tonic-gate 			}
337*0Sstevel@tonic-gate 			structfield = NO;
338*0Sstevel@tonic-gate 			goto more;
339*0Sstevel@tonic-gate 			/* NOTREACHED */
340*0Sstevel@tonic-gate 		}
341*0Sstevel@tonic-gate "##"		|	/* start of Ingres(TM) code line */
342*0Sstevel@tonic-gate ;		{
343*0Sstevel@tonic-gate 			/* if not in an enum/struct/union declaration */
344*0Sstevel@tonic-gate 			if (esudef == NO) {
345*0Sstevel@tonic-gate 				externdec = NO;
346*0Sstevel@tonic-gate 				typedefdef = NO;
347*0Sstevel@tonic-gate 				localdef = NO;
348*0Sstevel@tonic-gate 			}
349*0Sstevel@tonic-gate 			structfield = NO;
350*0Sstevel@tonic-gate 			initializer = NO;
351*0Sstevel@tonic-gate 			oldtype = NO;
352*0Sstevel@tonic-gate 			goto more;
353*0Sstevel@tonic-gate 			/* NOTREACHED */
354*0Sstevel@tonic-gate 		}
355*0Sstevel@tonic-gate \#[ \t]*define[ \t]+{identifier}	{
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 			/* preprocessor macro or constant definition */
358*0Sstevel@tonic-gate 			ppdefine = YES;
359*0Sstevel@tonic-gate 			token = DEFINE;
360*0Sstevel@tonic-gate 			if (compress == YES) {
361*0Sstevel@tonic-gate 				/* compress the keyword */
362*0Sstevel@tonic-gate 				yytext[0] = '\7';
363*0Sstevel@tonic-gate 			}
364*0Sstevel@tonic-gate 		findident:
365*0Sstevel@tonic-gate 			first = yyleng - 1;
366*0Sstevel@tonic-gate 			while (isalnum(yytext[first]) || yytext[first] == '_') {
367*0Sstevel@tonic-gate 				--first;
368*0Sstevel@tonic-gate 			}
369*0Sstevel@tonic-gate 			++first;
370*0Sstevel@tonic-gate 			goto iflongline;
371*0Sstevel@tonic-gate 			/* NOTREACHED */
372*0Sstevel@tonic-gate 		}
373*0Sstevel@tonic-gate class[ \t]+{identifier}[ \t\n\ra-zA-Z0-9_():]*\{	{
374*0Sstevel@tonic-gate 			/* class definition */
375*0Sstevel@tonic-gate 			classdef = YES;
376*0Sstevel@tonic-gate 			cesudeftoken = 'c';
377*0Sstevel@tonic-gate 			REJECT;
378*0Sstevel@tonic-gate 			/* NOTREACHED */
379*0Sstevel@tonic-gate 		}
380*0Sstevel@tonic-gate (enum|struct|union)/([ \t\n\r]+{identifier})?[ \t\n\r]*\{	{
381*0Sstevel@tonic-gate 			/* enum/struct/union definition */
382*0Sstevel@tonic-gate 			esudef = YES;
383*0Sstevel@tonic-gate 			if (esubraces < 0) {
384*0Sstevel@tonic-gate 				/* if outermost enum/struct/union */
385*0Sstevel@tonic-gate 				esubraces = braces;
386*0Sstevel@tonic-gate 			}
387*0Sstevel@tonic-gate 			cesudeftoken = *(yytext + first);
388*0Sstevel@tonic-gate 			goto iflongline;
389*0Sstevel@tonic-gate 			/* NOTREACHED */
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate {identifier}/[ \t]*\(([ \t\n\ra-zA-Z0-9_*&[\]=,.]*|\([ \ta-zA-Z0-9_*[\],]*\))*\)[ \t\n\r()]*[:a-zA-Z_#{]	{
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 			/*
394*0Sstevel@tonic-gate 			 * warning: "if (...)" must not overflow yytext, so
395*0Sstevel@tonic-gate 			 * the content of function argument definitions is
396*0Sstevel@tonic-gate 			 * restricted, in particular parentheses are
397*0Sstevel@tonic-gate 			 * not allowed
398*0Sstevel@tonic-gate 			 */
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 			if (asy) {
401*0Sstevel@tonic-gate 				/*
402*0Sstevel@tonic-gate 				 * In assembly files, if it looks like
403*0Sstevel@tonic-gate 				 * a definition, pass it down as one and we'll
404*0Sstevel@tonic-gate 				 * take care of it later.
405*0Sstevel@tonic-gate 				 */
406*0Sstevel@tonic-gate 				token = FCNDEF;
407*0Sstevel@tonic-gate 				goto iflongline;
408*0Sstevel@tonic-gate 			}
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 			/* if a function definition */
411*0Sstevel@tonic-gate 			/*
412*0Sstevel@tonic-gate 			 * note: "#define a (b) {" and "#if defined(a)\n#"
413*0Sstevel@tonic-gate 			 * are not
414*0Sstevel@tonic-gate 			 */
415*0Sstevel@tonic-gate 			if (braces == 0 && notpp() && rules == NO ||
416*0Sstevel@tonic-gate 			    braces == 1 && classdef == YES) {
417*0Sstevel@tonic-gate 				fcndef = YES;
418*0Sstevel@tonic-gate 				token = FCNDEF;
419*0Sstevel@tonic-gate 				globalscope = NO;
420*0Sstevel@tonic-gate 				goto iflongline;
421*0Sstevel@tonic-gate 			}
422*0Sstevel@tonic-gate 			goto iffcncall;
423*0Sstevel@tonic-gate 			/* NOTREACHED */
424*0Sstevel@tonic-gate 		}
425*0Sstevel@tonic-gate {identifier}/[ \t]*\(	{
426*0Sstevel@tonic-gate 			if (asy) {
427*0Sstevel@tonic-gate 				/*
428*0Sstevel@tonic-gate 				 * Macro calls can get here if they have
429*0Sstevel@tonic-gate 				 * arguments which contain %'s (i.e.,
430*0Sstevel@tonic-gate 				 * registers).
431*0Sstevel@tonic-gate 				 */
432*0Sstevel@tonic-gate 				token = FCNDEF;
433*0Sstevel@tonic-gate 				goto iflongline;
434*0Sstevel@tonic-gate 			}
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 			/* if a function call */
437*0Sstevel@tonic-gate 		iffcncall:
438*0Sstevel@tonic-gate 			if ((fcndef == YES || ppdefine == YES ||
439*0Sstevel@tonic-gate 			    rules == YES) && externdec == NO &&
440*0Sstevel@tonic-gate 			    (localdef == NO || initializer == YES)) {
441*0Sstevel@tonic-gate 				token = FCNCALL;
442*0Sstevel@tonic-gate 				goto iflongline;
443*0Sstevel@tonic-gate 			}
444*0Sstevel@tonic-gate 			if (template == NO && typedefdef == NO) {
445*0Sstevel@tonic-gate 				templateparens = parens;
446*0Sstevel@tonic-gate 				template = YES;
447*0Sstevel@tonic-gate 			}
448*0Sstevel@tonic-gate 			token = IDENT;
449*0Sstevel@tonic-gate 			goto iflongline;
450*0Sstevel@tonic-gate 			/* NOTREACHED */
451*0Sstevel@tonic-gate 		}
452*0Sstevel@tonic-gate (\+\+|--)[ \t]*{identifier}	{	/* prefix increment or decrement */
453*0Sstevel@tonic-gate 			token = ASSIGNMENT;
454*0Sstevel@tonic-gate 			goto findident;
455*0Sstevel@tonic-gate 			/* NOTREACHED */
456*0Sstevel@tonic-gate 		}
457*0Sstevel@tonic-gate {identifier}/[ \t]*(\+\+|--)	{	/* postfix increment or decrement */
458*0Sstevel@tonic-gate 			token = ASSIGNMENT;
459*0Sstevel@tonic-gate 			goto iflongline;
460*0Sstevel@tonic-gate 			/* NOTREACHED */
461*0Sstevel@tonic-gate 		}
462*0Sstevel@tonic-gate \*[ \t]*{identifier}/[ \t]*[^a-zA-Z0-9_(+-][^+-]	{
463*0Sstevel@tonic-gate 			/* indirect assignment or dcl */
464*0Sstevel@tonic-gate 			while (!isalnum(yytext[first]) &&
465*0Sstevel@tonic-gate 			    yytext[first] != '_') {
466*0Sstevel@tonic-gate 				++first;
467*0Sstevel@tonic-gate 			}
468*0Sstevel@tonic-gate 			goto ident;
469*0Sstevel@tonic-gate 			/* NOTREACHED */
470*0Sstevel@tonic-gate 		}
471*0Sstevel@tonic-gate {identifier}/[ \t\n\r]*(=[^=]|[-+*/%&^|]=|<<=|>>=)	{ /* assignment */
472*0Sstevel@tonic-gate 			if ((fcndef == YES || ppdefine == YES ||
473*0Sstevel@tonic-gate 			    rules == YES) && localdef == NO) {
474*0Sstevel@tonic-gate 				token = ASSIGNMENT;
475*0Sstevel@tonic-gate 				goto iflongline;
476*0Sstevel@tonic-gate 			}
477*0Sstevel@tonic-gate 			goto ident;
478*0Sstevel@tonic-gate 			/* NOTREACHED */
479*0Sstevel@tonic-gate 		}
480*0Sstevel@tonic-gate {identifier}/[* \t\n\r]+[a-zA-Z0-9_]	{	/* possible typedef name use */
481*0Sstevel@tonic-gate 			if (notpp() && esudef == NO && fcndef == YES &&
482*0Sstevel@tonic-gate 			    typedefdef == NO && parens == 0) {
483*0Sstevel@tonic-gate 				char	c, *s = yytext + first - 1;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 				while (--s >= yytext && (c = *s) != ';' &&
486*0Sstevel@tonic-gate 				    c != '{') {
487*0Sstevel@tonic-gate 					if (!isspace(c) && !isalpha(c)) {
488*0Sstevel@tonic-gate 						goto nottypedefname;
489*0Sstevel@tonic-gate 					}
490*0Sstevel@tonic-gate 				}
491*0Sstevel@tonic-gate 				typedefname = YES;
492*0Sstevel@tonic-gate 			}
493*0Sstevel@tonic-gate 		nottypedefname:
494*0Sstevel@tonic-gate 			/* skip the global/parameter/local tests */
495*0Sstevel@tonic-gate 			token = IDENT;
496*0Sstevel@tonic-gate 			goto iflongline;
497*0Sstevel@tonic-gate 			/* NOTREACHED */
498*0Sstevel@tonic-gate 		}
499*0Sstevel@tonic-gate {identifier}	{
500*0Sstevel@tonic-gate 			struct	keystruct *p;
501*0Sstevel@tonic-gate 			char	*s;
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 		ident:	token = IDENT;
504*0Sstevel@tonic-gate 			if (notpp() && externdec == NO &&
505*0Sstevel@tonic-gate 			    arraydimension == NO && initializer == NO) {
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate 				/* if an enum/struct/union member definition */
508*0Sstevel@tonic-gate 				if (esudef == YES) {
509*0Sstevel@tonic-gate 					if (structfield == NO) {
510*0Sstevel@tonic-gate 						token = MEMBERDEF;
511*0Sstevel@tonic-gate 					}
512*0Sstevel@tonic-gate 				} else if (typedefdef == YES && oldtype == NO) {
513*0Sstevel@tonic-gate 					/* if a typedef name */
514*0Sstevel@tonic-gate 					token = TYPEDEF;
515*0Sstevel@tonic-gate 				} else if (globalscope == YES &&
516*0Sstevel@tonic-gate 				    template == NO && oldtype == NO) {
517*0Sstevel@tonic-gate 					/* if a global definition */
518*0Sstevel@tonic-gate 					token = GLOBALDEF;
519*0Sstevel@tonic-gate 				} else if (fcndef == YES && braces == 0) {
520*0Sstevel@tonic-gate 					/* if a function parameter definition */
521*0Sstevel@tonic-gate 					token = PARAMETER;
522*0Sstevel@tonic-gate 				} else if (localdef == YES) {
523*0Sstevel@tonic-gate 					/* if a local definition */
524*0Sstevel@tonic-gate 					token = LOCALDEF;
525*0Sstevel@tonic-gate 				}
526*0Sstevel@tonic-gate 			}
527*0Sstevel@tonic-gate 		iflongline:
528*0Sstevel@tonic-gate 			/* if a long line */
529*0Sstevel@tonic-gate 			if (yyleng > STMTMAX) {
530*0Sstevel@tonic-gate 				int	c;
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate 				/* skip to the end of the line */
533*0Sstevel@tonic-gate 				warning("line too long");
534*0Sstevel@tonic-gate 				while ((c = input()) != LEXEOF) {
535*0Sstevel@tonic-gate 					if (c == '\n') {
536*0Sstevel@tonic-gate 						unput(c);
537*0Sstevel@tonic-gate 						break;
538*0Sstevel@tonic-gate 					}
539*0Sstevel@tonic-gate 				}
540*0Sstevel@tonic-gate 			}
541*0Sstevel@tonic-gate 			/* truncate a long symbol */
542*0Sstevel@tonic-gate 			if (yyleng - first > PATLEN) {
543*0Sstevel@tonic-gate 				warning("symbol too long");
544*0Sstevel@tonic-gate 				yyleng = first + PATLEN;
545*0Sstevel@tonic-gate 				yytext[yyleng] = '\0';
546*0Sstevel@tonic-gate 			}
547*0Sstevel@tonic-gate 
548*0Sstevel@tonic-gate 			yymore();
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 			if (asy) {
551*0Sstevel@tonic-gate 				int t;
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate 				last = yyleng;
554*0Sstevel@tonic-gate 				t = do_assembly(token);
555*0Sstevel@tonic-gate 				if (t >= 0) {
556*0Sstevel@tonic-gate 					token = t;
557*0Sstevel@tonic-gate 					return (token);
558*0Sstevel@tonic-gate 				}
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 				goto end;
561*0Sstevel@tonic-gate 			}
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 			/* if a keyword */
564*0Sstevel@tonic-gate 			if ((p = lookup(yytext + first)) != NULL) {
565*0Sstevel@tonic-gate 				first = yyleng;
566*0Sstevel@tonic-gate 				s = p->text;
567*0Sstevel@tonic-gate 
568*0Sstevel@tonic-gate 				/* if an extern declaration */
569*0Sstevel@tonic-gate 				if (s == externtext) {
570*0Sstevel@tonic-gate 					externdec = YES;
571*0Sstevel@tonic-gate 				} else if (s == typedeftext) {
572*0Sstevel@tonic-gate 					/* if a typedef name definition */
573*0Sstevel@tonic-gate 					typedefdef = YES;
574*0Sstevel@tonic-gate 					oldtype = YES;
575*0Sstevel@tonic-gate 				} else if (p->type == DECL && fcndef == YES &&
576*0Sstevel@tonic-gate 				    typedefdef == NO && parens == 0) {
577*0Sstevel@tonic-gate 					/* if a local definition */
578*0Sstevel@tonic-gate 					localdef = YES;
579*0Sstevel@tonic-gate 				} else if (templateparens == parens &&
580*0Sstevel@tonic-gate 				    template == YES) {
581*0Sstevel@tonic-gate 					/*
582*0Sstevel@tonic-gate 					 * keyword doesn't start a function
583*0Sstevel@tonic-gate 					 * template
584*0Sstevel@tonic-gate 					 */
585*0Sstevel@tonic-gate 					templateparens = -1;
586*0Sstevel@tonic-gate 					template = NO;
587*0Sstevel@tonic-gate 				} else {
588*0Sstevel@tonic-gate 					/*
589*0Sstevel@tonic-gate 					 * next identifier after typedef was
590*0Sstevel@tonic-gate 					 * a keyword
591*0Sstevel@tonic-gate 					 */
592*0Sstevel@tonic-gate 					oldtype = NO;
593*0Sstevel@tonic-gate 				}
594*0Sstevel@tonic-gate 				typedefname = NO;
595*0Sstevel@tonic-gate 			} else {	/* identifier */
596*0Sstevel@tonic-gate 				last = yyleng;
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 				/*
599*0Sstevel@tonic-gate 				 * if an enum/struct/union keyword preceded
600*0Sstevel@tonic-gate 				 * this ident.
601*0Sstevel@tonic-gate 				 */
602*0Sstevel@tonic-gate 				if (esudef == YES && cesudeftoken) {
603*0Sstevel@tonic-gate 					token = cesudeftoken;
604*0Sstevel@tonic-gate 					cesudeftoken = '\0';
605*0Sstevel@tonic-gate 				} else {
606*0Sstevel@tonic-gate 					oldtype = NO;
607*0Sstevel@tonic-gate 				}
608*0Sstevel@tonic-gate 				/* if a local definition using a typedef name */
609*0Sstevel@tonic-gate 				if (typedefname == YES) {
610*0Sstevel@tonic-gate 					localdef = YES;
611*0Sstevel@tonic-gate 				}
612*0Sstevel@tonic-gate 				typedefname = NO;
613*0Sstevel@tonic-gate 				return (token);
614*0Sstevel@tonic-gate 			}
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 		end:
617*0Sstevel@tonic-gate 			;
618*0Sstevel@tonic-gate 		}
619*0Sstevel@tonic-gate \[		{	/* array dimension (don't worry about subscripts) */
620*0Sstevel@tonic-gate 			arraydimension = YES;
621*0Sstevel@tonic-gate 			goto more;
622*0Sstevel@tonic-gate 			/* NOTREACHED */
623*0Sstevel@tonic-gate 		}
624*0Sstevel@tonic-gate \]		{
625*0Sstevel@tonic-gate 			arraydimension = NO;
626*0Sstevel@tonic-gate 			goto more;
627*0Sstevel@tonic-gate 			/* NOTREACHED */
628*0Sstevel@tonic-gate 		}
629*0Sstevel@tonic-gate \\\n		{	/* preprocessor statement is continued on next line */
630*0Sstevel@tonic-gate 			goto eol;
631*0Sstevel@tonic-gate 			/* NOTREACHED */
632*0Sstevel@tonic-gate 		}
633*0Sstevel@tonic-gate \n		{	/* end of the line */
634*0Sstevel@tonic-gate 			if (ppdefine == YES) {	/* end of a #define */
635*0Sstevel@tonic-gate 				ppdefine = NO;
636*0Sstevel@tonic-gate 				(void) yyless(yyleng - 1);	/* rescan \n */
637*0Sstevel@tonic-gate 				last = first;
638*0Sstevel@tonic-gate 				yymore();
639*0Sstevel@tonic-gate 				return (DEFINEEND);
640*0Sstevel@tonic-gate 			}
641*0Sstevel@tonic-gate 			/*
642*0Sstevel@tonic-gate 			 * skip the first 8 columns of a breakpoint listing
643*0Sstevel@tonic-gate 			 * line and skip the file path in the page header
644*0Sstevel@tonic-gate 			 */
645*0Sstevel@tonic-gate 			if (bplisting == YES) {
646*0Sstevel@tonic-gate 				int	c, i;
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 				switch (input()) {
649*0Sstevel@tonic-gate 				/* tab and EOF just fall through */
650*0Sstevel@tonic-gate 				case ' ':	/* breakpoint number line */
651*0Sstevel@tonic-gate 				case '[':
652*0Sstevel@tonic-gate 					for (i = 1; i < 8 && input() != LEXEOF;
653*0Sstevel@tonic-gate 					    ++i) {
654*0Sstevel@tonic-gate 					    /*EMPTY*/
655*0Sstevel@tonic-gate 					}
656*0Sstevel@tonic-gate 					break;
657*0Sstevel@tonic-gate 				case '.':	/* header line */
658*0Sstevel@tonic-gate 				case '/':
659*0Sstevel@tonic-gate 					/* skip to the end of the line */
660*0Sstevel@tonic-gate 					while ((c = input()) != LEXEOF) {
661*0Sstevel@tonic-gate 						if (c == '\n') {
662*0Sstevel@tonic-gate 							unput(c);
663*0Sstevel@tonic-gate 							break;
664*0Sstevel@tonic-gate 						}
665*0Sstevel@tonic-gate 					}
666*0Sstevel@tonic-gate 					break;
667*0Sstevel@tonic-gate 				case '\n':	/* empty line */
668*0Sstevel@tonic-gate 					unput('\n');
669*0Sstevel@tonic-gate 					break;
670*0Sstevel@tonic-gate 				}
671*0Sstevel@tonic-gate 			}
672*0Sstevel@tonic-gate 		eol:
673*0Sstevel@tonic-gate 			++yylineno;
674*0Sstevel@tonic-gate 			first = 0;
675*0Sstevel@tonic-gate 			last = 0;
676*0Sstevel@tonic-gate 			if (symbols > 0) {
677*0Sstevel@tonic-gate 				return (NEWLINE);
678*0Sstevel@tonic-gate 			}
679*0Sstevel@tonic-gate 			lineno = yylineno;
680*0Sstevel@tonic-gate 		}
681*0Sstevel@tonic-gate \'		{	/* character constant */
682*0Sstevel@tonic-gate 			if (sdl == NO) {
683*0Sstevel@tonic-gate 				multicharconstant('\'');
684*0Sstevel@tonic-gate 			}
685*0Sstevel@tonic-gate 			goto more;
686*0Sstevel@tonic-gate 			/* NOTREACHED */
687*0Sstevel@tonic-gate 		}
688*0Sstevel@tonic-gate \"		{	/* string constant */
689*0Sstevel@tonic-gate 			multicharconstant('"');
690*0Sstevel@tonic-gate 			goto more;
691*0Sstevel@tonic-gate 			/* NOTREACHED */
692*0Sstevel@tonic-gate 		}
693*0Sstevel@tonic-gate ^[ \t\f\b]+	{	/* don't save leading white space */
694*0Sstevel@tonic-gate 		}
695*0Sstevel@tonic-gate \#[# \t]*include[ \t]*["<][^"> \t\n\r]+	{ /* #include or Ingres ##include */
696*0Sstevel@tonic-gate 			char	*s;
697*0Sstevel@tonic-gate 
698*0Sstevel@tonic-gate 			s = strpbrk(yytext, "\"<");
699*0Sstevel@tonic-gate 			incfile(s + 1, *s);
700*0Sstevel@tonic-gate 			first = s - yytext;
701*0Sstevel@tonic-gate 			last = yyleng;
702*0Sstevel@tonic-gate 			if (compress == YES) {
703*0Sstevel@tonic-gate 				/* compress the keyword */
704*0Sstevel@tonic-gate 				yytext[0] = '\1';
705*0Sstevel@tonic-gate 			}
706*0Sstevel@tonic-gate 			/*
707*0Sstevel@tonic-gate 			 * avoid multicharconstant call triggered by trailing
708*0Sstevel@tonic-gate 			 * ", which puts a trailing comment in the database
709*0Sstevel@tonic-gate 			 */
710*0Sstevel@tonic-gate 			if (*s == '"') {
711*0Sstevel@tonic-gate 				int	c;
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate 				while ((c = input()) != LEXEOF) {
714*0Sstevel@tonic-gate 					if (c == '"') {
715*0Sstevel@tonic-gate 						yytext[yyleng] = '"';
716*0Sstevel@tonic-gate 						yytext[++yyleng] = '\0';
717*0Sstevel@tonic-gate 						break;
718*0Sstevel@tonic-gate 					}
719*0Sstevel@tonic-gate 					/* the trailing '"' may be missing */
720*0Sstevel@tonic-gate 					if (c == '\n') {
721*0Sstevel@tonic-gate 						unput('\n');
722*0Sstevel@tonic-gate 						break;
723*0Sstevel@tonic-gate 					}
724*0Sstevel@tonic-gate 				}
725*0Sstevel@tonic-gate 			}
726*0Sstevel@tonic-gate 			yymore();
727*0Sstevel@tonic-gate 			return (INCLUDE);
728*0Sstevel@tonic-gate 			/* NOTREACHED */
729*0Sstevel@tonic-gate 		}
730*0Sstevel@tonic-gate \#[ \t]*pragma[ \t]+weak[ \t]+{identifier} {
731*0Sstevel@tonic-gate 			ppdefine = YES;
732*0Sstevel@tonic-gate 			token = DEFINE;
733*0Sstevel@tonic-gate 			goto findident;
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 			/*NOTREACHED*/
736*0Sstevel@tonic-gate 		}
737*0Sstevel@tonic-gate \#[ \t]*{identifier}	|	/* preprocessor keyword */
738*0Sstevel@tonic-gate {number}	|	/* number */
739*0Sstevel@tonic-gate .		{	/* punctuation and operators */
740*0Sstevel@tonic-gate 		more:	first = yyleng;
741*0Sstevel@tonic-gate 			yymore();
742*0Sstevel@tonic-gate 		}
743*0Sstevel@tonic-gate %%
744*0Sstevel@tonic-gate 
745*0Sstevel@tonic-gate void
746*0Sstevel@tonic-gate initscanner(char *srcfile)
747*0Sstevel@tonic-gate {
748*0Sstevel@tonic-gate 	char	*s;
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 	if (maxifbraces == NULL) {
751*0Sstevel@tonic-gate 		maxifbraces = mymalloc(miflevel * sizeof (int));
752*0Sstevel@tonic-gate 		preifbraces = mymalloc(miflevel * sizeof (int));
753*0Sstevel@tonic-gate 	}
754*0Sstevel@tonic-gate 	first = 0;		/* buffer index for first char of symbol */
755*0Sstevel@tonic-gate 	last = 0;		/* buffer index for last char of symbol */
756*0Sstevel@tonic-gate 	lineno = 1;		/* symbol line number */
757*0Sstevel@tonic-gate 	yylineno = 1;		/* input line number */
758*0Sstevel@tonic-gate 	arraydimension = NO;	/* inside array dimension declaration */
759*0Sstevel@tonic-gate 	bplisting = NO;		/* breakpoint listing */
760*0Sstevel@tonic-gate 	braces = 0;		/* unmatched left brace count */
761*0Sstevel@tonic-gate 	cesudeftoken = '\0';	/* class/enum/struct/union definition */
762*0Sstevel@tonic-gate 	classdef = NO;		/* c++ class definition */
763*0Sstevel@tonic-gate 	elseelif = NO;		/* #else or #elif found */
764*0Sstevel@tonic-gate 	esudef = NO;		/* enum/struct/union definition */
765*0Sstevel@tonic-gate 	esubraces = -1;		/* outermost enum/struct/union brace count */
766*0Sstevel@tonic-gate 	externdec = NO;		/* extern declaration */
767*0Sstevel@tonic-gate 	fcndef = NO;		/* function definition */
768*0Sstevel@tonic-gate 	globalscope = YES;	/* file global scope (outside functions) */
769*0Sstevel@tonic-gate 	iflevel = 0;		/* #if nesting level */
770*0Sstevel@tonic-gate 	initializer = NO;	/* data initializer */
771*0Sstevel@tonic-gate 	initializerbraces = -1;	/* data initializer outer brace count */
772*0Sstevel@tonic-gate 	lex = NO;		/* lex file */
773*0Sstevel@tonic-gate 	localdef = NO;		/* function/block local definition */
774*0Sstevel@tonic-gate 	parens = 0;		/* unmatched left parenthesis count */
775*0Sstevel@tonic-gate 	ppdefine = NO;		/* preprocessor define statement */
776*0Sstevel@tonic-gate 	psuedoelif = NO;	/* psuedo-#elif */
777*0Sstevel@tonic-gate 	oldtype = NO;		/* next identifier is an old type */
778*0Sstevel@tonic-gate 	rules = NO;		/* lex/yacc rules */
779*0Sstevel@tonic-gate 	sdl = NO;		/* SDL file */
780*0Sstevel@tonic-gate 	structfield = NO;	/* structure field declaration */
781*0Sstevel@tonic-gate 	template = NO;		/* function template */
782*0Sstevel@tonic-gate 	templateparens = -1;	/* function template outer parentheses count */
783*0Sstevel@tonic-gate 	typedefdef = NO;	/* typedef name definition */
784*0Sstevel@tonic-gate 	typedefname = NO;	/* typedef name use */
785*0Sstevel@tonic-gate 	asy = NO;		/* assembly file */
786*0Sstevel@tonic-gate 	BEGIN 0;
787*0Sstevel@tonic-gate 
788*0Sstevel@tonic-gate 	/* if this is not a C file */
789*0Sstevel@tonic-gate 	if ((s = strrchr(srcfile, '.')) != NULL) {
790*0Sstevel@tonic-gate 		switch (*++s) {	/* this switch saves time on C files */
791*0Sstevel@tonic-gate 		case 'b':
792*0Sstevel@tonic-gate 			if (strcmp(s, "bp") == 0) {	/* breakpoint listing */
793*0Sstevel@tonic-gate 				bplisting = YES;
794*0Sstevel@tonic-gate 			}
795*0Sstevel@tonic-gate 			break;
796*0Sstevel@tonic-gate 		case 'l':
797*0Sstevel@tonic-gate 			if (strcmp(s, "l") == 0) {	/* lex */
798*0Sstevel@tonic-gate 				lex = YES;
799*0Sstevel@tonic-gate 				globalscope = NO;
800*0Sstevel@tonic-gate 			}
801*0Sstevel@tonic-gate 			break;
802*0Sstevel@tonic-gate 		case 'p':
803*0Sstevel@tonic-gate 		case 's':
804*0Sstevel@tonic-gate 			if (strcmp(s, "pr") == 0 ||
805*0Sstevel@tonic-gate 			    strcmp(s, "sd") == 0) {	/* SDL */
806*0Sstevel@tonic-gate 				sdl = YES;
807*0Sstevel@tonic-gate 				BEGIN SDL;
808*0Sstevel@tonic-gate 			} else if (strcmp(s, "s") == 0) {
809*0Sstevel@tonic-gate 				asy = YES;
810*0Sstevel@tonic-gate 			}
811*0Sstevel@tonic-gate 			break;
812*0Sstevel@tonic-gate 		case 'y':
813*0Sstevel@tonic-gate 			if (strcmp(s, "y") == 0) {	/* yacc */
814*0Sstevel@tonic-gate 				globalscope = NO;
815*0Sstevel@tonic-gate 			}
816*0Sstevel@tonic-gate 			break;
817*0Sstevel@tonic-gate 		}
818*0Sstevel@tonic-gate 	}
819*0Sstevel@tonic-gate }
820*0Sstevel@tonic-gate 
821*0Sstevel@tonic-gate int
822*0Sstevel@tonic-gate comment(void)
823*0Sstevel@tonic-gate {
824*0Sstevel@tonic-gate 	int	c, lastc;
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 	do {
827*0Sstevel@tonic-gate 		if ((c = getc(yyin)) == '*') {	/* C comment */
828*0Sstevel@tonic-gate 			lastc = '\0';
829*0Sstevel@tonic-gate 			while ((c = getc(yyin)) != EOF &&
830*0Sstevel@tonic-gate 			    (c != '/' || lastc != '*')) { /* fewer '/'s */
831*0Sstevel@tonic-gate 				if (c == '\n') {
832*0Sstevel@tonic-gate 					++yylineno;
833*0Sstevel@tonic-gate 				}
834*0Sstevel@tonic-gate 				lastc = c;
835*0Sstevel@tonic-gate 			}
836*0Sstevel@tonic-gate 			/* return a blank for Reiser cpp token concatenation */
837*0Sstevel@tonic-gate 			if ((c = getc(yyin)) == '_' || isalnum(c)) {
838*0Sstevel@tonic-gate 				(void) ungetc(c, yyin);
839*0Sstevel@tonic-gate 				c = ' ';
840*0Sstevel@tonic-gate 				break;
841*0Sstevel@tonic-gate 			}
842*0Sstevel@tonic-gate 		} else if (c == '/') {		/* C++ comment */
843*0Sstevel@tonic-gate 			while ((c = getc(yyin)) != EOF && c != '\n') {
844*0Sstevel@tonic-gate 				/*EMPTY*/
845*0Sstevel@tonic-gate 			}
846*0Sstevel@tonic-gate 			break;
847*0Sstevel@tonic-gate 		} else {	/* not a comment */
848*0Sstevel@tonic-gate 			(void) ungetc(c, yyin);
849*0Sstevel@tonic-gate 			c = '/';
850*0Sstevel@tonic-gate 			break;
851*0Sstevel@tonic-gate 		}
852*0Sstevel@tonic-gate 
853*0Sstevel@tonic-gate 		/* there may be an immediately following comment */
854*0Sstevel@tonic-gate 	} while (c == '/');
855*0Sstevel@tonic-gate 	return (c);
856*0Sstevel@tonic-gate }
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate void
859*0Sstevel@tonic-gate multicharconstant(char terminator)
860*0Sstevel@tonic-gate {
861*0Sstevel@tonic-gate 	char	c;
862*0Sstevel@tonic-gate 
863*0Sstevel@tonic-gate 	/* scan until the terminator is found */
864*0Sstevel@tonic-gate 	while ((c = yytext[yyleng++] = noncommentinput()) != terminator) {
865*0Sstevel@tonic-gate 		switch (c) {
866*0Sstevel@tonic-gate 		case '\\':	/* escape character */
867*0Sstevel@tonic-gate 			if ((yytext[yyleng++] = noncommentinput()) == '\n') {
868*0Sstevel@tonic-gate 				++yylineno;
869*0Sstevel@tonic-gate 			}
870*0Sstevel@tonic-gate 			break;
871*0Sstevel@tonic-gate 		case '\t':	/* tab character */
872*0Sstevel@tonic-gate 
873*0Sstevel@tonic-gate 			/* if not a lex program, continue */
874*0Sstevel@tonic-gate 			if (lex == NO) {
875*0Sstevel@tonic-gate 				break;
876*0Sstevel@tonic-gate 			}
877*0Sstevel@tonic-gate 			/* FALLTHROUGH */
878*0Sstevel@tonic-gate 
879*0Sstevel@tonic-gate 		case '\n':	/* illegal character */
880*0Sstevel@tonic-gate 
881*0Sstevel@tonic-gate 			/*
882*0Sstevel@tonic-gate 			 * assume the terminator is missing, so put
883*0Sstevel@tonic-gate 			 * this character back
884*0Sstevel@tonic-gate 			 */
885*0Sstevel@tonic-gate 			unput(c);
886*0Sstevel@tonic-gate 			yytext[--yyleng] = '\0';
887*0Sstevel@tonic-gate 			/* FALLTHROUGH */
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate 		case LEXEOF:	/* end of file */
890*0Sstevel@tonic-gate 			return;
891*0Sstevel@tonic-gate 
892*0Sstevel@tonic-gate 		default:
893*0Sstevel@tonic-gate 			/* change a control character to a blank */
894*0Sstevel@tonic-gate 			if (!isprint(c)) {
895*0Sstevel@tonic-gate 				yytext[yyleng - 1] = ' ';
896*0Sstevel@tonic-gate 			}
897*0Sstevel@tonic-gate 		}
898*0Sstevel@tonic-gate 		/* if this token will overflow the line buffer */
899*0Sstevel@tonic-gate 		/* note: '\\' may cause yyleng to be > STMTMAX */
900*0Sstevel@tonic-gate 		if (yyleng >= STMTMAX) {
901*0Sstevel@tonic-gate 
902*0Sstevel@tonic-gate 			/* truncate the token */
903*0Sstevel@tonic-gate 			while ((c = noncommentinput()) != LEXEOF) {
904*0Sstevel@tonic-gate 				if (c == terminator) {
905*0Sstevel@tonic-gate 					unput(c);
906*0Sstevel@tonic-gate 					break;
907*0Sstevel@tonic-gate 				} else if (c == '\n') {
908*0Sstevel@tonic-gate 					++yylineno;
909*0Sstevel@tonic-gate 				}
910*0Sstevel@tonic-gate 			}
911*0Sstevel@tonic-gate 		}
912*0Sstevel@tonic-gate 	}
913*0Sstevel@tonic-gate 	yytext[yyleng] = '\0';
914*0Sstevel@tonic-gate }
915*0Sstevel@tonic-gate 
916*0Sstevel@tonic-gate /*
917*0Sstevel@tonic-gate  * Returns true if the beginning of str matches ident, and the next character
918*0Sstevel@tonic-gate  * is not alphanumeric and not an underscore.
919*0Sstevel@tonic-gate  */
920*0Sstevel@tonic-gate int
921*0Sstevel@tonic-gate identcmp(const char *str, const char *ident)
922*0Sstevel@tonic-gate {
923*0Sstevel@tonic-gate 	int n = strlen(ident);
924*0Sstevel@tonic-gate 
925*0Sstevel@tonic-gate 	return (strncmp(str, ident, n) == 0 && !isalnum(str[n]) &&
926*0Sstevel@tonic-gate 	    str[n] != '_');
927*0Sstevel@tonic-gate }
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate /*
930*0Sstevel@tonic-gate  * Here we want to
931*0Sstevel@tonic-gate  *   - Make *ENTRY*() macro invocations into function definitions
932*0Sstevel@tonic-gate  *   - Make SET_SIZE() macro calls into function ends
933*0Sstevel@tonic-gate  *   - Make "call sym" instructions into function calls
934*0Sstevel@tonic-gate  *   - Eliminate C function definitions (since they are for lint, and we want
935*0Sstevel@tonic-gate  *     only one definition for each function)
936*0Sstevel@tonic-gate  */
937*0Sstevel@tonic-gate int
938*0Sstevel@tonic-gate do_assembly(int token)
939*0Sstevel@tonic-gate {
940*0Sstevel@tonic-gate 	/* Handle C keywords? */
941*0Sstevel@tonic-gate 
942*0Sstevel@tonic-gate 	switch (token) {
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 	case FCNDEF:
945*0Sstevel@tonic-gate 		/*
946*0Sstevel@tonic-gate 		 * We have a symbol that looks like a C function definition or
947*0Sstevel@tonic-gate 		 * call.  (Note: That can include assembly instructions with
948*0Sstevel@tonic-gate 		 * the right parentheses.)  We want to convert assembly macro
949*0Sstevel@tonic-gate 		 * invocations to function calls, and ignore everything else.
950*0Sstevel@tonic-gate 		 * Since we technically can't tell the difference, we'll use
951*0Sstevel@tonic-gate 		 * an all-caps heuristic.
952*0Sstevel@tonic-gate 		 *
953*0Sstevel@tonic-gate 		 * ... except for SET_SIZE macros, since they will precede
954*0Sstevel@tonic-gate 		 * FUNCEND tokens, which will break code in find.c which
955*0Sstevel@tonic-gate 		 * assumes that FUNCEND tokens occur at the beginning of
956*0Sstevel@tonic-gate 		 * lines.
957*0Sstevel@tonic-gate 		 */
958*0Sstevel@tonic-gate 		if (isupper(yytext[first]) && strcmp(yytext, "SET_SIZE") != 0)
959*0Sstevel@tonic-gate 			return (FCNCALL);
960*0Sstevel@tonic-gate 
961*0Sstevel@tonic-gate 		/* Don't return a token. */
962*0Sstevel@tonic-gate 		return (-1);
963*0Sstevel@tonic-gate 
964*0Sstevel@tonic-gate 	case GLOBALDEF:
965*0Sstevel@tonic-gate 	case IDENT:
966*0Sstevel@tonic-gate 		/* Macro arguments come down as global variable definitions. */
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 		if (identcmp(yytext, "ENTRY") ||
969*0Sstevel@tonic-gate 		    identcmp(yytext, "ENTRY2") ||
970*0Sstevel@tonic-gate 		    identcmp(yytext, "ENTRY_NP") ||
971*0Sstevel@tonic-gate 		    identcmp(yytext, "ENTRY_NP2") ||
972*0Sstevel@tonic-gate 		    identcmp(yytext, "RTENTRY") ||
973*0Sstevel@tonic-gate 		    identcmp(yytext, "ALTENTRY")) {
974*0Sstevel@tonic-gate 			/*
975*0Sstevel@tonic-gate 			 * Identifiers on lines beginning with *ENTRY* macros
976*0Sstevel@tonic-gate 			 * are actually function definitions.
977*0Sstevel@tonic-gate 			 */
978*0Sstevel@tonic-gate 			return (FCNDEF);
979*0Sstevel@tonic-gate 		}
980*0Sstevel@tonic-gate 
981*0Sstevel@tonic-gate 		if (identcmp(yytext, "SET_SIZE")) {
982*0Sstevel@tonic-gate 			/*
983*0Sstevel@tonic-gate 			 * Identifiers on lines beginning with SET_SIZE are
984*0Sstevel@tonic-gate 			 * actually function ends.
985*0Sstevel@tonic-gate 			 */
986*0Sstevel@tonic-gate 			return (FCNEND);
987*0Sstevel@tonic-gate 		}
988*0Sstevel@tonic-gate 
989*0Sstevel@tonic-gate 		if (first != 0 && identcmp(yytext, "call")) {
990*0Sstevel@tonic-gate 			/*
991*0Sstevel@tonic-gate 			 * Make this a function call.  We exclude first == 0,
992*0Sstevel@tonic-gate 			 * because that happens when we're looking at "call"
993*0Sstevel@tonic-gate 			 * itself.  (Then we'd get function calls to "call"
994*0Sstevel@tonic-gate 			 * everywhere.)
995*0Sstevel@tonic-gate 			 */
996*0Sstevel@tonic-gate 			return (FCNCALL);
997*0Sstevel@tonic-gate 		}
998*0Sstevel@tonic-gate 
999*0Sstevel@tonic-gate 	default:
1000*0Sstevel@tonic-gate 		/* Default to normal behavior. */
1001*0Sstevel@tonic-gate 		return (token);
1002*0Sstevel@tonic-gate 	}
1003*0Sstevel@tonic-gate }
1004