Initial commit of ctags utility

This commit is contained in:
taubert 1998-01-24 07:59:11 +00:00
parent 3e68d4bd15
commit bb09eed7f6
14 changed files with 1939 additions and 0 deletions

507
usr.bin/ctags/C.c Normal file
View File

@ -0,0 +1,507 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)C.c 8.4 (Berkeley) 4/2/94";
#endif /* not lint */
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "ctags.h"
static int func_entry __P((void));
static void hash_entry __P((void));
static void skip_string __P((int));
static int str_entry __P((int));
/*
* c_entries --
* read .c and .h files and call appropriate routines
*/
void
c_entries(void)
{
int c; /* current character */
int level; /* brace level */
int token; /* if reading a token */
int t_def; /* if reading a typedef */
int t_level; /* typedef's brace level */
char *sp; /* buffer pointer */
static char tok[MAXTOKEN]; /* token buffer */
lineftell = ftell(inf);
#ifdef __ORCAC203__
sp = tok; token = NO; t_def = NO; t_level = -1; level = 0; lineno = 1;
#else
sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
#endif
while (GETC(!=, EOF)) {
switch (c) {
/*
* Here's where it DOESN'T handle: {
* foo(a)
* {
* #ifdef notdef
* }
* #endif
* if (a)
* puts("hello, world");
* }
*/
case '{':
++level;
goto endtok;
case '}':
/*
* if level goes below zero, try and fix
* it, even though we've already messed up
*/
if (--level < 0)
level = 0;
goto endtok;
case '\n':
SETLINE;
/*
* the above 3 cases are similar in that they
* are special characters that also end tokens.
*/
endtok: if (sp > tok) {
*sp = EOS;
token = YES;
sp = tok;
}
else
token = NO;
continue;
/*
* We ignore quoted strings and character constants
* completely.
*/
case '"':
case '\'':
(void)skip_string(c);
break;
/*
* comments can be fun; note the state is unchanged after
* return, in case we found:
* "foo() XX comment XX { int bar; }"
*/
case '/':
if (GETC(==, '*')) {
skip_comment();
continue;
}
(void)ungetc(c, inf);
c = '/';
goto storec;
/* hash marks flag #define's. */
case '#':
if (sp == tok) {
hash_entry();
break;
}
goto storec;
/*
* if we have a current token, parenthesis on
* level zero indicates a function.
*/
case '(':
if (!level && token) {
int curline;
if (sp != tok)
*sp = EOS;
/*
* grab the line immediately, we may
* already be wrong, for example,
* foo\n
* (arg1,
*/
getline();
curline = lineno;
if (func_entry()) {
++level;
pfnote(tok, curline);
}
break;
}
goto storec;
/*
* 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 long time_t;"
* "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
* alternative to this...
*/
case ';':
if (t_def && level == t_level) {
t_def = NO;
getline();
if (sp != tok)
*sp = EOS;
pfnote(tok, lineno);
break;
}
goto storec;
/*
* store characters until one that can't be part of a token
* comes along; check the current token against certain
* reserved words.
*/
default:
storec: if (!intoken(c)) {
if (sp == tok)
break;
*sp = EOS;
if (tflag) {
/* no typedefs inside typedefs */
if (!t_def &&
!memcmp(tok, "typedef",8)) {
t_def = YES;
t_level = level;
break;
}
/* catch "typedef struct" */
if ((!t_def || t_level < level)
&& (!memcmp(tok, "struct", 7)
|| !memcmp(tok, "union", 6)
|| !memcmp(tok, "enum", 5))) {
/*
* get line immediately;
* may change before '{'
*/
getline();
if (str_entry(c))
++level;
break;
/* } */
}
}
sp = tok;
}
else if (sp != tok || begtoken(c)) {
*sp++ = c;
token = YES;
}
continue;
}
sp = tok;
token = NO;
}
}
/*
* func_entry --
* handle a function reference
*/
static int
func_entry(void)
{
int c; /* current character */
int level = 0; /* for matching '()' */
/*
* Find the end of the assumed function declaration.
* Note that ANSI C functions can have type definitions so keep
* track of the parentheses nesting level.
*/
while (GETC(!=, EOF)) {
switch (c) {
case '\'':
case '"':
/* skip strings and character constants */
skip_string(c);
break;
case '/':
/* skip comments */
if (GETC(==, '*'))
skip_comment();
break;
case '(':
level++;
break;
case ')':
if (level == 0)
goto fnd;
level--;
break;
case '\n':
SETLINE;
}
}
return (NO);
fnd:
/*
* 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...
*/
for (;;) {
while (GETC(!=, EOF) && iswhite(c))
if (c == '\n')
SETLINE;
if (intoken(c) || c == '{')
break;
if (c == '/' && GETC(==, '*'))
skip_comment();
else { /* don't ever "read" '/' */
(void)ungetc(c, inf);
return (NO);
}
}
if (c != '{')
(void)skip_key('{');
return (YES);
}
/*
* hash_entry --
* handle a line starting with a '#'
*/
static void
hash_entry(void)
{
int c; /* character read */
int curline; /* line started on */
char *sp; /* buffer pointer */
static char tok[MAXTOKEN]; /* storage buffer */
curline = lineno;
for (sp = tok;;) { /* get next token */
if (GETC(==, EOF))
return;
if (iswhite(c))
break;
*sp++ = c;
}
*sp = EOS;
if (memcmp(tok, "define", 6)) /* only interested in #define's */
goto skip;
for (;;) { /* this doesn't handle "#define \n" */
if (GETC(==, EOF))
return;
if (!iswhite(c))
break;
}
for (sp = tok;;) { /* get next token */
*sp++ = c;
if (GETC(==, EOF))
return;
/*
* this is where it DOESN'T handle
* "#define \n"
*/
if (!intoken(c))
break;
}
*sp = EOS;
if (dflag || c == '(') { /* only want macros */
getline();
pfnote(tok, curline);
}
skip: if (c == '\n') { /* get rid of rest of define */
SETLINE
if (*(sp - 1) != '\\')
return;
}
(void)skip_key('\n');
}
/*
* str_entry --
* handle a struct, union or enum entry
*/
static int
str_entry(int c)
{
int curline; /* line started on */
char *sp; /* buffer pointer */
static char tok[LINE_MAX]; /* storage buffer */
curline = lineno;
while (iswhite(c))
if (GETC(==, EOF))
return (NO);
if (c == '{') /* it was "struct {" */
return (YES);
for (sp = tok;;) { /* get next token */
*sp++ = c;
if (GETC(==, EOF))
return (NO);
if (!intoken(c))
break;
}
switch (c) {
case '{': /* it was "struct foo{" */
--sp;
break;
case '\n': /* it was "struct foo\n" */
SETLINE;
/*FALLTHROUGH*/
default: /* probably "struct foo " */
while (GETC(!=, EOF))
if (!iswhite(c))
break;
if (c != '{') {
(void)ungetc(c, inf);
return (NO);
}
}
*sp = EOS;
pfnote(tok, curline);
return (YES);
}
/*
* skip_comment --
* skip over comment
*/
void
skip_comment(void)
{
int c; /* character read */
int star; /* '*' flag */
for (star = 0; GETC(!=, EOF);)
switch(c) {
/* comments don't nest, nor can they be escaped. */
case '*':
star = YES;
break;
case '/':
if (star)
return;
break;
case '\n':
SETLINE;
/*FALLTHROUGH*/
default:
star = NO;
break;
}
}
/*
* skip_string --
* skip to the end of a string or character constant.
*/
void
skip_string(int key)
{
int c,
skip;
for (skip = NO; GETC(!=, EOF); )
switch (c) {
case '\\': /* a backslash escapes anything */
skip = !skip; /* we toggle in case it's "\\" */
break;
case '\n':
SETLINE;
/*FALLTHROUGH*/
default:
if (c == key && !skip)
return;
skip = NO;
}
}
/*
* skip_key --
* skip to next char "key"
*/
int
skip_key(int key)
{
int c,
skip,
retval;
#ifdef __ORCAC203__
for (skip = NO, retval = NO; GETC(!=, EOF);)
#else
for (skip = retval = NO; GETC(!=, EOF);)
#endif
switch(c) {
case '\\': /* a backslash escapes anything */
skip = !skip; /* we toggle in case it's "\\" */
break;
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 */
case '\'':
case '"':
/* skip strings and character constants */
skip_string(c);
break;
case '/':
/* skip comments */
if (GETC(==, '*')) {
skip_comment();
break;
}
(void)ungetc(c, inf);
c = '/';
goto norm;
case '\n':
SETLINE;
/*FALLTHROUGH*/
default:
norm:
if (c == key && !skip)
return (retval);
skip = NO;
}
return (retval);
}

8
usr.bin/ctags/Makefile Normal file
View File

@ -0,0 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $Id: Makefile,v 1.1 1998/01/24 07:58:57 taubert Exp $
PROG= ctags
SRCS= ctags.c C.c fortran.c lisp.c print.c tree.c yacc.c
STACK= 2048
.INCLUDE: /src/gno/prog.mk

214
usr.bin/ctags/ctags.1 Normal file
View File

@ -0,0 +1,214 @@
.\" Copyright (c) 1987, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)ctags.1 8.1 (Berkeley) 6/6/93
.\"
.Dd June 6, 1993
.Dt CTAGS 1
.Os BSD 4
.Sh NAME
.Nm ctags
.Nd create a tags file
.Sh SYNOPSIS
.Nm ctags
.Op Fl BFadtuwvx
.Op Fl f Ar tagsfile
.Ar name ...
.Sh DESCRIPTION
.Nm Ctags
makes a tags file for
.Xr ex 1
from the specified C,
Pascal, Fortran,
.Tn YACC ,
lex, and lisp sources.
A tags file gives the locations of specified objects in a group of files.
Each line of the tags file contains the object name, the file in which it
is defined, and a search pattern for the object definition, separated by
white-space.
Using the
.Ar tags
file,
.Xr ex 1
can quickly locate these object definitions.
Depending upon the options provided to
.Nm ctags ,
objects will consist of subroutines, typedefs, defines, structs,
enums and unions.
.Bl -tag -width Ds
.It Fl B
use backward searching patterns
.Pq Li ?...? .
.It Fl F
use forward searching patterns
.Pq Li /.../
(the default).
.It Fl a
append to
.Ar tags
file.
.It Fl d
create tags for
.Li #defines
that don't take arguments;
.Li #defines
that take arguments are tagged automatically.
.It Fl f
Places the tag descriptions in a file called
.Ar tagsfile .
The default behaviour is to place them in a file called
.Ar tags .
.It Fl t
create tags for typedefs, structs, unions, and enums.
.It Fl u
update the specified files in the
.Ar tags
file, that is, all
references to them are deleted, and the new values are appended to the
file. (Beware: this option is implemented in a way which is rather
slow; it is usually faster to simply rebuild the
.Ar tags
file.)
.It Fl v
An index of the form expected by
.Xr vgrind 1
is produced on the standard output. This listing
contains the object name, file name, and page number (assuming 64
line pages). Since the output will be sorted into lexicographic order,
it may be desired to run the output through
.Xr sort 1 .
Sample use:
.Bd -literal -offset indent
ctags \-v files \&| sort \-f > index
vgrind \-x index
.Ed
.It Fl w
suppress warning diagnostics.
.It Fl x
.Nm ctags
produces a list of object
names, the line number and file name on which each is defined, as well
as the text of that line and prints this on the standard output. This
is a simple index which can be printed out as an off-line readable
function index.
.El
.Pp
Files whose names end in
.Nm \&.c
or
.Nm \&.h
are assumed to be C
source files and are searched for C style routine and macro definitions.
Files whose names end in
.Nm \&.y
are assumed to be
.Tn YACC
source files.
Files whose names end in
.Nm \&.l
are assumed to be lisp files if their
first non-blank character is `;', `(', or `[',
otherwise, they are
treated as lex files. Other files are first examined to see if they
contain any Pascal or Fortran routine definitions, and, if not, are
searched for C style definitions.
.Pp
The tag
.Li main
is treated specially in C programs. The tag formed
is created by prepending
.Ar M
to the name of the file, with the
trailing
.Nm \&.c
and any leading pathname components removed. This
makes use of
.Nm ctags
practical in directories with more than one
program.
.Pp
Yacc and lex files each have a special tag.
.Ar Yyparse
is the start
of the second section of the yacc file, and
.Ar yylex
is the start of
the second section of the lex file.
.Sh FILES
.Bl -tag -width tags -compact
.It Pa tags
default output tags file
.El
.Sh DIAGNOSTICS
.Nm Ctags
exits with a value of 1 if an error occurred, 0 otherwise.
Duplicate objects are not considered errors.
.Sh SEE ALSO
.Xr ex 1 ,
.Xr vi 1
.Sh BUGS
Recognition of
.Nm functions ,
.Nm subroutines
and
.Nm procedures
for
.Tn FORTRAN
and Pascal is done is a very simpleminded way. No attempt
is made to deal with block structure; if you have two Pascal procedures
in different blocks with the same name you lose.
.Nm Ctags
doesn't
understand about Pascal types.
.Pp
The method of deciding whether to look for C, Pascal or
.Tn FORTRAN
functions is a hack.
.Pp
.Nm Ctags
relies on the input being well formed, and any syntactical
errors will completely confuse it. It also finds some legal syntax
confusing; for example, since it doesn't understand
.Li #ifdef Ns 's
(incidentally, that's a feature, not a bug), any code with unbalanced
braces inside
.Li #ifdef Ns 's
will cause it to become somewhat disoriented.
In a similar fashion, multiple line changes within a definition will
cause it to enter the last line of the object, rather than the first, as
the searching pattern. The last line of multiple line
.Li typedef Ns 's
will similarly be noted.
.Sh HISTORY
The
.Nm
command appeared in
.Bx 3.0 .

282
usr.bin/ctags/ctags.c Normal file
View File

@ -0,0 +1,282 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1987, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)ctags.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ctags.h"
/*
* ctags: create a tags file
*/
NODE *head; /* head of the sorted binary tree */
/* boolean "func" (see init()) */
bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256];
FILE *inf; /* ioptr for current input file */
FILE *outf; /* ioptr for tags file */
long lineftell; /* ftell after getc( inf ) == '\n' */
int lineno; /* line number of current line */
int dflag; /* -d: non-macro defines */
int tflag; /* -t: create tags for typedefs */
int vflag; /* -v: vgrind style index output */
int wflag; /* -w: suppress warnings */
int xflag; /* -x: cxref style output */
char *curfile; /* current input file name */
char searchar = '/'; /* use /.../ searches by default */
char lbuf[LINE_MAX];
void init __P((void));
void find_entries __P((char *));
int
main(int argc, char **argv)
{
static char *outfile = "tags"; /* output file */
int aflag; /* -a: append to tags */
int uflag; /* -u: update tags */
int exit_val; /* exit value */
int step; /* step through args */
int ch; /* getopts char */
static char cmd[100]; /* too ugly to explain */
#ifdef __ORCAC203__
aflag = NO; uflag = NO;
#else
aflag = uflag = NO;
#endif
while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != EOF)
switch(ch) {
case 'B':
searchar = '?';
break;
case 'F':
searchar = '/';
break;
case 'a':
aflag++;
break;
case 'd':
dflag++;
break;
case 'f':
outfile = optarg;
break;
case 't':
tflag++;
break;
case 'u':
uflag++;
break;
case 'w':
wflag++;
break;
case 'v':
vflag++;
case 'x':
xflag++;
break;
case '?':
default:
goto usage;
}
argv += optind;
argc -= optind;
if (!argc) {
usage: (void)fprintf(stderr,
"usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n");
exit(1);
}
init();
#ifdef __ORCAC203__
for (exit_val = 0, step = 0; step < argc; ++step)
#else
for (exit_val = step = 0; step < argc; ++step)
#endif
if (!(inf = fopen(argv[step], "r"))) {
warn("%s", argv[step]);
exit_val = 1;
}
else {
curfile = argv[step];
find_entries(argv[step]);
(void)fclose(inf);
}
if (head)
if (xflag)
put_entries(head);
else {
if (uflag) {
for (step = 0; step < argc; step++) {
(void)sprintf(cmd,
"mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS",
outfile, argv[step],
outfile);
system(cmd);
}
++aflag;
}
if (!(outf = fopen(outfile, aflag ? "a" : "w")))
err(exit_val, "%s", outfile);
put_entries(head);
(void)fclose(outf);
if (uflag) {
(void)sprintf(cmd, "sort -o %s %s",
outfile, outfile);
system(cmd);
}
}
exit(exit_val);
}
/*
* init --
* this routine sets up the boolean psuedo-functions which work by
* setting boolean flags dependent upon the corresponding character.
* Every char which is NOT in that string is false with respect to
* the pseudo-function. Therefore, all of the array "_wht" is NO
* by default and then the elements subscripted by the chars in
* CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
* the string CWHITE, else NO.
*/
void
init(void)
{
int i;
unsigned char *sp;
for (i = 0; i < 256; i++) {
#ifdef __ORCAC203__
_wht[i] = NO; _etk[i] = NO; _itk[i] = NO; _btk[i] = NO;
#else
_wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
#endif
_gd[i] = YES;
}
#define CWHITE " \f\t\n"
for (sp = CWHITE; *sp; sp++) /* white space chars */
_wht[*sp] = YES;
#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
for (sp = CTOKEN; *sp; sp++) /* token ending chars */
_etk[*sp] = YES;
#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
for (sp = CINTOK; *sp; sp++) /* valid in-token chars */
_itk[*sp] = YES;
#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
for (sp = CBEGIN; *sp; sp++) /* token starting chars */
_btk[*sp] = YES;
#define CNOTGD ",;"
for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */
_gd[*sp] = NO;
}
/*
* find_entries --
* this routine opens the specified file and calls the function
* which searches the file.
*/
void
find_entries(char *file)
{
char *cp;
lineno = 0; /* should be 1 ?? KB */
if (cp = strrchr(file, '.')) {
if (cp[1] == 'l' && !cp[2]) {
int c;
for (;;) {
if (GETC(==, EOF))
return;
if (!iswhite(c)) {
rewind(inf);
break;
}
}
#define LISPCHR ";(["
/* lisp */ if (strchr(LISPCHR, c)) {
l_entries();
return;
}
/* lex */ else {
/*
* we search all 3 parts of a lex file
* for C references. This may be wrong.
*/
toss_yysec();
(void)strcpy(lbuf, "%%$");
pfnote("yylex", lineno);
rewind(inf);
}
}
/* yacc */ else if (cp[1] == 'y' && !cp[2]) {
/*
* we search only the 3rd part of a yacc file
* for C references. This may be wrong.
*/
toss_yysec();
(void)strcpy(lbuf, "%%$");
pfnote("yyparse", lineno);
y_entries();
}
/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
if (PF_funcs())
return;
rewind(inf);
}
}
/* C */ c_entries();
}

9
usr.bin/ctags/ctags.desc Normal file
View File

@ -0,0 +1,9 @@
Name: ctags
Version: 1.0 (October 1997)
Shell: GNO
Author: Derek Taubert (from FreeBSD 2.1.0 code)
Contact: taubert@geeks.org
Where: /usr/bin
FTP: ground.isca.uiowa.edu apple2.caltech.edu trenco.myrias.com
Generate tag file for Emacs, vi.

90
usr.bin/ctags/ctags.h Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ctags.h 8.3 (Berkeley) 4/2/94
*/
#define bool char
#define YES 1
#define NO 0
#define EOS '\0'
#define ENDLINE 50 /* max length of pattern */
#define MAXTOKEN 250 /* max size of single token */
#define SETLINE {++lineno;lineftell = ftell(inf);}
#define GETC(op,exp) ((c = getc(inf)) op (int)exp)
#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */
#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */
#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */
#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */
#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */
typedef struct nd_st { /* sorting structure */
struct nd_st *left,
*right; /* left and right sons */
char *entry, /* function or type name */
*file, /* file name */
*pat; /* search pattern */
int lno; /* for -x option */
bool been_warned; /* set if noticed dup */
} NODE;
extern char *curfile; /* current input file name */
extern NODE *head; /* head of the sorted binary tree */
extern FILE *inf; /* ioptr for current input file */
extern FILE *outf; /* ioptr for current output file */
extern long lineftell; /* ftell after getc( inf ) == '\n' */
extern int lineno; /* line number of current line */
extern int dflag; /* -d: non-macro defines */
extern int tflag; /* -t: create tags for typedefs */
extern int vflag; /* -v: vgrind style index output */
extern int wflag; /* -w: suppress warnings */
extern int xflag; /* -x: cxref style output */
extern bool _wht[], _etk[], _itk[], _btk[], _gd[];
extern char lbuf[LINE_MAX];
extern char *lbp;
extern char searchar; /* ex search character */
extern int cicmp __P((char *));
extern void getline __P((void));
extern void pfnote __P((char *, int));
extern int skip_key __P((int));
extern void put_entries __P((NODE *));
extern void toss_yysec __P((void));
extern void l_entries __P((void));
extern void y_entries __P((void));
extern int PF_funcs __P((void));
extern void c_entries __P((void));
extern void skip_comment __P((void));

31
usr.bin/ctags/ctags.rez Normal file
View File

@ -0,0 +1,31 @@
/*
* Resources for ctags version and comment
*
* $Id: ctags.rez,v 1.1 1998/01/24 07:59:02 taubert Exp $
*/
#define PROG "ctags"
#define DESC "Generate tag file for Emacs, vi."
#include "Types.rez"
/*
* Version
*/
resource rVersion (1, purgeable3) {
{ 1, 0, 0, /* Version 1.0.0 */
release, /* development|alpha|beta|final|release */
0 }, /* non-final release number */
verUS, /* Country */
PROG, /* Program name */
DESC " Released with GNO/ME."
};
/*
* Comment
*/
resource rComment (1, purgeable3) {
PROG " v1.0 (October 1997)\n"
"GNO utility: " DESC "\n"
"Ported from FreeBSD 2.1.0 code by Derek Taubert."
};

168
usr.bin/ctags/fortran.c Normal file
View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)fortran.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "ctags.h"
static void takeprec __P((void));
char *lbp; /* line buffer pointer */
int
PF_funcs(void)
{
bool pfcnt; /* pascal/fortran functions found */
char *cp;
static char tok[MAXTOKEN];
for (pfcnt = NO;;) {
lineftell = ftell(inf);
if (!fgets(lbuf, sizeof(lbuf), inf))
return (pfcnt);
++lineno;
lbp = lbuf;
if (*lbp == '%') /* Ratfor escape to fortran */
++lbp;
for (; isspace(*lbp); ++lbp)
continue;
if (!*lbp)
continue;
switch (*lbp | ' ') { /* convert to lower-case */
case 'c':
if (cicmp("complex") || cicmp("character"))
takeprec();
break;
case 'd':
if (cicmp("double")) {
for (; isspace(*lbp); ++lbp)
continue;
if (!*lbp)
continue;
if (cicmp("precision"))
break;
continue;
}
break;
case 'i':
if (cicmp("integer"))
takeprec();
break;
case 'l':
if (cicmp("logical"))
takeprec();
break;
case 'r':
if (cicmp("real"))
takeprec();
break;
}
for (; isspace(*lbp); ++lbp)
continue;
if (!*lbp)
continue;
switch (*lbp | ' ') {
case 'f':
if (cicmp("function"))
break;
continue;
case 'p':
if (cicmp("program") || cicmp("procedure"))
break;
continue;
case 's':
if (cicmp("subroutine"))
break;
default:
continue;
}
for (; isspace(*lbp); ++lbp)
continue;
if (!*lbp)
continue;
for (cp = lbp + 1; *cp && intoken(*cp); ++cp)
continue;
if (cp = lbp + 1)
continue;
*cp = EOS;
(void)strcpy(tok, lbp);
getline(); /* process line for ex(1) */
pfnote(tok, lineno);
pfcnt = YES;
}
/*NOTREACHED*/
}
/*
* cicmp --
* do case-independent strcmp
*/
int
cicmp(char *cp)
{
int len;
char *bp;
for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' ');
++cp, ++len)
continue;
if (!*cp) {
lbp += len;
return (YES);
}
return (NO);
}
static void
takeprec(void)
{
for (; isspace(*lbp); ++lbp)
continue;
if (*lbp == '*') {
for (++lbp; isspace(*lbp); ++lbp)
continue;
if (!isdigit(*lbp))
--lbp; /* force failure */
else
while (isdigit(*++lbp))
continue;
}
}

106
usr.bin/ctags/lisp.c Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)lisp.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "ctags.h"
/*
* lisp tag functions
* just look for (def or (DEF
*/
void
l_entries(void)
{
int special;
char *cp;
char savedc;
static char tok[MAXTOKEN];
for (;;) {
lineftell = ftell(inf);
if (!fgets(lbuf, sizeof(lbuf), inf))
return;
++lineno;
lbp = lbuf;
if (!cicmp("(def"))
continue;
special = NO;
switch(*lbp | ' ') {
case 'm':
if (cicmp("method"))
special = YES;
break;
case 'w':
if (cicmp("wrapper") || cicmp("whopper"))
special = YES;
}
for (; !isspace(*lbp); ++lbp)
continue;
for (; isspace(*lbp); ++lbp)
continue;
for (cp = lbp; *cp && *cp != '\n'; ++cp)
continue;
*cp = EOS;
if (special) {
if (!(cp = strchr(lbp, ')')))
continue;
for (; cp >= lbp && *cp != ':'; --cp)
continue;
if (cp < lbp)
continue;
lbp = cp;
for (; *cp && *cp != ')' && *cp != ' '; ++cp)
continue;
}
else
for (cp = lbp + 1;
*cp && *cp != '(' && *cp != ' '; ++cp)
continue;
savedc = *cp;
*cp = EOS;
(void)strcpy(tok, lbp);
*cp = savedc;
getline();
pfnote(tok, lineno);
}
/*NOTREACHED*/
}

124
usr.bin/ctags/print.c Normal file
View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)print.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __GNO__
#include <fcntl.h>
#endif
#include "ctags.h"
/*
* getline --
* get the line the token of interest occurred on,
* prepare it for printing.
*/
void
getline(void)
{
long saveftell;
int c;
int cnt;
char *cp;
saveftell = ftell(inf);
(void)fseek(inf, lineftell, L_SET);
if (xflag)
for (cp = lbuf; GETC(!=, '\n'); *cp++ = c)
continue;
/*
* do all processing here, so we don't step through the
* line more than once; means you don't call this routine
* unless you're sure you've got a keeper.
*/
else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) {
if (c == '\\') { /* backslashes */
if (cnt > ENDLINE - 2)
break;
*cp++ = '\\'; *cp++ = '\\';
++cnt;
}
#ifdef __GNO__
else if (c == '*' || c == '[' || c == ']' ||
c == '.' || c == '^' || c == '$' ||
c == (int)searchar) /* search character */
#else
else if (c == (int)searchar) /* search character */
#endif
{
if (cnt > ENDLINE - 2)
break;
*cp++ = '\\'; *cp++ = c;
++cnt;
}
else if (c == '\n') { /* end of keep */
*cp++ = '$'; /* can find whole line */
break;
}
else
*cp++ = c;
}
*cp = EOS;
(void)fseek(inf, saveftell, L_SET);
}
/*
* put_entries --
* write out the tags
*/
void
put_entries(NODE *node)
{
if (node->left)
put_entries(node->left);
if (vflag)
printf("%s %s %d\n",
node->entry, node->file, (node->lno + 63) / 64);
else if (xflag)
printf("%-16s%4d %-16s %s\n",
node->entry, node->lno, node->file, node->pat);
else
fprintf(outf, "%s\t%s\t%c^%s%c\n",
node->entry, node->file, searchar, node->pat, searchar);
if (node->right)
put_entries(node->right);
}

41
usr.bin/ctags/tags Normal file
View File

@ -0,0 +1,41 @@
CBEGIN ctags.c /^#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefg/
CINTOK ctags.c /^#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefg/
CNOTGD ctags.c /^#define CNOTGD ",;"$/
CTOKEN ctags.c /^#define CTOKEN " \\t\\n\\"'#()\[\]{}=-+%\*\/&|\^~!/
CWHITE ctags.c /^#define CWHITE " \\f\\t\\n"$/
ENDLINE ctags.h /^#define ENDLINE 50 \/\* max length of pattern \*/
EOS ctags.h /^#define EOS '\\0'$/
GETC ctags.h /^#define GETC(op,exp) ((c = getc(inf)) op (int)exp)/
LISPCHR ctags.c /^#define LISPCHR ";(\["$/
MAXTOKEN ctags.h /^#define MAXTOKEN 250 \/\* max size of single toke/
Mctags ctags.c /^main(int argc, char \*\*argv)$/
NO ctags.h /^#define NO 0$/
NODE ctags.h /^} NODE;$/
PF_funcs fortran.c /^PF_funcs(void)$/
SETLINE ctags.h /^#define SETLINE {++lineno;lineftell = ftell(inf);/
YES ctags.h /^#define YES 1$/
add_node tree.c /^add_node(NODE \*node, NODE \*cur_node)$/
begtoken ctags.h /^#define begtoken(arg) (_btk\[(unsigned)arg\]) \/\*/
bool ctags.h /^#define bool char$/
c_entries C.c /^c_entries(void)$/
cicmp fortran.c /^cicmp(char \*cp)$/
endtoken ctags.h /^#define endtoken(arg) (_etk\[(unsigned)arg\]) \/\*/
find_entries ctags.c /^find_entries(char \*file)$/
free_tree tree.c /^free_tree(NODE \*node)$/
func_entry C.c /^func_entry(void)$/
getline print.c /^getline(void)$/
hash_entry C.c /^hash_entry(void)$/
init ctags.c /^init(void)$/
intoken ctags.h /^#define intoken(arg) (_itk\[(unsigned)arg\]) \/\* /
isgood ctags.h /^#define isgood(arg) (_gd\[(unsigned)arg\]) \/\* T /
iswhite ctags.h /^#define iswhite(arg) (_wht\[(unsigned)arg\]) \/\* /
l_entries lisp.c /^l_entries(void)$/
pfnote tree.c /^pfnote(char \*name, int ln)$/
put_entries print.c /^put_entries(NODE \*node)$/
skip_comment C.c /^skip_comment(void)$/
skip_key C.c /^skip_key(int key)$/
skip_string C.c /^skip_string(int key)$/
str_entry C.c /^str_entry(int c)$/
takeprec fortran.c /^takeprec(void)$/
toss_yysec yacc.c /^toss_yysec(void)$/
y_entries yacc.c /^y_entries(void)$/

View File

@ -0,0 +1,67 @@
int bar = (1 + 5);
FOO("here is a #define test: ) {");
char sysent[20];
int nsysent = sizeof (sysent) / sizeof (sysent[0]);
/*
* now is the time for a comment.
* four lines in length...
*/struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe;
#define FOO BAR
struct struct_three {
int list;
};
#define SINGLE
int BAD();
enum color {red, green, gold, brown};
char qq[] = " quote(one,two) {int bar;} ";
typedef struct {
int bar;
struct struct_two {
int foo;
union union_3 {
struct struct_three entry;
char size[25];
};
struct last {
struct struct_three xentry;
char list[34];
};
};
} struct_one;
#define TWOLINE ((MAXLIST + FUTURE + 15) \
/ (time_to_live ? 3 : 4))
#if (defined(BAR))
int bar;
#endif
#define MULTIPLE {\
multiple(one,two); \
lineno++; \
callroute(one,two); \
}
#if defined(BAR)
int bar;
#endif
union union_one {
struct struct_three s3;
char foo[25];
};
#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno)
routine1(one,two) /* comments here are fun... */
struct {
int entry;
char bar[34];
} *one;
char two[10];
{
typedef unsigned char u_char;
register struct buf *bp;
five(one,two);
}
routine2 (one,two) { puts("hello\n"); }
routine3
(one,
two) { puts("world\n"); }
routine4(int one, char (*two)(void)) /* test ANSI arguments */
{
}

140
usr.bin/ctags/tree.c Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ctags.h"
static void add_node __P((NODE *, NODE *));
static void free_tree __P((NODE *));
/*
* pfnote --
* enter a new node in the tree
*/
void
pfnote(char *name, int ln)
{
NODE *np;
char *fp;
static char nbuf[MAXTOKEN];
/*NOSTRICT*/
if (!(np = (NODE *)malloc(sizeof(NODE)))) {
warnx("too many entries to sort");
put_entries(head);
free_tree(head);
/*NOSTRICT*/
#ifdef __ORCAC203__
np = (NODE *)malloc(sizeof(NODE));
if (!(head = np))
#else
if (!(head = np = (NODE *)malloc(sizeof(NODE))))
#endif
err(1, "out of space");
}
if (!xflag && !strcmp(name, "main")) {
if (!(fp = strrchr(curfile, '/')))
fp = curfile;
else
++fp;
(void)sprintf(nbuf, "M%s", fp);
fp = strrchr(nbuf, '.');
if (fp && !fp[2])
*fp = EOS;
name = nbuf;
}
if (!(np->entry = strdup(name)))
err(1, NULL);
np->file = curfile;
np->lno = ln;
#ifdef __ORCAC203__
np->left = 0; np->right = 0;
#else
np->left = np->right = 0;
#endif
if (!(np->pat = strdup(lbuf)))
err(1, NULL);
if (!head)
head = np;
else
add_node(np, head);
}
static void
add_node(NODE *node, NODE *cur_node)
{
int dif;
dif = strcmp(node->entry, cur_node->entry);
if (!dif) {
if (node->file == cur_node->file) {
if (!wflag)
fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry);
return;
}
if (!cur_node->been_warned)
if (!wflag)
fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry);
cur_node->been_warned = YES;
}
else if (dif < 0)
if (cur_node->left)
add_node(node, cur_node->left);
else
cur_node->left = node;
else if (cur_node->right)
add_node(node, cur_node->right);
else
cur_node->right = node;
}
static void
free_tree(NODE *node)
{
while (node) {
if (node->right)
free_tree(node->right);
free(node);
node = node->left;
}
}

152
usr.bin/ctags/yacc.c Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)yacc.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "ctags.h"
/*
* y_entries:
* find the yacc tags and put them in.
*/
void
y_entries(void)
{
int c;
char *sp;
bool in_rule;
static char tok[MAXTOKEN];
in_rule = NO;
while (GETC(!=, EOF))
switch (c) {
case '\n':
SETLINE;
/* FALLTHROUGH */
case ' ':
case '\f':
case '\r':
case '\t':
break;
case '{':
if (skip_key('}'))
in_rule = NO;
break;
case '\'':
case '"':
if (skip_key(c))
in_rule = NO;
break;
case '%':
if (GETC(==, '%'))
return;
(void)ungetc(c, inf);
break;
case '/':
if (GETC(==, '*'))
skip_comment();
else
(void)ungetc(c, inf);
break;
case '|':
case ';':
in_rule = NO;
break;
default:
if (in_rule || !isalpha(c) && c != '.' && c != '_')
break;
sp = tok;
*sp++ = c;
while (GETC(!=, EOF) && (intoken(c) || c == '.'))
*sp++ = c;
*sp = EOS;
getline(); /* may change before ':' */
while (iswhite(c)) {
if (c == '\n')
SETLINE;
if (GETC(==, EOF))
return;
}
if (c == ':') {
pfnote(tok, lineno);
in_rule = YES;
}
else
(void)ungetc(c, inf);
}
}
/*
* toss_yysec --
* throw away lines up to the next "\n%%\n"
*/
void
toss_yysec(void)
{
int c; /* read character */
int state;
/*
* state == 0 : waiting
* state == 1 : received a newline
* state == 2 : received first %
* state == 3 : recieved second %
*/
lineftell = ftell(inf);
for (state = 0; GETC(!=, EOF);)
switch (c) {
case '\n':
++lineno;
lineftell = ftell(inf);
if (state == 3) /* done! */
return;
state = 1; /* start over */
break;
case '%':
if (state) /* if 1 or 2 */
++state; /* goto 3 */
break;
default:
state = 0; /* reset */
break;
}
}