* Copyright (c) 1987 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)C.c 5.5 (Berkeley) %G%";
static int func_entry(), str_entry();
static void hash_entry();
* read .c and .h files and call appropriate routines
extern int tflag
; /* -t: create tags for typedefs */
register int c
, /* current character */
register char *sp
; /* buffer pointer */
int token
, /* if reading a token */
t_def
, /* if reading a typedef */
t_level
; /* typedef's brace level */
char tok
[MAXTOKEN
]; /* token buffer */
sp
= tok
; token
= t_def
= NO
; t_level
= -1; level
= 0; lineno
= 1;
* Here's where it DOESN'T handle:
* if level goes below zero, try and fix
* it, even though we've already messed up
* the above 3 cases are similar in that they
* are special characters that also end tokens.
/* we ignore quoted strings and comments in their entirety */
* comments can be fun; note the state is unchanged after
* return, in case we found:
* "foo() XX comment XX { int bar; }"
/* hash marks flag #define's. */
* if we have a current token, parenthesis on
* level zero indicates a function.
* grab the line immediately, we may
* already be wrong, for example,
* semi-colons indicate the end of a typedef; if we find a
* typedef we search for the next semi-colon of the same
* level as the typedef. Ignoring "structs", they are
* tricky, since you can find:
* "typedef unsigned int u_int;"
* "typedef unsigned int u_int [10];"
* If looking at a typedef, we save a copy of the last token
* found. Then, when we find the ';' we take the current
* token if it starts with a valid token name, else we take
* the one we saved. There's probably some reasonable
if (t_def
&& level
== t_level
) {
* store characters until one that can't be part of a token
* comes along; check the current token against certain
storec
: if (!intoken(c
)) {
/* no typedefs inside typedefs */
if (!t_def
&& !bcmp(tok
,"typedef",8)) {
/* catch "typedef struct" */
if ((!t_def
|| t_level
< level
)
&& (!bcmp(tok
,"struct",7)
|| !bcmp(tok
,"enum",5))) {
else if (sp
!= tok
|| begtoken(c
)) {
* handle a function reference
register int c
; /* current character */
* we assume that the character after a function's right paren
* is a token character if it's a function and a non-token
* character if it's a declaration. Comments don't count...
(void)skip_key((int)')');
while (GETC(!=,EOF
) && iswhite(c
))
if (intoken(c
) || c
== (int)'{')
if (c
== (int)'/' && GETC(==,'*'))
else { /* don't ever "read" '/' */
(void)skip_key((int)'{');
* handle a line starting with a '#'
extern int dflag
; /* -d: non-macro defines */
register int c
, /* character read */
curline
; /* line started on */
register char *sp
; /* buffer pointer */
char tok
[MAXTOKEN
]; /* storage buffer */
for (sp
= tok
;;) { /* get next token */
if (bcmp(tok
,"define",6)) /* only interested in #define's */
for (;;) { /* this doesn't handle "#define \n" */
for (sp
= tok
;;) { /* get next token */
* this is where it DOESN'T handle
if (dflag
|| c
== (int)'(') { /* only want macros */
skip
: if (c
== (int)'\n') { /* get rid of rest of define */
(void)skip_key((int)'\n');
* handle a struct, union or enum entry
register int c
; /* current character */
register char *sp
; /* buffer pointer */
int curline
; /* line started on */
char tok
[BUFSIZ
]; /* storage buffer */
if (c
== (int)'{') /* it was "struct {" */
for (sp
= tok
;;) { /* get next token */
case '{': /* it was "struct foo{" */
case '\n': /* it was "struct foo\n" */
default: /* probably "struct foo " */
register int c
, /* character read */
for (star
= 0;GETC(!=,EOF
);)
/* comments don't nest, nor can they be escaped. */
* skip to next char "key"
for (skip
= retval
= NO
;GETC(!=,EOF
);)
case '\\': /* a backslash escapes anything */
skip
= !skip
; /* we toggle in case it's "\\" */
case ';': /* special case for yacc; if one */
case '|': /* of these chars occurs, we may */
retval
= YES
; /* have moved out of the rule */
break; /* not used by C */