386BSD 0.0 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 12 Apr 1991 21:30:32 +0000 (13:30 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 12 Apr 1991 21:30:32 +0000 (13:30 -0800)
Work on file usr/src/usr.bin/ctags/C.c
Work on file usr/src/usr.bin/ctags/ctags.c
Work on file usr/src/usr.bin/ctags/fortran.c
Work on file usr/src/usr.bin/ctags/ctags.h
Work on file usr/src/usr.bin/ctags/print.c
Work on file usr/src/usr.bin/ctags/lisp.c
Work on file usr/src/usr.bin/ctags/tree.c
Work on file usr/src/usr.bin/ctags/yacc.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.0/src

usr/src/usr.bin/ctags/C.c [new file with mode: 0644]
usr/src/usr.bin/ctags/ctags.c [new file with mode: 0644]
usr/src/usr.bin/ctags/ctags.h [new file with mode: 0644]
usr/src/usr.bin/ctags/fortran.c [new file with mode: 0644]
usr/src/usr.bin/ctags/lisp.c [new file with mode: 0644]
usr/src/usr.bin/ctags/print.c [new file with mode: 0644]
usr/src/usr.bin/ctags/tree.c [new file with mode: 0644]
usr/src/usr.bin/ctags/yacc.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/ctags/C.c b/usr/src/usr.bin/ctags/C.c
new file mode 100644 (file)
index 0000000..8c1c936
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 1987 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        5.5 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "ctags.h"
+
+static int func_entry(), str_entry();
+static void hash_entry();
+
+/*
+ * c_entries --
+ *     read .c and .h files and call appropriate routines
+ */
+c_entries()
+{
+       extern int      tflag;          /* -t: create tags for typedefs */
+       register int    c,              /* current character */
+                       level;          /* brace level */
+       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 */
+
+       lineftell = ftell(inf);
+       sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
+       while (GETC(!=,EOF)) {
+
+       switch ((char)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 comments in their entirety */
+               case '"':
+               case '\'':
+                       (void)skip_key(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 && !bcmp(tok,"typedef",8)) {
+                                               t_def = YES;
+                                               t_level = level;
+                                               break;
+                                       }
+                                       /* catch "typedef struct" */
+                                       if ((!t_def || t_level < level)
+                                           && (!bcmp(tok,"struct",7)
+                                           || !bcmp(tok,"union",6)
+                                           || !bcmp(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
+func_entry()
+{
+       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)')');
+       for (;;) {
+               while (GETC(!=,EOF) && iswhite(c))
+                       if (c == (int)'\n')
+                               SETLINE;
+               if (intoken(c) || c == (int)'{')
+                       break;
+               if (c == (int)'/' && GETC(==,'*'))
+                       skip_comment();
+               else {                          /* don't ever "read" '/' */
+                       (void)ungetc(c,inf);
+                       return(NO);
+               }
+       }
+       if (c != (int)'{')
+               (void)skip_key((int)'{');
+       return(YES);
+}
+
+/*
+ * hash_entry --
+ *     handle a line starting with a '#'
+ */
+static void
+hash_entry()
+{
+       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 */
+
+       curline = lineno;
+       for (sp = tok;;) {              /* get next token */
+               if (GETC(==,EOF))
+                       return;
+               if (iswhite(c))
+                       break;
+               *sp++ = c;
+       }
+       *sp = EOS;
+       if (bcmp(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 == (int)'(') {   /* only want macros */
+               getline();
+               pfnote(tok,curline);
+       }
+skip:  if (c == (int)'\n') {           /* get rid of rest of define */
+               SETLINE
+               if (*(sp - 1) != '\\')
+                       return;
+       }
+       (void)skip_key((int)'\n');
+}
+
+/*
+ * str_entry --
+ *     handle a struct, union or enum entry
+ */
+static
+str_entry(c)
+       register int    c;              /* current character */
+{
+       register char   *sp;            /* buffer pointer */
+       int     curline;                /* line started on */
+       char    tok[BUFSIZ];            /* storage buffer */
+
+       curline = lineno;
+       while (iswhite(c))
+               if (GETC(==,EOF))
+                       return(NO);
+       if (c == (int)'{')              /* it was "struct {" */
+               return(YES);
+       for (sp = tok;;) {              /* get next token */
+               *sp++ = c;
+               if (GETC(==,EOF))
+                       return(NO);
+               if (!intoken(c))
+                       break;
+       }
+       switch ((char)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 != (int)'{') {
+                               (void)ungetc(c, inf);
+                               return(NO);
+                       }
+       }
+       *sp = EOS;
+       pfnote(tok,curline);
+       return(YES);
+}
+
+/*
+ * skip_comment --
+ *     skip over comment
+ */
+skip_comment()
+{
+       register int    c,              /* character read */
+                       star;           /* '*' flag */
+
+       for (star = 0;GETC(!=,EOF);)
+               switch((char)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;
+               }
+}
+
+/*
+ * skip_key --
+ *     skip to next char "key"
+ */
+skip_key(key)
+       register int    key;
+{
+       register int    c,
+                       skip,
+                       retval;
+
+       for (skip = retval = NO;GETC(!=,EOF);)
+               switch((char)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 '\n':
+                       SETLINE;
+                       /*FALLTHROUGH*/
+               default:
+                       if (c == key && !skip)
+                               return(retval);
+                       skip = NO;
+               }
+       return(retval);
+}
diff --git a/usr/src/usr.bin/ctags/ctags.c b/usr/src/usr.bin/ctags/ctags.c
new file mode 100644 (file)
index 0000000..d61dd60
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1987 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
+char copyright[] =
+"@(#) Copyright (c) 1987 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ctags.c    5.8 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "ctags.h"
+
+/*
+ * ctags: create a tags file
+ */
+
+NODE   *head;                  /* head of the sorted binary tree */
+
+                               /* boolean "func" (see init()) */
+bool   _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
+
+FILE   *inf,                   /* ioptr for current input file */
+       *outf;                  /* ioptr for tags file */
+
+long   lineftell;              /* ftell after getc( inf ) == '\n' */
+
+int    lineno,                 /* line number of current line */
+       dflag,                  /* -d: non-macro defines */
+       tflag,                  /* -t: create tags for typedefs */
+       wflag,                  /* -w: suppress warnings */
+       vflag,                  /* -v: vgrind style index output */
+       xflag;                  /* -x: cxref style output */
+
+char   *curfile,               /* current input file name */
+       searchar = '/',         /* use /.../ searches by default */
+       lbuf[BUFSIZ];
+
+main(argc,argv)
+       int     argc;
+       char    **argv;
+{
+       extern char     *optarg;                /* getopt arguments */
+       extern int      optind;
+       static char     *outfile = "tags";      /* output file */
+       int     aflag,                          /* -a: append to tags */
+               uflag,                          /* -u: update tags */
+               exit_val,                       /* exit value */
+               step,                           /* step through args */
+               ch;                             /* getopts char */
+       char    cmd[100];                       /* too ugly to explain */
+
+       aflag = uflag = NO;
+       while ((ch = getopt(argc,argv,"BFadf:tuwvx")) != EOF)
+               switch((char)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:         puts("Usage: ctags [-BFadtuwvx] [-f tagsfile] file ...");
+               exit(1);
+       }
+
+       init();
+
+       for (exit_val = step = 0;step < argc;++step)
+               if (!(inf = fopen(argv[step],"r"))) {
+                       perror(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"))) {
+                               perror(outfile);
+                               exit(exit_val);
+                       }
+                       put_entries(head);
+                       (void)fclose(outf);
+                       if (uflag) {
+                               (void)sprintf(cmd,"sort %s -o %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.
+ */
+init()
+{
+       register int    i;
+       register char   *sp;
+
+       for (i = 0; i < 0177; i++) {
+               _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
+               _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.
+ */
+find_entries(file)
+       char    *file;
+{
+       register char   *cp;
+
+       lineno = 0;                             /* should be 1 ?? KB */
+       if (cp = rindex(file, '.')) {
+               if (cp[1] == 'l' && !cp[2]) {
+                       register int    c;
+
+                       for (;;) {
+                               if (GETC(==,EOF))
+                                       return;
+                               if (!iswhite(c)) {
+                                       rewind(inf);
+                                       break;
+                               }
+                       }
+#define        LISPCHR ";(["
+/* lisp */             if (index(LISPCHR,(char)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();
+}
diff --git a/usr/src/usr.bin/ctags/ctags.h b/usr/src/usr.bin/ctags/ctags.h
new file mode 100644 (file)
index 0000000..c1a7173
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1987 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     5.4 (Berkeley) 2/26/91
+ */
+
+#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[arg])     /* T if char is white */
+#define        begtoken(arg)   (_btk[arg])     /* T if char can start token */
+#define        intoken(arg)    (_itk[arg])     /* T if char can be in token */
+#define        endtoken(arg)   (_etk[arg])     /* T if char ends tokens */
+#define        isgood(arg)     (_gd[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 FILE    *inf;                   /* ioptr for current input file */
+extern long    lineftell;              /* ftell after getc( inf ) == '\n' */
+extern int     lineno,                 /* line number of current line */
+               xflag;                  /* -x: cxref style output */
+extern bool    _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
+extern char    lbuf[BUFSIZ];
diff --git a/usr/src/usr.bin/ctags/fortran.c b/usr/src/usr.bin/ctags/fortran.c
new file mode 100644 (file)
index 0000000..025a204
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1987 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  5.5 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "ctags.h"
+
+static void takeprec();
+
+char *lbp;                             /* line buffer pointer */
+
+PF_funcs()
+{
+       register bool   pfcnt;          /* pascal/fortran functions found */
+       register char   *cp;
+       char    tok[MAXTOKEN],
+               *gettoken();
+
+       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);
+               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);
+                               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);
+               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);
+               if (!*lbp)
+                       continue;
+               for (cp = lbp + 1;*cp && intoken(*cp);++cp);
+               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
+ */
+cicmp(cp)
+       register char   *cp;
+{
+       register int    len;
+       register char   *bp;
+
+       for (len = 0,bp = lbp;*cp && (*cp &~ ' ') == (*bp++ &~ ' ');
+           ++cp,++len);
+       if (!*cp) {
+               lbp += len;
+               return(YES);
+       }
+       return(NO);
+}
+
+static void
+takeprec()
+{
+       for (;isspace(*lbp);++lbp);
+       if (*lbp == '*') {
+               for (++lbp;isspace(*lbp);++lbp);
+               if (!isdigit(*lbp))
+                       --lbp;                  /* force failure */
+               else
+                       while (isdigit(*++lbp));
+       }
+}
diff --git a/usr/src/usr.bin/ctags/lisp.c b/usr/src/usr.bin/ctags/lisp.c
new file mode 100644 (file)
index 0000000..652313d
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1987 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     5.5 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "ctags.h"
+
+extern char    *lbp;                   /* pointer shared with fortran */
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+l_entries()
+{
+       register int    special;
+       register char   *cp,
+                       savedc;
+       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);
+               for (;isspace(*lbp);++lbp);
+               for (cp = lbp;*cp && *cp != '\n';++cp);
+               *cp = EOS;
+               if (special) {
+                       if (!(cp = index(lbp,')')))
+                               continue;
+                       for (;cp >= lbp && *cp != ':';--cp);
+                       if (cp < lbp)
+                               continue;
+                       lbp = cp;
+                       for (;*cp && *cp != ')' && *cp != ' ';++cp);
+               }
+               else
+                       for (cp = lbp + 1;
+                           *cp && *cp != '(' && *cp != ' ';++cp);
+               savedc = *cp;
+               *cp = EOS;
+               (void)strcpy(tok,lbp);
+               *cp = savedc;
+               getline();
+               pfnote(tok,lineno);
+       }
+       /*NOTREACHED*/
+}
diff --git a/usr/src/usr.bin/ctags/print.c b/usr/src/usr.bin/ctags/print.c
new file mode 100644 (file)
index 0000000..f39c283
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1987 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    5.4 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ctags.h"
+
+extern char    searchar;               /* ex search character */
+
+/*
+ * getline --
+ *     get the line the token of interest occurred on,
+ *     prepare it for printing.
+ */
+getline()
+{
+       register long   saveftell;
+       register int    c,
+                       cnt;
+       register char   *cp;
+
+       saveftell = ftell(inf);
+       (void)fseek(inf,lineftell,L_SET);
+       if (xflag)
+               for (cp = lbuf;GETC(!=,'\n');*cp++ = c);
+       /*
+        * 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 == (int)'\\') {           /* backslashes */
+                       if (cnt > ENDLINE - 2)
+                               break;
+                       *cp++ = '\\'; *cp++ = '\\';
+                       ++cnt;
+               }
+               else if (c == (int)searchar) {  /* search character */
+                       if (cnt > ENDLINE - 2)
+                               break;
+                       *cp++ = '\\'; *cp++ = c;
+                       ++cnt;
+               }
+               else if (c == (int)'\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
+ */
+put_entries(node)
+       register NODE   *node;
+{
+       extern FILE     *outf;          /* ioptr for tags file */
+       extern int      vflag;          /* -v: vgrind style output */
+
+       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);
+}
diff --git a/usr/src/usr.bin/ctags/tree.c b/usr/src/usr.bin/ctags/tree.c
new file mode 100644 (file)
index 0000000..da326ef
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1987 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     5.5 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ctags.h"
+
+/*
+ * pfnote --
+ *     enter a new node in the tree
+ */
+pfnote(name,ln)
+       char    *name;
+       int     ln;
+{
+       extern NODE     *head;          /* head of the sorted binary tree */
+       extern char     *curfile;       /* current input file name */
+       register NODE   *np;
+       register char   *fp;
+       char    nbuf[MAXTOKEN];
+
+       /*NOSTRICT*/
+       if (!(np = (NODE *)malloc(sizeof(NODE)))) {
+               fputs("ctags: too many entries to sort\n",stderr);
+               put_entries(head);
+               free_tree(head);
+               /*NOSTRICT*/
+               if (!(head = np = (NODE *)malloc(sizeof(NODE)))) {
+                       fputs("ctags: out of space.\n",stderr);
+                       exit(1);
+               }
+       }
+       if (!xflag && !strcmp(name,"main")) {
+               if (!(fp = rindex(curfile,'/')))
+                       fp = curfile;
+               else
+                       ++fp;
+               (void)sprintf(nbuf,"M%s",fp);
+               fp = rindex(nbuf,'.');
+               if (fp && !fp[2])
+                       *fp = EOS;
+               name = nbuf;
+       }
+       if (!(np->entry = strdup(name))) {
+               (void)fprintf(stderr, "ctags: %s\n", strerror(errno));
+               exit(1);
+       }
+       np->file = curfile;
+       np->lno = ln;
+       np->left = np->right = 0;
+       if (!(np->pat = strdup(lbuf))) {
+               (void)fprintf(stderr, "ctags: %s\n", strerror(errno));
+               exit(1);
+       }
+       if (!head)
+               head = np;
+       else
+               add_node(np,head);
+}
+
+add_node(node,cur_node)
+       register NODE   *node,
+                       *cur_node;
+{
+       extern int      wflag;                  /* -w: suppress warnings */
+       register 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;
+}
+
+free_tree(node)
+       register NODE   *node;
+{
+       while (node) {
+               if (node->right)
+                       free_tree(node->right);
+               cfree(node);
+               node = node->left;
+       }
+}
diff --git a/usr/src/usr.bin/ctags/yacc.c b/usr/src/usr.bin/ctags/yacc.c
new file mode 100644 (file)
index 0000000..f073f2b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1987 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     5.6 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "ctags.h"
+
+/*
+ * y_entries:
+ *     find the yacc tags and put them in.
+ */
+y_entries()
+{
+       register int    c;
+       register char   *sp;
+       register bool   in_rule;
+       char    tok[MAXTOKEN];
+
+       while (GETC(!=,EOF))
+               switch ((char)c) {
+               case '\n':
+                       SETLINE;
+                       /* FALLTHROUGH */
+               case ' ':
+               case '\f':
+               case '\r':
+               case '\t':
+                       break;
+               case '{':
+                       if (skip_key((int)'}'))
+                               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 != (int)'.'
+                           && c != (int)'_')
+                               break;
+                       sp = tok;
+                       *sp++ = c;
+                       while (GETC(!=,EOF) && (intoken(c) || c == (int)'.'))
+                               *sp++ = c;
+                       *sp = EOS;
+                       getline();              /* may change before ':' */
+                       while (iswhite(c)) {
+                               if (c == (int)'\n')
+                                       SETLINE;
+                               if (GETC(==,EOF))
+                                       return;
+                       }
+                       if (c == (int)':') {
+                               pfnote(tok,lineno);
+                               in_rule = YES;
+                       }
+                       else
+                               (void)ungetc(c,inf);
+               }
+}
+
+/*
+ * toss_yysec --
+ *     throw away lines up to the next "\n%%\n"
+ */
+toss_yysec()
+{
+       register int    c,                      /* read character */
+                       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 ((char)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 */
+               }
+}