* etags.c (stab_entry, stab_create, stab_find, stab_search,
[bpt/emacs.git] / lib-src / etags.c
index 95e2358..5f8825f 100644 (file)
@@ -1,21 +1,21 @@
 /* Tags file maker to go with GNU Emacs
    Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
 
-This file is part of GNU Emacs.
+This file is not considered part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GNU Emacs is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * Authors:
@@ -24,25 +24,29 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  *     Ed Pelegri-Llopart added C typedefs.
  *     Gnu Emacs TAGS format and modifications by RMS?
  *     Sam Kendall added C++.
+ *
+ *     Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 10.6
  */
 
+#ifdef MSDOS
+#include <fcntl.h>
+#endif /* MSDOS */
+
+#ifdef HAVE_CONFIG_H
+#include <../src/config.h>
+#endif
+
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include "getopt.h"
-
-#ifdef __GNUC__
-#define        alloca  __builtin_alloca
-#else
-#ifdef sparc
-#include <alloca.h>
-#else
-extern char *alloca ();
-#endif
+#if !defined (S_ISREG) && defined (S_IFREG)
+# define S_ISREG(m)    (((m) & S_IFMT) == S_IFREG)
 #endif
 
+#include "getopt.h"
+
 extern char *malloc (), *realloc ();
 extern char *getenv ();
 extern char *strcpy (), *strncpy ();
@@ -142,7 +146,7 @@ struct nd_st
   char *name;                  /* function or type name        */
   char *file;                  /* file name                    */
   logical is_func;             /* use pattern or line no       */
-  logical rewritten;           /* list name separately         */
+  logical named;               /* list name separately         */
   logical been_warned;         /* set if noticed dup           */
   int lno;                     /* line number tag is on        */
   long cno;                    /* character number line starts on */
@@ -163,7 +167,7 @@ char *savenstr ();
 char *savestr ();
 char *xmalloc ();
 char *xrealloc ();
-int L_isdef ();
+int L_isdef (), L_isquote ();
 int PF_funcs ();
 int total_size_of_entries ();
 logical consider_token ();
@@ -179,10 +183,9 @@ void TEX_funcs ();
 void add_node ();
 void error ();
 void fatal ();
-void find_entries ();
+logical find_entries ();
 void free_tree ();
 void getit ();
-void getline ();
 void init ();
 void initbuffer ();
 void initbuffer ();
@@ -199,127 +202,14 @@ void takeprec ();
  *     Type *xnew (int n, Type);
  */
 #define xnew(n, Type)  ((Type *) xmalloc ((n) * sizeof (Type)))
-\f
-
 
 /*
- *     Symbol table stuff.
- *
- * Should probably be implemented with hash table; linked list for now.
+ *     Symbol table types.
  */
-
 enum sym_type
 {
   st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
 };
-
-struct stab_entry
-{
-  char *sym;
-  int symlen;
-  enum sym_type type;
-  struct stab_entry *next;
-};
-
-typedef struct stab_entry Stab_entry;
-typedef Stab_entry *Stab;
-
-/*
- * NAME
- *     Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
- *
- * SYNOPSIS
- *     Types: Stab, Stab_entry, enum sym_type
- *
- *     Stab * stab_create ()
- *
- *     Stab_entry * stab_find (stab, sym)
- *     Stab *stab;
- *     char *sym;
- *
- *     Stab_entry * stab_search (stab, sym)
- *     Stab *stab;
- *     char *sym;
- *
- * DESCRIPTION
- *     stab_create creates a Stab, a symbol table object, and returns a
- *     pointer to it.  stab_find finds a symbol in a Stab; it returns a
- *     pointer to the Stab_entry if found, otherwise NULL.  stab_search
- *     is like stab_find, except that it creates a new Stab_entry,
- *     initialized with type = st_none, if one did not exist already
- *     (it never returns NULL).
- *
- *     A Stab_entry is a structure that contains at least the following
- *     members:
- *
- *             char *name;             // must not be modified
- *             enum sym_type type;     // should be set
- *
- *     The type field is initially set to st_none; it should be set to
- *     something else by the caller of stab_search.  Other possible values
- *     of an enum sym_type can be added.
- */
-
-Stab *
-stab_create ()
-{
-  Stab *sp;
-  sp = xnew (1, Stab);
-  *sp = NULL;                  /* a Stab starts out as a null Stab_entry* */
-  return sp;
-}
-
-Stab_entry *
-stab_find (stab, sym, symlen)
-     Stab *stab;
-     register char *sym;
-     register int symlen;
-{
-  register Stab_entry *se;
-  for (se = *stab; se != NULL; se = se->next)
-    {
-      if (se->symlen == symlen && strneq (se->sym, sym, symlen))
-       return se;
-    }
-
-  return NULL;
-}
-
-Stab_entry *
-stab_search (stab, sym, symlen)
-     register Stab *stab;
-     char *sym;
-     int symlen;
-{
-  register Stab_entry *se;
-  se = stab_find (stab, sym, symlen);
-
-  if (se == NULL)
-    {
-      /* make a new one */
-      se = xnew (1, Stab_entry);
-      se->sym = savenstr (sym, symlen);
-      se->symlen = symlen;
-      se->type = st_none;
-      se->next = *stab;
-      *stab = se;
-    }
-
-  return se;
-}
-
-/*
- * NAME
- *     stab_type -- type of a symbol table entry
- *
- * SYNOPSIS
- *     enum sym_type stab_type (Stab_entry *se);
- *
- * WARNING
- *     May evaluate its argument more than once.
- */
-
-#define stab_type(se)  ((se)==NULL ? st_none : (se)->type)
 \f
 
 
@@ -330,7 +220,7 @@ typedef struct
   char *p;
   int len;
   LINENO lineno;
-  logical rewritten;
+  logical named;
 } TOKEN;
 
 /* C extensions.
@@ -353,7 +243,7 @@ char *curfile,                      /* current input file name              */
  *white = " \f\t\n",           /* white chars                          */
  *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars   */
                                /* token starting chars                 */
- *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
+ *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
                                  /* valid in-token chars               */
  *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
 
@@ -436,7 +326,7 @@ print_version ()
 #ifdef ETAGS
   printf ("ETAGS ");
 #endif
-  printf ("for Emacs version 19.0.\n");
+  printf ("for Emacs version 19.\n");
 
   exit (0);
 }
@@ -447,14 +337,13 @@ print_help ()
   printf ("These are the options accepted by %s.  You may use unambiguous\n\
 abbreviations for the long option names.\n\n", progname);
 
-  fputs ("\
--a, --append\n\
-        Append tag entries to existing tags file.\n\
--C, --c++\n\
+  puts ("-a, --append\n\
+        Append tag entries to existing tags file.");
+  puts ("-C, --c++\n\
         Treat files with `.c' and `.h' extensions as C++ code, not C\n\
         code.  Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
-        extensions are always assumed to be C++ code.\n\
--d, --defines\n\
+        extensions are always assumed to be C++ code.");
+  fputs ("-d, --defines\n\
         Create tag entries for #defines, too.", stdout);
 
 #ifdef ETAGS
@@ -478,11 +367,11 @@ abbreviations for the long option names.\n\n", progname);
         Don't rely on indentation quite as much as normal.  Currently,\n\
         this means not to assume that a closing brace in the first\n\
         column is the final brace of a function or structure\n\
-        definition.\n\
--t, --typedefs\n\
+        definition.");
+  puts ("-t, --typedefs\n\
         Generate tag entries for typedefs.  This is the default\n\
-        behavior.\n\
--T, --typedefs-and-c++\n\
+        behavior.");
+  puts ("-T, --typedefs-and-c++\n\
         Generate tag entries for typedefs, struct/enum/union tags, and\n\
         C++ member functions.");
 
@@ -496,27 +385,27 @@ abbreviations for the long option names.\n\n", progname);
 #ifdef CTAGS
   puts ("-B, --backward-search\n\
         Write the search commands for the tag entries using '?', the\n\
-        backward-search command.\n\
--F, --forward-search\n\
+        backward-search command.");
+  puts ("-F, --forward-search\n\
         Write the search commands for the tag entries using '/', the\n\
-        forward-search command.\n\
--u, --update\n\
+        forward-search command.");
+  puts ("-u, --update\n\
         Update the tag entries for the given files, leaving tag\n\
         entries for other files in place.  Currently, this is\n\
         implemented by deleting the existing entries for the given\n\
         files and then rewriting the new entries at the end of the\n\
         tags file.  It is often faster to simply rebuild the entire\n\
-        tag file than to use this.\n\
--v, --vgrind\n\
+        tag file than to use this.");
+  puts ("-v, --vgrind\n\
         Generates an index of items intended for human consumption,\n\
         similar to the output of vgrind.  The index is sorted, and\n\
-        gives the page number of each item.\n\
--x, --cxref\n\
+        gives the page number of each item.");
+  puts ("-x, --cxref\n\
         Like --vgrind, but in the style of cxref, rather than vgrind.\n\
         The output uses line numbers instead of page numbers, but\n\
         beyond that the differences are cosmetic; try both to see\n\
-        which you like.\n\
--w, --no-warn\n\
+        which you like.");
+  puts ("-w, --no-warn\n\
         Suppress warning messages about entries defined in multiple\n\
         files.");
 #endif
@@ -538,7 +427,7 @@ main (argc, argv)
   char cmd[100];
   int i;
   unsigned int nincluded_files = 0;
-  char **included_files = (char **) alloca (argc * sizeof (char *));
+  char **included_files = xnew (argc, char *);
   char *this_file;
 #ifdef VMS
   char got_err;
@@ -547,6 +436,10 @@ main (argc, argv)
   extern char *massage_name ();
 #endif
 
+#ifdef MSDOS
+  _fmode = O_BINARY;   /* all of files are treated as binary files */
+#endif /* MSDOS */
+
   progname = argv[0];
 
 #ifndef CTAGS
@@ -565,7 +458,7 @@ main (argc, argv)
   for (;;)
     {
       int opt;
-      opt = getopt_long (argc, argv, "aCdDo:StTi:BFuvxwVH", longopts, 0);
+      opt = getopt_long (argc, argv, "aCdDo:f:StTi:BFuvxwVH", longopts, 0);
 
       if (opt == EOF)
        break;
@@ -590,11 +483,12 @@ main (argc, argv)
        case 'D':
          constantypedefs = 0;
          break;
+       case 'f':
        case 'o':
          if (outfile)
            {
              fprintf (stderr,
-                      "%s: -o flag may only be given once\n", progname);
+                      "%s: -%c flag may only be given once\n", progname, opt);
              goto usage;
            }
          outfile = optarg;
@@ -658,12 +552,12 @@ main (argc, argv)
        }
     }
 
-  if (optind == argc)
+  if (optind == argc && nincluded_files == 0)
     {
       fprintf (stderr, "%s: No input files specified.\n", progname);
 
     usage:
-      fprintf (stderr, "%s: Try '%s --help' for a complete list of options.\n",
+      fprintf (stderr, "%s: Try `%s --help' for a complete list of options.\n",
               progname, progname);
       exit (BAD);
     }
@@ -716,11 +610,8 @@ main (argc, argv)
   for (; optind < argc; optind++)
     {
       this_file = argv[optind];
-      if (1)
-       {
 #endif
-         /* Input file named "-" means read file names from stdin
-            and use them.  */
+      /* Input file named "-" means read file names from stdin and use them. */
          if (streq (this_file, "-"))
            {
              while (!feof (stdin))
@@ -733,7 +624,6 @@ main (argc, argv)
          else
            process_file (this_file);
        }
-    }
 
   if (emacs_tags_format)
     {
@@ -788,35 +678,23 @@ process_file (file)
 {
   struct stat stat_buf;
 
-  stat (file, &stat_buf);
-  if (!(stat_buf.st_mode & S_IFREG)
-#ifdef S_IFLNK
-      || !(stat_buf.st_mode & S_IFLNK)
-#endif
-      )
+  if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
     {
       fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
       return;
     }
-
   if (streq (file, outfile) && !streq (outfile, "-"))
     {
       fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
       return;
     }
-  if (emacs_tags_format)
+  if (!find_entries (file))
     {
-      char *cp = etags_rindex (file, '/');
-      if (cp)
-       ++cp;
-      else
-       cp = file;
+      return;
     }
-  find_entries (file);
   if (emacs_tags_format)
     {
-      fprintf (outf, "\f\n%s,%d\n",
-              file, total_size_of_entries (head));
+      fprintf (outf, "\f\n%s,%d\n", file, total_size_of_entries (head));
       put_entries (head);
       free_tree (head);
       head = NULL;
@@ -824,7 +702,7 @@ process_file (file)
 }
 
 /*
- * This routine sets up the boolean psuedo-functions which work
+ * This routine sets up the boolean pseudo-functions which work
  * by setting boolean flags dependent upon the corresponding character
  * Every char which is NOT in that string is not a white char.  Therefore,
  * all of the array "_wht" is set to FALSE, and then the elements
@@ -857,7 +735,7 @@ init ()
  * This routine opens the specified file and calls the function
  * which finds the function and type definitions.
  */
-void
+logical
 find_entries (file)
      char *file;
 {
@@ -868,7 +746,7 @@ find_entries (file)
   if (inf == NULL)
     {
       perror (file);
-      return;
+      return FALSE;
     }
   curfile = savestr (file);
   cp = etags_rindex (file, '.');
@@ -908,8 +786,7 @@ find_entries (file)
                 && string_numeric_p (cp + 1))))
     {
       Scheme_funcs (inf);
-      fclose (inf);
-      return;
+      goto close_and_return;
     }
   /* Assume that ".s" or ".a" is assembly code. -wolfgang.
      Or even ".sa". */
@@ -918,8 +795,7 @@ find_entries (file)
             || streq (cp + 1, "sa")))
     {
       Asm_funcs (inf);
-      fclose (inf);
-      return;
+      goto close_and_return;
     }
   /* .C or .H or .cxx or .hxx or .cc: a C++ file */
   if (cp && (streq (cp + 1, "C")
@@ -961,7 +837,7 @@ find_entries (file)
   if (cp && (streq (cp + 1, "f")
             || streq (cp + 1, "for")))
     {
-      PF_funcs (inf);
+      (void) PF_funcs (inf);
       goto close_and_return;
     }
   /* if not a .c or .h or .y file, try fortran */
@@ -978,6 +854,7 @@ find_entries (file)
 
 close_and_return:
   (void) fclose (inf);
+  return TRUE;
 }
 
 /* Nonzero if string STR is composed of digits.  */
@@ -997,10 +874,10 @@ string_numeric_p (str)
 /* Record a tag. */
 /* Should take a TOKEN* instead!! */
 void
-pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
+pfnote (name, is_func, named, linestart, linelen, lno, cno)
      char *name;               /* tag name */
      logical is_func;          /* function or type name? */
-     logical rewritten;                /* tag different from text of definition? */
+     logical named;            /* tag different from text of definition? */
      char *linestart;
      int linelen;
      int lno;
@@ -1035,12 +912,12 @@ pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
       fp = etags_rindex (name, '.');
       if (fp && fp[1] != '\0' && fp[2] == '\0')
        *fp = 0;
-      rewritten = TRUE;
+      named = TRUE;
     }
   np->name = savestr (name);
   np->file = curfile;
   np->is_func = is_func;
-  np->rewritten = rewritten;
+  np->named = named;
   np->lno = lno;
   /* UNCOMMENT THE +1 HERE: */
   np->cno = cno /* + 1 */ ;    /* our char numbers are 0-base; emacs's are 1-base */
@@ -1092,13 +969,16 @@ free_tree (node)
  *     add_node is the only function allowed to add nodes, so it can
  *     maintain state.
  */
+/* Must avoid static vars within functions since some systems
+   #define static as nothing.  */
+static NODE *last_node = NULL;
+
 void
 add_node (node, cur_node_p)
      NODE *node, **cur_node_p;
 {
   register int dif;
   register NODE *cur_node = *cur_node_p;
-  static NODE *last_node = NULL;/* careful */
 
   if (cur_node == NULL)
     {
@@ -1175,15 +1055,17 @@ put_entries (node)
 
   if (emacs_tags_format)
     {
-      if (node->rewritten)
+      if (node->named)
        {
          fprintf (outf, "%s\177%s\001%d,%d\n",
-                  node->name, node->pat, node->lno, node->cno);
+                  node->pat, node->name,
+                  node->lno, node->cno);
        }
       else
        {
          fprintf (outf, "%s\177%d,%d\n",
-                  node->pat, node->lno, node->cno);
+                  node->pat,
+                  node->lno, node->cno);
        }
     }
   else if (!cxref_style)
@@ -1258,7 +1140,7 @@ total_size_of_entries (node)
       /* Count this entry */
       total += strlen (node->pat) + 1;
       total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
-      if (node->rewritten)
+      if (node->named)
        total += 1 + strlen (node->name);       /* \001name */
     }
 
@@ -1269,77 +1151,162 @@ total_size_of_entries (node)
  * The C symbol tables.
  */
 
-Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;
-
+/* Feed stuff between (but not including) %[ and %] lines to:
+      gperf -c -k1,3 -o -p -r -t
+%[
+struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
+%%
+class,         C_PLPL, st_C_struct
+domain,        C_STAR, st_C_struct
+union,         0,      st_C_struct
+struct,        0,      st_C_struct
+enum,          0,      st_C_enum
+typedef,       0,      st_C_typedef
+define,        0,      st_C_define
+long,          0,      st_C_typespec
+short,         0,      st_C_typespec
+int,           0,      st_C_typespec
+char,          0,      st_C_typespec
+float,         0,      st_C_typespec
+double,        0,      st_C_typespec
+signed,        0,      st_C_typespec
+unsigned,      0,      st_C_typespec
+auto,          0,      st_C_typespec
+void,          0,      st_C_typespec
+extern,        0,      st_C_typespec
+static,        0,      st_C_typespec
+const,         0,      st_C_typespec
+volatile,      0,      st_C_typespec
+%]
+and replace lines between %< and %> with its output. */
+/*%<*/
+/* C code produced by gperf version 1.8.1 (K&R C version) */
+/* Command-line: gperf -c -k1,3 -o -p -r -t  */
+
+
+struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
+
+#define MIN_WORD_LENGTH 3
+#define MAX_WORD_LENGTH 8
+#define MIN_HASH_VALUE 10
+#define MAX_HASH_VALUE 62
 /*
- * SYNOPSIS
- *     Stab *get_C_stab (int c_ext);
- */
-#define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab :            \
-                          (c_ext & C_PLPL) ? C_PLPL_stab :             \
-                          C_stab)
+   21 keywords
+   53 is the maximum key range
+*/
+
+static int
+hash (str, len)
+     register char  *str;
+     register int  len;
+{
+  static unsigned char hash_table[] =
+    {
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+     62, 62, 62, 62, 62, 62, 62,  2, 62,  7,
+      6,  9, 15, 30, 62, 24, 62, 62,  1, 24,
+      7, 27, 13, 62, 19, 26, 18, 27,  1, 62,
+     62, 62, 62, 62, 62, 62, 62, 62,
+  };
+  return len + hash_table[str[2]] + hash_table[str[0]];
+}
 
-void
-add_keyword (stab, sym, type)
-     Stab *stab;
-     char *sym;
-     enum sym_type type;
-{
-  stab_search (stab, sym, strlen (sym))->type = type;
+struct C_stab_entry *
+in_word_set  (str, len)
+     register char *str;
+     register int len;
+{
+
+  static struct C_stab_entry  wordlist[] =
+    {
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"",}, 
+      {"volatile",     0,      st_C_typespec},
+      {"",}, 
+      {"long",         0,      st_C_typespec},
+      {"char",         0,      st_C_typespec},
+      {"class",        C_PLPL, st_C_struct},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"const",        0,      st_C_typespec},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"auto",         0,      st_C_typespec},
+      {"",}, {"",}, 
+      {"define",       0,      st_C_define},
+      {"",}, 
+      {"void",         0,      st_C_typespec},
+      {"",}, {"",}, {"",}, 
+      {"extern",       0,      st_C_typespec},
+      {"static",       0,      st_C_typespec},
+      {"",}, 
+      {"domain",       C_STAR, st_C_struct},
+      {"",}, 
+      {"typedef",      0,      st_C_typedef},
+      {"double",       0,      st_C_typespec},
+      {"enum",         0,      st_C_enum},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"int",          0,      st_C_typespec},
+      {"",}, 
+      {"float",        0,      st_C_typespec},
+      {"",}, {"",}, {"",}, 
+      {"struct",       0,      st_C_struct},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"union",        0,      st_C_struct},
+      {"",}, 
+      {"short",        0,      st_C_typespec},
+      {"",}, {"",}, 
+      {"unsigned",     0,      st_C_typespec},
+      {"signed",       0,      st_C_typespec},
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
+        {
+          register char *s = wordlist[key].name;
+
+          if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
+            return &wordlist[key];
+        }
+    }
+  return 0;
 }
+/*%>*/
 
-Stab *
-C_create_stab (c_ext)
+enum sym_type
+C_symtype(str, len, c_ext)
+     char *str;
+     int len;
      int c_ext;
 {
-  Stab *stab;
-
-  stab = stab_create ();
-
-  /* C, C++ and C* */
-  if (c_ext & C_PLPL)
-    add_keyword (stab, "class", st_C_struct);
-  if (c_ext & C_STAR)
-    add_keyword (stab, "domain", st_C_struct);
-  add_keyword (stab, "union", st_C_struct);
-  add_keyword (stab, "struct", st_C_struct);
-  add_keyword (stab, "enum", st_C_enum);
-  add_keyword (stab, "typedef", st_C_typedef);
-  add_keyword (stab, "define", st_C_define);
-  add_keyword (stab, "long", st_C_typespec);
-  add_keyword (stab, "short", st_C_typespec);
-  add_keyword (stab, "int", st_C_typespec);
-  add_keyword (stab, "char", st_C_typespec);
-  add_keyword (stab, "float", st_C_typespec);
-  add_keyword (stab, "double", st_C_typespec);
-  add_keyword (stab, "signed", st_C_typespec);
-  add_keyword (stab, "unsigned", st_C_typespec);
-  add_keyword (stab, "auto", st_C_typespec);
-  add_keyword (stab, "void", st_C_typespec);
-  add_keyword (stab, "extern", st_C_typespec);
-  add_keyword (stab, "static", st_C_typespec);
-  add_keyword (stab, "const", st_C_typespec);
-  add_keyword (stab, "volatile", st_C_typespec);
-
-  return stab;
-}
+  register struct C_stab_entry *se = in_word_set(str, len);
 
-void
-C_create_stabs ()
-{
-  C_stab = C_create_stab (0);
-  C_PLPL_stab = C_create_stab (C_PLPL);
-  C_STAR_stab = C_create_stab (C_STAR | C_PLPL);
+  if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
+    return st_none;
+  return se->type;
 }
 \f
  /*
-  *    etags.c 4.2 1993/03/22 12:13:40 pot Exp
   * C functions are recognized using a simple finite automaton.
   * funcdef is its state variable.
   */
 typedef enum
 {
-  fnone, ftagseen, finlist, flistseen
+  fnone,                       /* nothing seen */
+  ftagseen,                    /* function-like tag seen */
+  fstartlist,                  /* just after open parenthesis */
+  finlist,                     /* in parameter list */
+  flistseen,                   /* after parameter list */
+  fignore                      /* before open brace */
 } FUNCST;
 FUNCST funcdef;
 
@@ -1349,7 +1316,10 @@ FUNCST funcdef;
   */
 typedef enum
 {
-  tnone, ttypedseen, tinbody, tend
+  tnone,                       /* nothing seen */
+  ttypedseen,                  /* typedef keyword seen */
+  tinbody,                     /* inside typedef body */
+  tend                         /* just before typedef tag */
 } TYPEDST;
 TYPEDST typdef;
 
@@ -1366,15 +1336,16 @@ typedef enum
   skeyseen,                    /* struct-like keyword seen */
   stagseen,                    /* struct-like tag seen */
   scolonseen,                  /* colon seen after struct-like tag */
-  sinbody                      /* in class body: recognize member func defs */
+  sinbody                      /* in struct body: recognize member func defs*/
 } STRUCTST;
 STRUCTST structdef;
 /*
  * When structdef is stagseen, scolonseen, or sinbody, structtag is the
- * struct tag, and structkey is the preceding struct-like keyword.
+ * struct tag, and structtype is the type of the preceding struct-like  
+ * keyword.
  */
 char structtag[BUFSIZ];
-Stab_entry *structkey;
+enum sym_type structtype;
 
 /*
  * Yet another little state machine to deal with preprocessor lines.
@@ -1406,14 +1377,6 @@ logical yacc_rules;
  *     to the list.
  */
 
-/*
- * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
- * Currently typdef and structdef stuff (typedefs and struct
- * definitions) are only noticed when level==0, but that may change.
- */
-#define LEVEL_OK_FOR_FUNCDEF()                                 \
-       (level==0 || (cplpl && level==1 && structdef==sinbody))
-
 #define curlb (lbs[curndx].lb)
 #define othlb (lbs[1-curndx].lb)
 #define newlb (lbs[newndx].lb)
@@ -1421,6 +1384,15 @@ logical yacc_rules;
 #define othlinepos (lbs[1-curndx].linepos)
 #define newlinepos (lbs[newndx].linepos)
 
+/* Save and restore token state.  This is used when preprocessor defines
+   are handled, to avoid disturbing active function/typedef/struct states.  */
+#define TOKEN_SAVED_P  (savetok.lineno > 0)
+#define SAVE_TOKEN     (savetok = tok, savetok.p = (char *) tokoff,    \
+                        savetok.len = toklen, strcpy(savenameb, nameb))
+#define RESTORE_TOKEN  (tok = savetok, tokoff = (int) tok.p,           \
+                        toklen = tok.len, strcpy(nameb, savenameb),    \
+                        savetok.lineno = 0)
+
 #define CNL_SAVE_DEFINEDEF                                             \
 do {                                                                   \
   SET_FILEPOS (curlinepos, inf, charno);                               \
@@ -1434,12 +1406,14 @@ do {                                                                    \
 #define CNL                                                            \
 do {                                                                   \
   CNL_SAVE_DEFINEDEF;                                                  \
+  if (TOKEN_SAVED_P)                                                   \
+    RESTORE_TOKEN;                                                     \
   definedef = dnone;                                                   \
 } while (FALSE)
 
-#define MAKE_TAG_FROM_NEW_LB(isfun)  pfnote (tokb, isfun, tok.rewritten, \
+#define MAKE_TAG_FROM_NEW_LB(isfun)  pfnote (nameb, isfun, tok.named,  \
   newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
-#define MAKE_TAG_FROM_OTH_LB(isfun)  pfnote (tokb, isfun, tok.rewritten, \
+#define MAKE_TAG_FROM_OTH_LB(isfun)  pfnote (nameb, isfun, tok.named,  \
   othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
 
 void
@@ -1450,13 +1424,17 @@ C_entries (c_ext)
   register char *lp;           /* pointer one beyond the character `c' */
   int curndx, newndx;          /* indices for current and new lb */
   TOKEN tok;                   /* latest token read for funcdef & structdef */
-  char tokb[BUFSIZ];           /* latest token name for funcdef & structdef */
+  char nameb[BUFSIZ];          /* latest token name for funcdef & structdef */
   register int tokoff;         /* offset in line of start of latest token */
   register int toklen;         /* length of latest token */
-  int level;                   /* current curly brace level */
+  int cblev;                   /* current curly brace level */
+  int parlev;                  /* current parenthesis level */
   logical incomm, inquote, inchar, quotednl, midtoken;
   logical cplpl;
+  TOKEN savetok;               /* saved token during preprocessor handling */
+  char savenameb[BUFSIZ];      /* ouch! */
 
+  savetok.lineno = 0;
   curndx = newndx = 0;
   lineno = 0;
   charno = 0;
@@ -1466,11 +1444,10 @@ C_entries (c_ext)
   definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
   next_token_is_func = yacc_rules = FALSE;
   midtoken = inquote = inchar = incomm = quotednl = FALSE;
-  level = 0;
+  cblev = 0;
+  parlev = 0;
   cplpl = c_ext & C_PLPL;
 
-  C_create_stabs ();
-
   while (!feof (inf))
     {
       c = *lp++;
@@ -1514,7 +1491,7 @@ C_entries (c_ext)
              inquote = FALSE;
              break;
            case '\0':
-             /* Newlines inside strings, do not end macro definitions
+             /* Newlines inside strings do not end macro definitions
                 in traditional cpp, even though compilers don't
                 usually accept them. */
              CNL_SAVE_DEFINEDEF;
@@ -1524,8 +1501,16 @@ C_entries (c_ext)
        }
       else if (inchar)
        {
-         if (c == '\'')
+         switch (c)
+           {
+           case '\0':
+             /* Hmmm, something went wrong. */
+             CNL;
+             /* FALLTHRU */
+           case '\'':
            inchar = FALSE;
+             break;
+           }
          continue;
        }
       else 
@@ -1533,9 +1518,13 @@ C_entries (c_ext)
          {
          case '"':
            inquote = TRUE;
+           if (funcdef != finlist && funcdef != fignore)
+             funcdef = fnone;
            continue;
          case '\'':
            inchar = TRUE;
+           if (funcdef != finlist && funcdef != fignore)
+             funcdef = fnone;
            continue;
          case '/':
            if (*lp == '*')
@@ -1549,7 +1538,8 @@ C_entries (c_ext)
                c = 0;
                break;
              }
-           continue;
+           else
+             break;
          case '%':
            if ((c_ext & YACC) && *lp == '%')
              {
@@ -1559,10 +1549,12 @@ C_entries (c_ext)
                typdef= tnone; structdef= snone;
                next_token_is_func = FALSE;
                midtoken = inquote = inchar = incomm = quotednl = FALSE;
-               level = 0;
+               cblev = 0;
                yacc_rules = !yacc_rules;
                continue;
-             }
+             }
+           else
+             break;
          case '#':
            if (lp == newlb.buffer + 1 && definedef == dnone)
              definedef = dsharpseen;
@@ -1570,16 +1562,18 @@ C_entries (c_ext)
          } /* switch (c) */
 
 
-      if (LEVEL_OK_FOR_FUNCDEF ()
+      /* Consider token only if some complicated conditions are satisfied. */
+      if (((cblev == 0 && structdef != scolonseen)
+          || (cblev == 1 && cplpl && structdef == sinbody))
          && definedef != dignorerest
-         && structdef != scolonseen
-         && funcdef != finlist)
+         && (funcdef != finlist
+             || (definedef != dnone && definedef != dignorerest)))
        {
          if (midtoken)
            {
              if (endtoken (c))
                {
-                 if (cplpl && c == ':' && *lp == ':' && intoken (*(lp + 1)))
+                 if (cplpl && c == ':' && *lp == ':' && begtoken(*(lp + 1)))
                    {
                      /*
                       * This handles :: in the middle, but not at beginning
@@ -1590,31 +1584,39 @@ C_entries (c_ext)
                    }
                  else
                    {
-                     logical is_func;
+                     logical is_func = FALSE;
 
                      tok.lineno = lineno;
                      tok.p = newlb.buffer + tokoff;
                      tok.len = toklen;
-                     tok.rewritten = FALSE;
+                     tok.named = FALSE;
                      if (yacc_rules
-                         || consider_token (c, lp, &tok,
-                                            c_ext, level, &is_func))
+                         || consider_token (c, &tok, c_ext, cblev, &is_func))
                        {
                          if (structdef == sinbody
-                             && definedef == dnone && is_func)
-                           {   /* function defined in C++ class body */
-                             sprintf (tokb, "%s::%.*s",
+                             && definedef == dnone
+                             && is_func)
+                           /* function defined in C++ class body */
+                           {
+                             tok.named = TRUE;
+                             sprintf (nameb, "%s::%.*s",
                                       ((structtag[0] == '\0')
                                        ? "_anonymous_" : structtag),
                                       tok.len, tok.p);
-                             tok.rewritten = TRUE;
                            }
                          else
                            {
-                             sprintf (tokb, "%.*s", tok.len, tok.p);
+                             sprintf (nameb, "%.*s", tok.len, tok.p);
                            }
 
-                         if (funcdef == ftagseen || structdef == stagseen)
+                         if (structdef == stagseen
+                             || typdef == tend)
+                           tok.named = TRUE;
+
+                         if (definedef == dnone
+                             && (funcdef == ftagseen
+                                 || structdef == stagseen
+                                 || typdef == tend))
                            {
                              if (newndx == curndx)
                                curndx = 1 - curndx; /* switch line buffers */
@@ -1633,17 +1635,40 @@ C_entries (c_ext)
            } /* if (midtoken) */
          else if (begtoken (c))
            {
-             switch (funcdef)
+             switch (definedef)
                {
-               case flistseen:
-                 MAKE_TAG_FROM_OTH_LB (TRUE);
-                 /* FALLTHRU */
-               case ftagseen:
-                 funcdef = fnone;
+               case dnone:
+                 switch (funcdef)
+                   {
+                   case fstartlist:
+                     funcdef = finlist;
+                     continue;
+                   case flistseen:
+                     MAKE_TAG_FROM_OTH_LB (TRUE);
+                     funcdef = fignore;
+                     break;
+                   case ftagseen:
+                     funcdef = fnone;
+                     break;
+                   }
+                 if (structdef == stagseen)
+                   structdef = snone;
                  break;
+               case dsharpseen:
+                 /* Take a quick peek ahead for define directive,
+                    so we can avoid saving the token when not absolutely
+                    necessary. [This is a speed hack.] */
+                 if (c == 'd' && strneq(lp, "efine", 5)
+                     && iswhite(*(lp + 5)))
+                   {
+                     SAVE_TOKEN;
+                     definedef = ddefineseen;
+                     lp += 6;
+                   }
+                 else
+                   definedef = dignorerest;
+                 continue;
                }
-             if (structdef == stagseen)
-               structdef = snone;
              if (!yacc_rules || lp == newlb.buffer + 1)
                {
                  tokoff = lp - 1 - newlb.buffer;
@@ -1656,50 +1681,83 @@ C_entries (c_ext)
 
 
       /* Detect end of line, colon, comma, semicolon and various braces
-        after having handled the last token on the line.*/
+        after having handled a token.*/
       switch (c)
        {
        case ':':
+         if (definedef != dnone)
+           break;
          if (structdef == stagseen)
            structdef = scolonseen;
-         else if (yacc_rules && funcdef == ftagseen)
+         else
+           switch (funcdef)
+             {
+             case ftagseen:
+               if (yacc_rules)
+                 {
+                   MAKE_TAG_FROM_OTH_LB (FALSE);
+                   funcdef = fignore;
+                 }
+               break;
+             case fstartlist:
+               funcdef = fnone;
+               break;
+             }
+         break;
+       case ';':
+         if (definedef != dnone)
+           break;
+         if (cblev == 0 && typdef == tend)
            {
+             typdef = tnone;
              MAKE_TAG_FROM_OTH_LB (FALSE);
-             funcdef == fnone;
            }
-         break;
-       case ';':
-         funcdef = fnone;
+         if (funcdef != fignore)
+           funcdef = fnone;
          /* FALLTHRU */
        case ',':
-         if (funcdef != finlist)
-           funcdef = fnone;
-         if (level == 0 && typdef == tend)
-           typdef = tnone;
          /* FALLTHRU */
        case '[':
-         if (funcdef != finlist)
+         if (definedef != dnone)
+           break;
+         if (funcdef != finlist && funcdef != fignore)
            funcdef = fnone;
          if (structdef == stagseen)
            structdef = snone;
          break;
        case '(':
+         if (definedef != dnone)
+           break;
          switch (funcdef)
            {
            case ftagseen:
-             funcdef = finlist;
+             funcdef = fstartlist;
              break;
-           case finlist:
            case flistseen:
-             funcdef = fnone;
+             funcdef = finlist;
              break;
            }
+         parlev++;
          break;
        case ')':
-         if (funcdef == finlist)
-           funcdef = flistseen;
+         if (definedef != dnone)
+           break;
+         if (--parlev == 0)
+           {
+             switch (funcdef)
+               {
+               case fstartlist:
+               case finlist:
+                 funcdef = flistseen;
+                 break;
+               }
+           }
+         else if (parlev < 0)  /* can happen due to ill-conceived #if's. */
+           parlev = 0;
          break;
        case '{':
+         if (definedef != dnone)
+           break;
          if (typdef == ttypedseen)
            typdef = tinbody;
          switch (structdef)
@@ -1714,21 +1772,33 @@ C_entries (c_ext)
              MAKE_TAG_FROM_OTH_LB (FALSE);
              break;
            }
-         level++;
-         /* FALLTHRU */
-       case '*':
-         if (funcdef == flistseen)
+         switch (funcdef)
            {
+           case flistseen:
              MAKE_TAG_FROM_OTH_LB (TRUE);
+             /* FALLTHRU */
+           case fignore:
              funcdef = fnone;
            }
+         cblev++;
+         break;
+       case '*':
+         if (definedef != dnone)
+           break;
+         if (funcdef == fstartlist)
+           funcdef = fnone;    /* avoid tagging `foo' in `foo (*bar()) ()' */
          break;
        case '}':
+         if (definedef != dnone)
+           break;
          if (!noindentypedefs && lp == newlb.buffer + 1)
-           level = 0;  /* reset level if first column */
-         else if (level > 0)
-           level--;
-         if (level == 0)
+           {
+             cblev = 0;        /* reset curly brace level if first column */
+             parlev = 0;       /* also reset paren level, just in case... */
+           }
+         else if (cblev > 0)
+           cblev--;
+         if (cblev == 0)
            {
              if (typdef == tinbody)
                typdef = tend;
@@ -1736,6 +1806,15 @@ C_entries (c_ext)
              (void) strcpy (structtag, "<error 2>");
            }
          break;
+       case '=':
+       case '#': case '+': case '-': case '~': case '&': case '%': case '/':
+       case '|': case '^': case '!': case '<': case '>': case '.': case '?':
+         if (definedef != dnone)
+           break;
+         /* These surely cannot follow a function tag. */
+         if (funcdef != finlist && funcdef != fignore)
+           funcdef = fnone;
+         break;
        case '\0':
          /* If a macro spans multiple lines don't reset its state. */
          if (quotednl)
@@ -1771,19 +1850,14 @@ C_entries (c_ext)
  */
 
 logical
-consider_token (c, lp, tokp, c_ext, level, is_func)
+consider_token (c, tokp, c_ext, cblev, is_func)
      register char c;          /* IN: first char after the token */
-     register char *lp;                /* IN: lp points to 2nd char after the token */
-     register TOKEN *tokp;     /* IN */
-     int c_ext;                        /* IN */
-     int level;                        /* IN */
+     register TOKEN *tokp;     /* IN: token pointer */
+     int c_ext;                        /* IN: C extensions mask */
+     int cblev;                        /* IN: curly brace level */
      logical *is_func;         /* OUT */
 {
-  logical firsttok;            /* TRUE if have seen first token in ()'s */
-  Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
-  enum sym_type toktype = stab_type (tokse);
-
-  *is_func = FALSE;            /* not a function */
+  enum sym_type toktype = C_symtype(tokp->p, tokp->len, c_ext);
 
   /*
    * Advance the definedef state machine.
@@ -1857,9 +1931,10 @@ consider_token (c, lp, tokp, c_ext, level, is_func)
     }
 
   /*
-   * This structdef business is currently only invoked when level==0.
-   * It should be recursively invoked whatever the level, and a stack of
-   * states kept, to allow for definitions of structs within structs.
+   * This structdef business is currently only invoked when cblev==0.
+   * It should be recursively invoked whatever the curly brace level,
+   * and a stack of states kept, to allow for definitions of structs
+   * within structs.
    *
    * This structdef business is NOT invoked when we are ctags and the
    * file is plain C.  This is because a struct tag may have the same
@@ -1875,16 +1950,16 @@ consider_token (c, lp, tokp, c_ext, level, is_func)
     case st_C_struct:
     case st_C_enum:
       if (typdef == ttypedseen
-         || (typedefs_and_cplusplus && level == 0 && structdef == snone))
+         || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
        {
          structdef = skeyseen;
-         structkey = tokse;
+         structtype = toktype;
        }
       return (FALSE);
     }
   if (structdef == skeyseen)
     {
-      if (stab_type (structkey) == st_C_struct)
+      if (structtype == st_C_struct)
        {
          (void) strncpy (structtag, tokp->p, tokp->len);
          structtag[tokp->len] = '\0';  /* for struct/union/class */
@@ -1924,6 +1999,8 @@ consider_token (c, lp, tokp, c_ext, level, is_func)
   if (next_token_is_func)
     {
       next_token_is_func = FALSE;
+      funcdef = fnone;
+      *is_func = TRUE;         /* to force search string in ctags */
       return (TRUE);
     }
 
@@ -1931,13 +2008,18 @@ consider_token (c, lp, tokp, c_ext, level, is_func)
   switch (toktype)
     {
     case st_C_typespec:
-      funcdef == fnone;                /* should be useless */
+      funcdef = fnone;         /* should be useless */
       return (FALSE);
     default:
-      funcdef = ftagseen;
-      *is_func = TRUE;
-      return (TRUE);
+      if (funcdef == fnone)
+       {
+         funcdef = ftagseen;
+         *is_func = TRUE;
+         return (TRUE);
+       }
     }
+
+  return (FALSE);
 }
 \f
 /* Fortran parsing */
@@ -2004,24 +2086,24 @@ PF_funcs (fi)
        {
        case 'f':
          if (tail ("function"))
-           getit ();
+           getit (fi);
          continue;
        case 's':
          if (tail ("subroutine"))
-           getit ();
+           getit (fi);
          continue;
        case 'e':
          if (tail ("entry"))
-           getit ();
+           getit (fi);
          continue;
        case 'p':
          if (tail ("program"))
            {
-             getit ();
+             getit (fi);
              continue;
            }
          if (tail ("procedure"))
-           getit ();
+           getit (fi);
          continue;
        }
     }
@@ -2034,14 +2116,14 @@ tail (cp)
 {
   register int len = 0;
 
-  while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))
+  while (*cp && (*cp | ' ') == (dbp[len] | ' '))
     cp++, len++;
   if (*cp == 0)
     {
       dbp += len;
-      return (1);
+      return (TRUE);
     }
-  return (0);
+  return (FALSE);
 }
 
 void
@@ -2065,7 +2147,8 @@ takeprec ()
 }
 
 void
-getit ()
+getit (fi)
+     FILE *fi;
 {
   register char *cp;
   char c;
@@ -2073,19 +2156,33 @@ getit ()
 
   while (isspace (*dbp))
     dbp++;
-  if (*dbp == 0
-      || (!isalpha (*dbp)
+  if (*dbp == '\0')
+    {
+      lineno++;
+      linecharno = charno;
+      charno += readline (&lb, fi);
+      dbp = lb.buffer;
+      if (dbp[5] != '&')
+       return;
+      dbp += 6;
+      while (isspace (*dbp))
+       dbp++;
+    }
+  if (!isalpha (*dbp)
          && *dbp != '_'
-         && *dbp != '$'))
+      && *dbp != '$')
     return;
-  for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
-                            || (*cp == '_') || (*cp == '$')); cp++)
+  for (cp = dbp + 1;
+       (*cp
+       && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
+       cp++)
     continue;
-  c = cp[0];
-  cp[0] = 0;
+  c = *cp;
+  *cp = '\0';
   (void) strcpy (nambuf, dbp);
-  cp[0] = c;
-  pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+  *cp = c;
+  pfnote (nambuf, TRUE, FALSE, lb.buffer,
+         cp - lb.buffer + 1, lineno, linecharno);
   pfcnt++;
 }
 
@@ -2113,7 +2210,7 @@ Asm_funcs (fi)
        ;
 
       if ((i > 0) && (c == ':'))
-       getit ();
+       getit (fi);
     }
 }
 \f
@@ -2346,15 +2443,17 @@ L_funcs (fi)
          else
            {
              /* Check for (foo::defmumble name-defined ... */
-             while (*dbp && *dbp != ':' && !isspace (*dbp)
-                    && *dbp != '(' && *dbp != ')')
+             do
                dbp++;
+             while (*dbp && !isspace (*dbp)
+                    && *dbp != ':' && *dbp != '(' && *dbp != ')');
              if (*dbp == ':')
                {
-                 while (*dbp == ':')
+                 do
                    dbp++;
+                 while (*dbp == ':');
 
-                 if (L_isdef (dbp))
+                 if (L_isdef (dbp - 1))
                    {
                      while (!isspace (*dbp))
                        dbp++;
@@ -2370,11 +2469,23 @@ L_funcs (fi)
 
 int
 L_isdef (dbp)
-     char *dbp;
+     register char *dbp;
 {
-  return ((dbp[1] == 'D' || dbp[1] == 'd') &&
-         (dbp[2] == 'E' || dbp[2] == 'e') &&
-         (dbp[3] == 'F' || dbp[3] == 'f'));
+  return ((dbp[1] == 'd' || dbp[1] == 'D')
+         && (dbp[2] == 'e' || dbp[2] == 'E')
+         && (dbp[3] == 'f' || dbp[3] == 'F'));
+}
+
+int
+L_isquote (dbp)
+     register char *dbp;
+{
+  return ((*(++dbp) == 'q' || *dbp == 'Q')
+         && (*(++dbp) == 'u' || *dbp == 'U')
+         && (*(++dbp) == 'o' || *dbp == 'O')
+         && (*(++dbp) == 't' || *dbp == 'T')
+         && (*(++dbp) == 'e' || *dbp == 'E')
+         && isspace(*(++dbp)));
 }
 
 void
@@ -2384,15 +2495,25 @@ L_getit ()
   char c;
   char nambuf[BUFSIZ];
 
-  if (*dbp == 0)
-    return;
-  for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
+  if (*dbp == '\'')            /* Skip prefix quote */
+    dbp++;
+  else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
+  {
+    dbp += 7;
+    while (isspace(*dbp))
+      dbp++;
+  }
+  for (cp = dbp /*+1*/; *cp && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
     continue;
+  if (cp == dbp)
+    return;
+  
   c = cp[0];
   cp[0] = 0;
   (void) strcpy (nambuf, dbp);
   cp[0] = c;
-  pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+  pfnote (nambuf, TRUE, FALSE, lb.buffer,
+         cp - lb.buffer + 1, lineno, linecharno);
   pfcnt++;
 }
 \f
@@ -2737,7 +2858,7 @@ prolog_getit (s, lineno, linecharno)
   *s = '\0';
   strcpy (nambuf, save_s);
   *s = tmpc;
-  pfnote (nambuf, TRUE, save_s, strlen (nambuf), lineno, linecharno);
+  pfnote (nambuf, TRUE, FALSE, save_s, strlen (nambuf), lineno, linecharno);
 }
 
 /* It is assumed that prolog predicate starts from column 0. */
@@ -2835,7 +2956,7 @@ readline (linebuffer, stream)
   register char *pend;
   int newline;                 /* 1 if ended with newline, 0 if ended with EOF */
 
-  pend = p + linebuffer->size; /* Separate to avoind 386/IX compiler bug.  */
+  pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug.  */
 
   while (1)
     {
@@ -2848,10 +2969,10 @@ readline (linebuffer, stream)
          pend = buffer + linebuffer->size;
          linebuffer->buffer = buffer;
        }
-      if (c < 0 || c == '\n')
+      if (c == EOF || c == '\n')
        {
          *p = 0;
-         newline = (c == '\n' ? 1 : 0);
+         newline = (c == '\n') ? 1 : 0;
          break;
        }
       *p++ = c;
@@ -2966,7 +3087,7 @@ concat (s1, s2, s3)
 
 char *
 xmalloc (size)
-     int size;
+     unsigned int size;
 {
   char *result = malloc (size);
   if (!result)
@@ -2977,7 +3098,7 @@ xmalloc (size)
 char *
 xrealloc (ptr, size)
      char *ptr;
-     int size;
+     unsigned int size;
 {
   char *result = realloc (ptr, size);
   if (!result)