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