%{
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* cscope - interactive C symbol cross-reference
*
*
* C symbol scanner
*/
#ident "@(#)scanner.l 1.2 93/06/07 SMI"
#include "global.h"
/* the line counting has been moved from character reading for speed */
/* comments are discarded */
#define input() \
#define noncommentinput() \
/* not a preprocessor line (allow Ingres(TM) "## char var;" lines) */
/* keyword text for fast testing of keywords in the scanner */
extern char externtext[];
extern char typedeftext[];
int first; /* buffer index for first char of symbol */
int last; /* buffer index for last char of symbol */
int lineno; /* symbol line number */
static int braces; /* unmatched left brace count */
static int cesudeftoken; /* class/enum/struct/union definition */
/* brace count */
/* (outside functions) */
static int iflevel; /* #if nesting level */
static int initializerbraces; /* data initializer outer brace count */
static int *maxifbraces; /* maximum brace count within #if */
static int *preifbraces; /* brace count before #if */
static int parens; /* unmatched left parenthesis count */
static int templateparens; /* function template outer parentheses count */
static int token; /* token found */
void multicharconstant(char terminator);
int do_assembly(int token);
%}
%a 6000
%o 11000
%p 3000
%%
%\{ { /* lex/yacc C declarations/definitions */
globalscope = YES;
goto more;
/* NOTREACHED */
}
%\} {
globalscope = NO;
goto more;
/* NOTREACHED */
}
braces = 0;
/* simulate a yylex() or yyparse() definition */
} else {
/*
* yacc: yyparse implicitly calls yylex
*/
char *s = " yylex()";
while (--cp >= s) {
}
}
yymore();
return (FCNDEF);
} else {
globalscope = YES;
yymore();
return (FCNEND);
}
/* NOTREACHED */
}
braces = 1;
globalscope = NO;
goto findident;
/* NOTREACHED */
}
goto findident; /* treat as function call */
/* NOTREACHED */
}
/* end of an SDL procedure or state */
goto endstate; /* treat as the end of a function */
/* NOTREACHED */
}
\{ {
/* count unmatched left braces for fcn def detection */
++braces;
/*
* can be found
*/
if (cesudeftoken) {
cesudeftoken = '\0';
}
goto more;
/* NOTREACHED */
}
\#[ \t]*endif/.*[\n\r][ \t\n\r]*#[ \t]*if {
/*
* attempt to correct erroneous brace count caused by:
*
* #if ...
* ... {
* #endif
* #if ...
* ... {
* #endif
*/
/* the current #if must not have an #else or #elif */
goto endif;
}
psuedoelif = YES;
goto more;
/* NOTREACHED */
}
if (psuedoelif == YES) {
psuedoelif = NO;
goto elif;
}
/*
* make sure there is room for the current brace count
*/
miflevel += IFLEVELINC;
miflevel * sizeof (int));
miflevel * sizeof (int));
}
/* push the current brace count */
maxifbraces[iflevel++] = 0;
goto more;
/* NOTREACHED */
}
elif:
if (iflevel > 0) {
/* save the maximum brace count for this #if */
}
/* restore the brace count to before the #if */
}
goto more;
/* NOTREACHED */
}
\#[ \t]*endif { /* #endif */
endif:
if (iflevel > 0) {
/* get the maximum brace count for this #if */
}
}
goto more;
/* NOTREACHED */
}
\} {
/* could be the last enum member initializer */
if (braces == initializerbraces) {
initializerbraces = -1;
initializer = NO;
}
if (--braces <= 0) {
braces = 0;
}
/*
* definition
*/
esubraces = -1;
yymore();
return (ESUEND);
}
/* if the end of a function */
globalscope = YES;
yymore();
return (FCNEND);
}
goto more;
/* NOTREACHED */
}
\( {
/*
* count unmatched left parentheses for function
* templates
*/
++parens;
goto more;
/* NOTREACHED */
}
\) {
if (--parens <= 0) {
parens = 0;
}
/* if the end of a function template */
if (parens == templateparens) {
templateparens = -1;
}
goto more;
/* NOTREACHED */
}
= { /* if a global definition initializer */
notpp()) {
initializer = YES;
}
goto more;
/* NOTREACHED */
}
: { /* if a structure field */
/* note: a pr header has a colon in the date */
structfield = YES;
}
goto more;
/* NOTREACHED */
}
\, {
if (braces == initializerbraces) {
initializerbraces = -1;
initializer = NO;
}
structfield = NO;
goto more;
/* NOTREACHED */
}
"##" | /* start of Ingres(TM) code line */
; {
typedefdef = NO;
}
structfield = NO;
initializer = NO;
goto more;
/* NOTREACHED */
}
\#[ \t]*define[ \t]+{identifier} {
/* preprocessor macro or constant definition */
/* compress the keyword */
yytext[0] = '\7';
}
--first;
}
++first;
goto iflongline;
/* NOTREACHED */
}
/* class definition */
cesudeftoken = 'c';
/* NOTREACHED */
}
(enum|struct|union)/([ \t\n\r]+{identifier})?[ \t\n\r]*\{ {
if (esubraces < 0) {
}
goto iflongline;
/* NOTREACHED */
}
{identifier}/[ \t]*\(([ \t\n\ra-zA-Z0-9_*&[\]=,.]*|\([ \ta-zA-Z0-9_*[\],]*\))*\)[ \t\n\r()]*[:a-zA-Z_#{] {
/*
* warning: "if (...)" must not overflow yytext, so
* the content of function argument definitions is
* restricted, in particular parentheses are
* not allowed
*/
if (asy) {
/*
* In assembly files, if it looks like
* a definition, pass it down as one and we'll
* take care of it later.
*/
goto iflongline;
}
/* if a function definition */
/*
* note: "#define a (b) {" and "#if defined(a)\n#"
* are not
*/
globalscope = NO;
goto iflongline;
}
goto iffcncall;
/* NOTREACHED */
}
{identifier}/[ \t]*\( {
if (asy) {
/*
* Macro calls can get here if they have
* arguments which contain %'s (i.e.,
* registers).
*/
goto iflongline;
}
/* if a function call */
goto iflongline;
}
}
goto iflongline;
/* NOTREACHED */
}
(\+\+|--)[ \t]*{identifier} { /* prefix increment or decrement */
token = ASSIGNMENT;
goto findident;
/* NOTREACHED */
}
{identifier}/[ \t]*(\+\+|--) { /* postfix increment or decrement */
token = ASSIGNMENT;
goto iflongline;
/* NOTREACHED */
}
/* indirect assignment or dcl */
++first;
}
goto ident;
/* NOTREACHED */
}
{identifier}/[ \t\n\r]*(=[^=]|[-+*/%&^|]=|<<=|>>=) { /* assignment */
token = ASSIGNMENT;
goto iflongline;
}
goto ident;
/* NOTREACHED */
}
while (--s >= yytext && (c = *s) != ';' &&
c != '{') {
goto nottypedefname;
}
}
typedefname = YES;
}
goto iflongline;
/* NOTREACHED */
}
{identifier} {
struct keystruct *p;
char *s;
if (structfield == NO) {
}
/* if a typedef name */
} else if (globalscope == YES &&
/* if a global definition */
/* if a function parameter definition */
/* if a local definition */
}
}
/* if a long line */
int c;
/* skip to the end of the line */
warning("line too long");
if (c == '\n') {
unput(c);
break;
}
}
}
/* truncate a long symbol */
warning("symbol too long");
}
yymore();
if (asy) {
int t;
t = do_assembly(token);
if (t >= 0) {
token = t;
return (token);
}
goto end;
}
/* if a keyword */
s = p->text;
/* if an extern declaration */
if (s == externtext) {
} else if (s == typedeftext) {
/* if a typedef name definition */
typedefdef = YES;
/* if a local definition */
} else if (templateparens == parens &&
/*
* keyword doesn't start a function
* template
*/
templateparens = -1;
} else {
/*
* next identifier after typedef was
* a keyword
*/
}
typedefname = NO;
} else { /* identifier */
/*
* this ident.
*/
cesudeftoken = '\0';
} else {
}
/* if a local definition using a typedef name */
if (typedefname == YES) {
}
typedefname = NO;
return (token);
}
end:
;
}
\[ { /* array dimension (don't worry about subscripts) */
goto more;
/* NOTREACHED */
}
\] {
arraydimension = NO;
goto more;
/* NOTREACHED */
}
\\\n { /* preprocessor statement is continued on next line */
goto eol;
/* NOTREACHED */
}
\n { /* end of the line */
yymore();
return (DEFINEEND);
}
/*
* skip the first 8 columns of a breakpoint listing
* line and skip the file path in the page header
*/
int c, i;
switch (input()) {
/* tab and EOF just fall through */
case ' ': /* breakpoint number line */
case '[':
++i) {
/*EMPTY*/
}
break;
case '.': /* header line */
case '/':
/* skip to the end of the line */
if (c == '\n') {
unput(c);
break;
}
}
break;
case '\n': /* empty line */
unput('\n');
break;
}
}
eol:
++yylineno;
first = 0;
last = 0;
if (symbols > 0) {
return (NEWLINE);
}
}
\' { /* character constant */
if (sdl == NO) {
multicharconstant('\'');
}
goto more;
/* NOTREACHED */
}
\" { /* string constant */
multicharconstant('"');
goto more;
/* NOTREACHED */
}
}
\#[# \t]*include[ \t]*["<][^"> \t\n\r]+ { /* #include or Ingres ##include */
char *s;
incfile(s + 1, *s);
/* compress the keyword */
yytext[0] = '\1';
}
/*
* avoid multicharconstant call triggered by trailing
* ", which puts a trailing comment in the database
*/
if (*s == '"') {
int c;
if (c == '"') {
break;
}
/* the trailing '"' may be missing */
if (c == '\n') {
unput('\n');
break;
}
}
}
yymore();
return (INCLUDE);
/* NOTREACHED */
}
\#[ \t]*pragma[ \t]+weak[ \t]+{identifier} {
goto findident;
/*NOTREACHED*/
}
\#[ \t]*{identifier} | /* preprocessor keyword */
{number} | /* number */
. { /* punctuation and operators */
yymore();
}
%%
void
initscanner(char *srcfile)
{
char *s;
if (maxifbraces == NULL) {
}
first = 0; /* buffer index for first char of symbol */
last = 0; /* buffer index for last char of symbol */
braces = 0; /* unmatched left brace count */
iflevel = 0; /* #if nesting level */
parens = 0; /* unmatched left parenthesis count */
BEGIN 0;
/* if this is not a C file */
switch (*++s) { /* this switch saves time on C files */
case 'b':
}
break;
case 'l':
globalscope = NO;
}
break;
case 'p':
case 's':
if (strcmp(s, "pr") == 0 ||
} else if (strcmp(s, "s") == 0) {
}
break;
case 'y':
globalscope = NO;
}
break;
}
}
}
int
comment(void)
{
int c, lastc;
do {
lastc = '\0';
if (c == '\n') {
++yylineno;
}
lastc = c;
}
/* return a blank for Reiser cpp token concatenation */
c = ' ';
break;
}
} else if (c == '/') { /* C++ comment */
/*EMPTY*/
}
break;
} else { /* not a comment */
c = '/';
break;
}
/* there may be an immediately following comment */
} while (c == '/');
return (c);
}
void
multicharconstant(char terminator)
{
char c;
/* scan until the terminator is found */
switch (c) {
case '\\': /* escape character */
++yylineno;
}
break;
case '\t': /* tab character */
/* if not a lex program, continue */
break;
}
/* FALLTHROUGH */
case '\n': /* illegal character */
/*
* assume the terminator is missing, so put
* this character back
*/
unput(c);
/* FALLTHROUGH */
case LEXEOF: /* end of file */
return;
default:
/* change a control character to a blank */
if (!isprint(c)) {
}
}
/* if this token will overflow the line buffer */
/* note: '\\' may cause yyleng to be > STMTMAX */
/* truncate the token */
while ((c = noncommentinput()) != LEXEOF) {
if (c == terminator) {
unput(c);
break;
} else if (c == '\n') {
++yylineno;
}
}
}
}
}
/*
* Returns true if the beginning of str matches ident, and the next character
* is not alphanumeric and not an underscore.
*/
int
{
int n = strlen(ident);
str[n] != '_');
}
/*
* Here we want to
* - Make *ENTRY*() macro invocations into function definitions
* - Make SET_SIZE() macro calls into function ends
* - Make "call sym" instructions into function calls
* - Eliminate C function definitions (since they are for lint, and we want
* only one definition for each function)
*/
int
do_assembly(int token)
{
/* Handle C keywords? */
switch (token) {
case FCNDEF:
/*
* We have a symbol that looks like a C function definition or
* call. (Note: That can include assembly instructions with
* the right parentheses.) We want to convert assembly macro
* invocations to function calls, and ignore everything else.
* Since we technically can't tell the difference, we'll use
* an all-caps heuristic.
*
* ... except for SET_SIZE macros, since they will precede
* FUNCEND tokens, which will break code in find.c which
* assumes that FUNCEND tokens occur at the beginning of
* lines.
*/
return (FCNCALL);
/* Don't return a token. */
return (-1);
case GLOBALDEF:
case IDENT:
/* Macro arguments come down as global variable definitions. */
/*
* Identifiers on lines beginning with *ENTRY* macros
* are actually function definitions.
*/
return (FCNDEF);
}
/*
* Identifiers on lines beginning with SET_SIZE are
* actually function ends.
*/
return (FCNEND);
}
/*
* Make this a function call. We exclude first == 0,
* because that happens when we're looking at "call"
* itself. (Then we'd get function calls to "call"
* everywhere.)
*/
return (FCNCALL);
}
default:
/* Default to normal behavior. */
return (token);
}
}