Convert function definitions to standard C.
[bpt/emacs.git] / lib-src / etags.c
index 0edc281..79475fe 100644 (file)
@@ -29,15 +29,15 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 Copyright (C) 1984, 1987, 1988, 1989, 1993, 1994, 1995, 1998, 1999,
-  2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+  2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
 
-This program 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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -45,9 +45,7 @@ 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 this program; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 /* NB To comply with the above BSD license, copyright information is
@@ -61,14 +59,14 @@ University of California, as described above. */
 
 /*
  * Authors:
- * 1983        Ctags originally by Ken Arnold.
- * 1984        Fortran added by Jim Kleckner.
- * 1984        Ed Pelegri-Llopart added C typedefs.
- * 1985        Emacs TAGS format by Richard Stallman.
- * 1989        Sam Kendall added C++.
+ * 1983 Ctags originally by Ken Arnold.
+ * 1984 Fortran added by Jim Kleckner.
+ * 1984 Ed Pelegri-Llopart added C typedefs.
+ * 1985 Emacs TAGS format by Richard Stallman.
+ * 1989 Sam Kendall added C++.
  * 1992 Joseph B. Wells improved C and C++ parsing.
- * 1993        Francesco Potortì reorganised C and C++.
- * 1994        Line-by-line regexp tags by Tom Tromey.
+ * 1993 Francesco Potortì reorganized C and C++.
+ * 1994 Line-by-line regexp tags by Tom Tromey.
  * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
  * 2002 #line directives by Francesco Potortì.
  *
@@ -77,11 +75,11 @@ University of California, as described above. */
 
 /*
  * If you want to add support for a new language, start by looking at the LUA
- * language, which is the simplest.  Alternatively, consider shipping a
- * configuration file containing regexp definitions for etags.
+ * language, which is the simplest.  Alternatively, consider distributing etags
+ * together with a configuration file containing regexp definitions for etags.
  */
 
-char pot_etags_version[] = "@(#) pot revision number is 17.34";
+char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 
 #define        TRUE    1
 #define        FALSE   0
@@ -102,15 +100,10 @@ char pot_etags_version[] = "@(#) pot revision number is 17.34";
 # ifndef PTR                   /* for XEmacs */
 #   define PTR void *
 # endif
-# ifndef __P                   /* for XEmacs */
-#   define __P(args) args
-# endif
 #else  /* no config.h */
 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
-#   define __P(args) args      /* use prototypes */
 #   define PTR void *          /* for generic pointers */
 # else /* not standard C */
-#   define __P(args) ()                /* no prototypes */
 #   define const               /* remove const for old compilers' sake */
 #   define PTR long *          /* don't use void* */
 # endif
@@ -160,21 +153,22 @@ char pot_etags_version[] = "@(#) pot revision number is 17.34";
 #  include <stdlib.h>
 #  include <string.h>
 # else /* no standard C headers */
-   extern char *getenv ();
-   extern char *strcpy ();
-   extern char *strncpy ();
-   extern char *strcat ();
-   extern char *strncat ();
-   extern unsigned long strlen ();
-   extern PTR malloc ();
-   extern PTR realloc ();
-#  ifdef VMS
-#   define EXIT_SUCCESS        1
-#   define EXIT_FAILURE        0
-#  else /* no VMS */
-#   define EXIT_SUCCESS        0
-#   define EXIT_FAILURE        1
-#  endif
+   extern char *getenv (const char *);
+   extern char *strcpy (char *, const char *);
+   extern char *strncpy (char *, const char *, unsigned long);
+   extern char *strcat (char *, const char *);
+   extern char *strncat (char *, const char *, unsigned long);
+   extern int strcmp (const char *, const char *);
+   extern int strncmp (const char *, const char *, unsigned long);
+   extern int system (const char *);
+   extern unsigned long strlen (const char *);
+   extern void *malloc (unsigned long);
+   extern void *realloc (void *, unsigned long);
+   extern void exit (int);
+   extern void free (void *);
+   extern void *memmove (void *, const void *, unsigned long);
+#  define EXIT_SUCCESS 0
+#  define EXIT_FAILURE 1
 # endif
 #endif /* !WINDOWSNT */
 
@@ -189,9 +183,6 @@ char pot_etags_version[] = "@(#) pot revision number is 17.34";
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
-#ifndef errno
-  extern int errno;
-#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -277,7 +268,7 @@ If you want regular expression support, you should delete this notice and
 
 #define bool int
 
-typedef void Lang_function __P((FILE *));
+typedef void Lang_function (FILE *);
 
 typedef struct
 {
@@ -369,87 +360,87 @@ typedef struct regexp
 /* Many compilers barf on this:
        Lang_function Ada_funcs;
    so let's write it this way */
-static void Ada_funcs __P((FILE *));
-static void Asm_labels __P((FILE *));
-static void C_entries __P((int c_ext, FILE *));
-static void default_C_entries __P((FILE *));
-static void plain_C_entries __P((FILE *));
-static void Cjava_entries __P((FILE *));
-static void Cobol_paragraphs __P((FILE *));
-static void Cplusplus_entries __P((FILE *));
-static void Cstar_entries __P((FILE *));
-static void Erlang_functions __P((FILE *));
-static void Forth_words __P((FILE *));
-static void Fortran_functions __P((FILE *));
-static void HTML_labels __P((FILE *));
-static void Lisp_functions __P((FILE *));
-static void Lua_functions __P((FILE *));
-static void Makefile_targets __P((FILE *));
-static void Pascal_functions __P((FILE *));
-static void Perl_functions __P((FILE *));
-static void PHP_functions __P((FILE *));
-static void PS_functions __P((FILE *));
-static void Prolog_functions __P((FILE *));
-static void Python_functions __P((FILE *));
-static void Scheme_functions __P((FILE *));
-static void TeX_commands __P((FILE *));
-static void Texinfo_nodes __P((FILE *));
-static void Yacc_entries __P((FILE *));
-static void just_read_file __P((FILE *));
-
-static void print_language_names __P((void));
-static void print_version __P((void));
-static void print_help __P((argument *));
-int main __P((int, char **));
-
-static compressor *get_compressor_from_suffix __P((char *, char **));
-static language *get_language_from_langname __P((const char *));
-static language *get_language_from_interpreter __P((char *));
-static language *get_language_from_filename __P((char *, bool));
-static void readline __P((linebuffer *, FILE *));
-static long readline_internal __P((linebuffer *, FILE *));
-static bool nocase_tail __P((char *));
-static void get_tag __P((char *, char **));
-
-static void analyse_regex __P((char *));
-static void free_regexps __P((void));
-static void regex_tag_multiline __P((void));
-static void error __P((const char *, const char *));
-static void suggest_asking_for_help __P((void));
-void fatal __P((char *, char *));
-static void pfatal __P((char *));
-static void add_node __P((node *, node **));
-
-static void init __P((void));
-static void process_file_name __P((char *, language *));
-static void process_file __P((FILE *, char *, language *));
-static void find_entries __P((FILE *));
-static void free_tree __P((node *));
-static void free_fdesc __P((fdesc *));
-static void pfnote __P((char *, bool, char *, int, int, long));
-static void make_tag __P((char *, int, bool, char *, int, int, long));
-static void invalidate_nodes __P((fdesc *, node **));
-static void put_entries __P((node *));
-
-static char *concat __P((char *, char *, char *));
-static char *skip_spaces __P((char *));
-static char *skip_non_spaces __P((char *));
-static char *savenstr __P((char *, int));
-static char *savestr __P((char *));
-static char *etags_strchr __P((const char *, int));
-static char *etags_strrchr __P((const char *, int));
-static int etags_strcasecmp __P((const char *, const char *));
-static int etags_strncasecmp __P((const char *, const char *, int));
-static char *etags_getcwd __P((void));
-static char *relative_filename __P((char *, char *));
-static char *absolute_filename __P((char *, char *));
-static char *absolute_dirname __P((char *, char *));
-static bool filename_is_absolute __P((char *f));
-static void canonicalize_filename __P((char *));
-static void linebuffer_init __P((linebuffer *));
-static void linebuffer_setlen __P((linebuffer *, int));
-static PTR xmalloc __P((unsigned int));
-static PTR xrealloc __P((char *, unsigned int));
+static void Ada_funcs (FILE *);
+static void Asm_labels (FILE *);
+static void C_entries (int c_ext, FILE *);
+static void default_C_entries (FILE *);
+static void plain_C_entries (FILE *);
+static void Cjava_entries (FILE *);
+static void Cobol_paragraphs (FILE *);
+static void Cplusplus_entries (FILE *);
+static void Cstar_entries (FILE *);
+static void Erlang_functions (FILE *);
+static void Forth_words (FILE *);
+static void Fortran_functions (FILE *);
+static void HTML_labels (FILE *);
+static void Lisp_functions (FILE *);
+static void Lua_functions (FILE *);
+static void Makefile_targets (FILE *);
+static void Pascal_functions (FILE *);
+static void Perl_functions (FILE *);
+static void PHP_functions (FILE *);
+static void PS_functions (FILE *);
+static void Prolog_functions (FILE *);
+static void Python_functions (FILE *);
+static void Scheme_functions (FILE *);
+static void TeX_commands (FILE *);
+static void Texinfo_nodes (FILE *);
+static void Yacc_entries (FILE *);
+static void just_read_file (FILE *);
+
+static void print_language_names (void);
+static void print_version (void);
+static void print_help (argument *);
+int main (int, char **);
+
+static compressor *get_compressor_from_suffix (char *, char **);
+static language *get_language_from_langname (const char *);
+static language *get_language_from_interpreter (char *);
+static language *get_language_from_filename (char *, bool);
+static void readline (linebuffer *, FILE *);
+static long readline_internal (linebuffer *, FILE *);
+static bool nocase_tail (char *);
+static void get_tag (char *, char **);
+
+static void analyse_regex (char *);
+static void free_regexps (void);
+static void regex_tag_multiline (void);
+static void error (const char *, const char *);
+static void suggest_asking_for_help (void);
+void fatal (char *, char *);
+static void pfatal (char *);
+static void add_node (node *, node **);
+
+static void init (void);
+static void process_file_name (char *, language *);
+static void process_file (FILE *, char *, language *);
+static void find_entries (FILE *);
+static void free_tree (node *);
+static void free_fdesc (fdesc *);
+static void pfnote (char *, bool, char *, int, int, long);
+static void make_tag (char *, int, bool, char *, int, int, long);
+static void invalidate_nodes (fdesc *, node **);
+static void put_entries (node *);
+
+static char *concat (char *, char *, char *);
+static char *skip_spaces (char *);
+static char *skip_non_spaces (char *);
+static char *savenstr (char *, int);
+static char *savestr (char *);
+static char *etags_strchr (const char *, int);
+static char *etags_strrchr (const char *, int);
+static int etags_strcasecmp (const char *, const char *);
+static int etags_strncasecmp (const char *, const char *, int);
+static char *etags_getcwd (void);
+static char *relative_filename (char *, char *);
+static char *absolute_filename (char *, char *);
+static char *absolute_dirname (char *, char *);
+static bool filename_is_absolute (char *f);
+static void canonicalize_filename (char *);
+static void linebuffer_init (linebuffer *);
+static void linebuffer_setlen (linebuffer *, int);
+static PTR xmalloc (unsigned int);
+static PTR xrealloc (char *, unsigned int);
 
 \f
 static char searchar = '/';    /* use /.../ searches */
@@ -491,7 +482,7 @@ static char
   *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
 
 static bool append_to_tagfile; /* -a: append to tags */
-/* The next five default to TRUE for etags, but to FALSE for ctags.  */
+/* The next five default to TRUE in C and derived languages.  */
 static bool typedefs;          /* -t: create tags for C and Ada typedefs */
 static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
                                /* 0 struct/enum/union decls, and C++ */
@@ -508,7 +499,7 @@ static bool update;         /* -u: update tags */
 static bool vgrind_style;      /* -v: create vgrind style index output */
 static bool no_warnings;       /* -w: suppress warnings (undocumented) */
 static bool cxref_style;       /* -x: create cxref style output */
-static bool cplusplus;         /* .[hc] means C++, not C */
+static bool cplusplus;         /* .[hc] means C++, not C (undocumented) */
 static bool ignoreindent;      /* -I: ignore indentation in C */
 static bool packages_only;     /* --packages-only: in Ada, only tag packages*/
 
@@ -615,10 +606,19 @@ followed by a colon, are tags.";
 
 
 /* Note that .c and .h can be considered C++, if the --c++ flag was
-   given, or if the `class' or `template' keyowrds are met inside the file.
+   given, or if the `class' or `template' keywords are met inside the file.
    That is why default_C_entries is called for these. */
 static char *default_C_suffixes [] =
   { "c", "h", NULL };
+#if CTAGS                              /* C help for Ctags */
+static char default_C_help [] =
+"In C code, any C function is a tag.  Use -t to tag typedefs.\n\
+Use -T to tag definitions of `struct', `union' and `enum'.\n\
+Use -d to tag `#define' macro definitions and `enum' constants.\n\
+Use --globals to tag global variables.\n\
+You can tag function declarations and external variables by\n\
+using `--declarations', and struct members by using `--members'.";
+#else                                  /* C help for Etags */
 static char default_C_help [] =
 "In C code, any C function or typedef is a tag, and so are\n\
 definitions of `struct', `union' and `enum'.  `#define' macro\n\
@@ -629,6 +629,7 @@ definitions and `enum' constants are tags unless you specify\n\
 `--no-members' can make the tags table file much smaller.\n\
 You can tag function declarations and external variables by\n\
 using `--declarations'.";
+#endif /* C help for Ctags and Etags */
 
 static char *Cplusplus_suffixes [] =
   { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
@@ -847,7 +848,7 @@ static language lang_names [] =
 
 \f
 static void
-print_language_names ()
+print_language_names (void)
 {
   language *lang;
   char **name, **ext;
@@ -883,13 +884,13 @@ etags --help --lang=ada.");
 # define EMACS_NAME "standalone"
 #endif
 #ifndef VERSION
-# define VERSION "17.34"
+# define VERSION "17.38.1.4"
 #endif
 static void
-print_version ()
+print_version (void)
 {
   /* Makes it easier to update automatically. */
-  char emacs_copyright[] = "Copyright (C) 2007 Free Software Foundation, Inc.";
+  char emacs_copyright[] = "Copyright (C) 2010 Free Software Foundation, Inc.";
 
   printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
   puts (emacs_copyright);
@@ -903,8 +904,7 @@ print_version ()
 #endif
 
 static void
-print_help (argbuffer)
-     argument *argbuffer;
+print_help (argument *argbuffer)
 {
   bool help_for_lang = FALSE;
 
@@ -1080,135 +1080,8 @@ Relative ones are stored relative to the output file's directory.\n");
 }
 
 \f
-#ifdef VMS                     /* VMS specific functions */
-
-#define        EOS     '\0'
-
-/* This is a BUG!  ANY arbitrary limit is a BUG!
-   Won't someone please fix this?  */
-#define        MAX_FILE_SPEC_LEN       255
-typedef struct {
-  short   curlen;
-  char    body[MAX_FILE_SPEC_LEN + 1];
-} vspec;
-
-/*
- v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
- returning in each successive call the next file name matching the input
- spec. The function expects that each in_spec passed
- to it will be processed to completion; in particular, up to and
- including the call following that in which the last matching name
- is returned, the function ignores the value of in_spec, and will
- only start processing a new spec with the following call.
- If an error occurs, on return out_spec contains the value
- of in_spec when the error occurred.
-
- With each successive file name returned in out_spec, the
- function's return value is one. When there are no more matching
- names the function returns zero. If on the first call no file
- matches in_spec, or there is any other error, -1 is returned.
-*/
-
-#include       <rmsdef.h>
-#include       <descrip.h>
-#define                OUTSIZE MAX_FILE_SPEC_LEN
-static short
-fn_exp (out, in)
-     vspec *out;
-     char *in;
-{
-  static long context = 0;
-  static struct dsc$descriptor_s o;
-  static struct dsc$descriptor_s i;
-  static bool pass1 = TRUE;
-  long status;
-  short retval;
-
-  if (pass1)
-    {
-      pass1 = FALSE;
-      o.dsc$a_pointer = (char *) out;
-      o.dsc$w_length = (short)OUTSIZE;
-      i.dsc$a_pointer = in;
-      i.dsc$w_length = (short)strlen(in);
-      i.dsc$b_dtype = DSC$K_DTYPE_T;
-      i.dsc$b_class = DSC$K_CLASS_S;
-      o.dsc$b_dtype = DSC$K_DTYPE_VT;
-      o.dsc$b_class = DSC$K_CLASS_VS;
-    }
-  if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
-    {
-      out->body[out->curlen] = EOS;
-      return 1;
-    }
-  else if (status == RMS$_NMF)
-    retval = 0;
-  else
-    {
-      strcpy(out->body, in);
-      retval = -1;
-    }
-  lib$find_file_end(&context);
-  pass1 = TRUE;
-  return retval;
-}
-
-/*
-  v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
-  name of each file specified by the provided arg expanding wildcards.
-*/
-static char *
-gfnames (arg, p_error)
-     char *arg;
-     bool *p_error;
-{
-  static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
-
-  switch (fn_exp (&filename, arg))
-    {
-    case 1:
-      *p_error = FALSE;
-      return filename.body;
-    case 0:
-      *p_error = FALSE;
-      return NULL;
-    default:
-      *p_error = TRUE;
-      return filename.body;
-    }
-}
-
-#ifndef OLD  /* Newer versions of VMS do provide `system'.  */
-system (cmd)
-     char *cmd;
-{
-  error ("%s", "system() function not implemented under VMS");
-}
-#endif
-
-#define        VERSION_DELIM   ';'
-char *massage_name (s)
-     char *s;
-{
-  char *start = s;
-
-  for ( ; *s; s++)
-    if (*s == VERSION_DELIM)
-      {
-       *s = EOS;
-       break;
-      }
-    else
-      *s = lowcase (*s);
-  return start;
-}
-#endif /* VMS */
-
-\f
 int
-main (argc, argv)
-     int argc;
-     char *argv[];
+main (int argc, char **argv)
 {
   int i;
   unsigned int nincluded_files;
@@ -1217,9 +1090,6 @@ main (argc, argv)
   int current_arg, file_count;
   linebuffer filename_lb;
   bool help_asked = FALSE;
-#ifdef VMS
-  bool got_err;
-#endif
  char *optstring;
  int opt;
 
@@ -1239,15 +1109,12 @@ main (argc, argv)
   argbuffer = xnew (argc, argument);
 
   /*
-   * If etags, always find typedefs and structure tags.  Why not?
+   * Always find typedefs and structure tags.
    * Also default to find macro constants, enum constants, struct
-   * members and global variables.
+   * members and global variables.  Do it for both etags and ctags.
    */
-  if (!CTAGS)
-    {
-      typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
-      globals = members = TRUE;
-    }
+  typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
+  globals = members = TRUE;
 
   /* When the optstring begins with a '-' getopt_long does not rearrange the
      non-options arguments to be at the end, but leaves them alone. */
@@ -1373,7 +1240,7 @@ main (argc, argv)
     }
 
   if (tagfile == NULL)
-    tagfile = CTAGS ? "tags" : "TAGS";
+    tagfile = savestr (CTAGS ? "tags" : "TAGS");
   cwd = etags_getcwd ();       /* the current working directory */
   if (cwd[strlen (cwd) - 1] != '/')
     {
@@ -1381,12 +1248,16 @@ main (argc, argv)
       cwd = concat (oldcwd, "/", "");
       free (oldcwd);
     }
-  /* Relative file names are made relative to the current directory. */
+
+  /* Compute base directory for relative file names. */
   if (streq (tagfile, "-")
       || strneq (tagfile, "/dev/", 5))
-    tagfiledir = cwd;
+    tagfiledir = cwd;           /* relative file names are relative to cwd */
   else
-    tagfiledir = absolute_dirname (tagfile, cwd);
+    {
+      canonicalize_filename (tagfile);
+      tagfiledir = absolute_dirname (tagfile, cwd);
+    }
 
   init ();                     /* set up boolean "functions" */
 
@@ -1430,21 +1301,7 @@ main (argc, argv)
          analyse_regex (argbuffer[i].what);
          break;
        case at_filename:
-#ifdef VMS
-         while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
-           {
-             if (got_err)
-               {
-                 error ("can't find file %s\n", this_file);
-                 argc--, argv++;
-               }
-             else
-               {
-                 this_file = massage_name (this_file);
-               }
-#else
              this_file = argbuffer[i].what;
-#endif
              /* Input file named "-" means read file names from stdin
                 (one per line) and use them. */
              if (streq (this_file, "-"))
@@ -1457,9 +1314,6 @@ main (argc, argv)
                }
              else
                process_file_name (this_file, lang);
-#ifdef VMS
-           }
-#endif
          break;
         case at_stdin:
           this_file = argbuffer[i].what;
@@ -1498,6 +1352,7 @@ main (argc, argv)
       exit (EXIT_SUCCESS);
     }
 
+  /* From here on, we are in (CTAGS && !cxref_style) */
   if (update)
     {
       char cmd[BUFSIZ];
@@ -1551,14 +1406,12 @@ main (argc, argv)
  * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
  */
 static compressor *
-get_compressor_from_suffix (file, extptr)
-     char *file;
-     char **extptr;
+get_compressor_from_suffix (char *file, char **extptr)
 {
   compressor *compr;
   char *slash, *suffix;
 
-  /* This relies on FN to be after canonicalize_filename,
+  /* File has been processed by canonicalize_filename,
      so we don't need to consider backslashes on DOS_NT.  */
   slash = etags_strrchr (file, '/');
   suffix = etags_strrchr (file, '.');
@@ -1589,8 +1442,7 @@ get_compressor_from_suffix (file, extptr)
  * Return a language given the name.
  */
 static language *
-get_language_from_langname (name)
-     const char *name;
+get_language_from_langname (const char *name)
 {
   language *lang;
 
@@ -1612,8 +1464,7 @@ get_language_from_langname (name)
  * Return a language given the interpreter name.
  */
 static language *
-get_language_from_interpreter (interpreter)
-     char *interpreter;
+get_language_from_interpreter (char *interpreter)
 {
   language *lang;
   char **iname;
@@ -1635,9 +1486,7 @@ get_language_from_interpreter (interpreter)
  * Return a language given the file name.
  */
 static language *
-get_language_from_filename (file, case_sensitive)
-     char *file;
-     bool case_sensitive;
+get_language_from_filename (char *file, int case_sensitive)
 {
   language *lang;
   char **name, **ext, *suffix;
@@ -1671,9 +1520,7 @@ get_language_from_filename (file, case_sensitive)
  * This routine is called on each file argument.
  */
 static void
-process_file_name (file, lang)
-     char *file;
-     language *lang;
+process_file_name (char *file, language *lang)
 {
   struct stat stat_buf;
   FILE *inf;
@@ -1787,18 +1634,15 @@ process_file_name (file, lang)
     pfatal (file);
 
  cleanup:
-  if (compressed_name) free (compressed_name);
-  if (uncompressed_name) free (uncompressed_name);
+  free (compressed_name);
+  free (uncompressed_name);
   last_node = NULL;
   curfdp = NULL;
   return;
 }
 
 static void
-process_file (fh, fn, lang)
-     FILE *fh;
-     char *fn;
-     language *lang;
+process_file (FILE *fh, char *fn, language *lang)
 {
   static const fdesc emptyfdesc;
   fdesc *fdp;
@@ -1875,7 +1719,7 @@ process_file (fh, fn, lang)
  * of a char is TRUE if it is the string "white", else FALSE.
  */
 static void
-init ()
+init (void)
 {
   register char *sp;
   register int i;
@@ -1898,8 +1742,7 @@ init ()
  * which finds the function and type definitions.
  */
 static void
-find_entries (inf)
-     FILE *inf;
+find_entries (FILE *inf)
 {
   char *cp;
   language *lang = curfdp->lang;
@@ -2057,14 +1900,14 @@ find_entries (inf)
  * etags.el needs to use the same characters that are in NONAM.
  */
 static void
-make_tag (name, namelen, is_func, linestart, linelen, lno, cno)
-     char *name;               /* tag name, or NULL if unnamed */
-     int namelen;              /* tag length */
-     bool is_func;             /* tag is a function */
-     char *linestart;          /* start of the line where tag is */
-     int linelen;              /* length of the line where tag is */
-     int lno;                  /* line number */
-     long cno;                 /* character number */
+make_tag (char *name, int namelen, int is_func, char *linestart, int linelen, int lno, long int cno)
+                               /* tag name, or NULL if unnamed */
+                               /* tag length */
+                               /* tag is a function */
+                               /* start of the line where tag is */
+                               /* length of the line where tag is */
+                               /* line number */
+                               /* character number */
 {
   bool named = (name != NULL && namelen > 0);
 
@@ -2100,13 +1943,13 @@ make_tag (name, namelen, is_func, linestart, linelen, lno, cno)
 
 /* Record a tag. */
 static void
-pfnote (name, is_func, linestart, linelen, lno, cno)
-     char *name;               /* tag name, or NULL if unnamed */
-     bool is_func;             /* tag is a function */
-     char *linestart;          /* start of the line where tag is */
-     int linelen;              /* length of the line where tag is */
-     int lno;                  /* line number */
-     long cno;                 /* character number */
+pfnote (char *name, int is_func, char *linestart, int linelen, int lno, long int cno)
+                               /* tag name, or NULL if unnamed */
+                               /* tag is a function */
+                               /* start of the line where tag is */
+                               /* length of the line where tag is */
+                               /* line number */
+                               /* character number */
 {
   register node *np;
 
@@ -2160,15 +2003,13 @@ pfnote (name, is_func, linestart, linelen, lno, cno)
  *     recurse on left children, iterate on right children.
  */
 static void
-free_tree (np)
-     register node *np;
+free_tree (register node *np)
 {
   while (np)
     {
       register node *node_right = np->right;
       free_tree (np->left);
-      if (np->name != NULL)
-       free (np->name);
+      free (np->name);
       free (np->regex);
       free (np);
       np = node_right;
@@ -2180,14 +2021,13 @@ free_tree (np)
  *     delete a file description
  */
 static void
-free_fdesc (fdp)
-     register fdesc *fdp;
+free_fdesc (register fdesc *fdp)
 {
-  if (fdp->infname != NULL) free (fdp->infname);
-  if (fdp->infabsname != NULL) free (fdp->infabsname);
-  if (fdp->infabsdir != NULL) free (fdp->infabsdir);
-  if (fdp->taggedfname != NULL) free (fdp->taggedfname);
-  if (fdp->prop != NULL) free (fdp->prop);
+  free (fdp->infname);
+  free (fdp->infabsname);
+  free (fdp->infabsdir);
+  free (fdp->taggedfname);
+  free (fdp->prop);
   free (fdp);
 }
 
@@ -2201,8 +2041,7 @@ free_fdesc (fdp)
  *     maintain state.
  */
 static void
-add_node (np, cur_node_p)
-     node *np, **cur_node_p;
+add_node (node *np, node **cur_node_p)
 {
   register int dif;
   register node *cur_node = *cur_node_p;
@@ -2282,9 +2121,7 @@ add_node (np, cur_node_p)
  *     given file description (CTAGS case) or free them (ETAGS case).
  */
 static void
-invalidate_nodes (badfdp, npp)
-     fdesc *badfdp;
-     node **npp;
+invalidate_nodes (fdesc *badfdp, node **npp)
 {
   node *np = *npp;
 
@@ -2316,13 +2153,12 @@ invalidate_nodes (badfdp, npp)
 }
 
 \f
-static int total_size_of_entries __P((node *));
-static int number_len __P((long));
+static int total_size_of_entries (node *);
+static int number_len (long);
 
 /* Length of a non-negative number's decimal representation. */
 static int
-number_len (num)
-     long num;
+number_len (long int num)
 {
   int len = 1;
   while ((num /= 10) > 0)
@@ -2337,8 +2173,7 @@ number_len (num)
  * but is still supplied for backward compatibility.
  */
 static int
-total_size_of_entries (np)
-     register node *np;
+total_size_of_entries (register node *np)
 {
   register int total = 0;
 
@@ -2358,8 +2193,7 @@ total_size_of_entries (np)
 }
 
 static void
-put_entries (np)
-     register node *np;
+put_entries (register node *np)
 {
   register char *sp;
   static fdesc *fdp = NULL;
@@ -2468,9 +2302,9 @@ enum sym_type
   st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef
 };
 
-static unsigned int hash __P((const char *, unsigned int));
-static struct C_stab_entry * in_word_set __P((const char *, unsigned int));
-static enum sym_type C_symtype __P((char *, int, int));
+static unsigned int hash (const char *, unsigned int);
+static struct C_stab_entry * in_word_set (const char *, unsigned int);
+static enum sym_type C_symtype (char *, int, int);
 
 /* Feed stuff between (but not including) %[ and %] lines to:
      gperf -m 5
@@ -2486,6 +2320,7 @@ while,            0,                      st_C_ignore
 switch,                0,                      st_C_ignore
 return,                0,                      st_C_ignore
 __attribute__, 0,                      st_C_attribute
+GTY,            0,                      st_C_attribute
 @interface,    0,                      st_C_objprot
 @protocol,     0,                      st_C_objprot
 @implementation,0,                     st_C_objimpl
@@ -2537,9 +2372,7 @@ inline
 #endif
 #endif
 static unsigned int
-hash (str, len)
-     register const char *str;
-     register unsigned int len;
+hash (register const char *str, register unsigned int len)
 {
   static unsigned char asso_values[] =
     {
@@ -2549,9 +2382,9 @@ hash (str, len)
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-      35, 35, 35, 35, 35, 35, 35, 35, 35, 15,
-      14, 35, 35, 35, 35, 35, 35, 35, 14, 35,
-      35, 35, 35, 12, 13, 35, 35, 35, 35, 12,
+      35, 35, 35, 35, 35, 35, 35, 35, 35,  3,
+      26, 35, 35, 35, 35, 35, 35, 35, 27, 35,
+      35, 35, 35, 24,  0, 35, 35, 35, 35,  0,
       35, 35, 35, 35, 35,  1, 35, 16, 35,  6,
       23,  0,  0, 35, 22,  0, 35, 35,  5,  0,
        0, 15,  1, 35,  6, 35,  8, 19, 35, 16,
@@ -2585,13 +2418,11 @@ hash (str, len)
 }
 
 static struct C_stab_entry *
-in_word_set (str, len)
-     register const char *str;
-     register unsigned int len;
+in_word_set (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 32,
+      TOTAL_KEYWORDS = 33,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 15,
       MIN_HASH_VALUE = 2,
@@ -2602,7 +2433,7 @@ in_word_set (str, len)
     {
       {""}, {""},
       {"if",           0,                      st_C_ignore},
-      {""},
+      {"GTY",           0,                      st_C_attribute},
       {"@end",         0,                      st_C_objend},
       {"union",                0,                      st_C_struct},
       {"define",               0,                      st_C_define},
@@ -2653,10 +2484,7 @@ in_word_set (str, len)
 /*%>*/
 
 static enum sym_type
-C_symtype (str, len, c_ext)
-     char *str;
-     int len;
-     int c_ext;
+C_symtype (char *str, int len, int c_ext)
 {
   register struct C_stab_entry *se = in_word_set (str, len);
 
@@ -2783,9 +2611,9 @@ static struct tok
  * Variables and functions for dealing with nested structures.
  * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
  */
-static void pushclass_above __P((int, char *, int));
-static void popclass_above __P((int));
-static void write_classname __P((linebuffer *, char *qualifier));
+static void pushclass_above (int, char *, int);
+static void popclass_above (int);
+static void write_classname (linebuffer *, char *qualifier);
 
 static struct {
   char **cname;                        /* nested class names */
@@ -2800,10 +2628,7 @@ static struct {
                         && bracelev == cstack.bracelev[nestlev-1] + 1)
 
 static void
-pushclass_above (bracelev, str, len)
-     int bracelev;
-     char *str;
-     int len;
+pushclass_above (int bracelev, char *str, int len)
 {
   int nl;
 
@@ -2822,8 +2647,7 @@ pushclass_above (bracelev, str, len)
 }
 
 static void
-popclass_above (bracelev)
-     int bracelev;
+popclass_above (int bracelev)
 {
   int nl;
 
@@ -2831,16 +2655,13 @@ popclass_above (bracelev)
        nl >= 0 && cstack.bracelev[nl] >= bracelev;
        nl--)
     {
-      if (cstack.cname[nl] != NULL)
-       free (cstack.cname[nl]);
+      free (cstack.cname[nl]);
       cstack.nl = nl;
     }
 }
 
 static void
-write_classname (cn, qualifier)
-     linebuffer *cn;
-     char *qualifier;
+write_classname (linebuffer *cn, char *qualifier)
 {
   int i, len;
   int qlen = strlen (qualifier);
@@ -2874,8 +2695,8 @@ write_classname (cn, qualifier)
 }
 
 \f
-static bool consider_token __P((char *, int, int, int *, int, int, bool *));
-static void make_C_tag __P((bool));
+static bool consider_token (char *, int, int, int *, int, int, bool *);
+static void make_C_tag (bool);
 
 /*
  * consider_token ()
@@ -2895,14 +2716,14 @@ static void make_C_tag __P((bool));
  */
 
 static bool
-consider_token (str, len, c, c_extp, bracelev, parlev, is_func_or_var)
-     register char *str;       /* IN: token pointer */
-     register int len;         /* IN: token length */
-     register int c;           /* IN: first char after the token */
-     int *c_extp;              /* IN, OUT: C extensions mask */
-     int bracelev;             /* IN: brace level */
-     int parlev;               /* IN: parenthesis level */
-     bool *is_func_or_var;     /* OUT: function or variable found */
+consider_token (register char *str, register int len, register int c, int *c_extp, int bracelev, int parlev, int *is_func_or_var)
+                               /* IN: token pointer */
+                               /* IN: token length */
+                               /* IN: first char after the token */
+                               /* IN, OUT: C extensions mask */
+                               /* IN: brace level */
+                               /* IN: parenthesis level */
+                               /* OUT: function or variable found */
 {
   /* When structdef is stagseen, scolonseen, or snone with bracelev > 0,
      structtype is the type of the preceding struct-like keyword, and
@@ -3006,11 +2827,6 @@ consider_token (str, len, c, c_extp, bracelev, parlev, is_func_or_var)
        return TRUE;
      }
 
-   /*
-    * 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
-    * name as another tag, and this loses with ctags.
-    */
    switch (toktype)
      {
      case st_C_javastruct:
@@ -3241,21 +3057,20 @@ do {                                                                    \
 
 
 static void
-make_C_tag (isfun)
-     bool isfun;
+make_C_tag (int isfun)
 {
   /* This function is never called when token.valid is FALSE, but
      we must protect against invalid input or internal errors. */
-  if (!DEBUG && !token.valid)
-    return;
-
   if (token.valid)
     make_tag (token_name.buffer, token_name.len, isfun, token.line,
              token.offset+token.length+1, token.lineno, token.linepos);
-  else                         /* this case is optimised away if !DEBUG */
-    make_tag (concat ("INVALID TOKEN:-->", token_name.buffer, ""),
-             token_name.len + 17, isfun, token.line,
-             token.offset+token.length+1, token.lineno, token.linepos);
+  else if (DEBUG)
+    {                            /* this branch is optimised away if !DEBUG */
+      make_tag (concat ("INVALID TOKEN:-->", token_name.buffer, ""),
+               token_name.len + 17, isfun, token.line,
+               token.offset+token.length+1, token.lineno, token.linepos);
+      error ("INVALID TOKEN", NULL);
+    }
 
   token.valid = FALSE;
 }
@@ -3268,9 +3083,9 @@ make_C_tag (isfun)
  *     C syntax and adds them to the list.
  */
 static void
-C_entries (c_ext, inf)
-     int c_ext;                        /* extension of C */
-     FILE *inf;                        /* input file */
+C_entries (int c_ext, FILE *inf)
+                                       /* extension of C */
+                                       /* input file */
 {
   register char c;             /* latest char read; '\0' for end of line */
   register char *lp;           /* pointer one beyond the character `c' */
@@ -3978,7 +3793,7 @@ C_entries (c_ext, inf)
              make_C_tag (FALSE);  /* a struct or enum */
              break;
            }
-         bracelev++;
+         bracelev += 1;
          break;
        case '*':
          if (definedef != dnone)
@@ -3992,20 +3807,18 @@ C_entries (c_ext, inf)
        case '}':
          if (definedef != dnone)
            break;
+         bracelev -= 1;
          if (!ignoreindent && lp == newlb.buffer + 1)
            {
              if (bracelev != 0)
-               token.valid = FALSE;
+               token.valid = FALSE; /* unexpected value, token unreliable */
              bracelev = 0;     /* reset brace level if first column */
              parlev = 0;       /* also reset paren level, just in case... */
            }
-         else
+         else if (bracelev < 0)
            {
-             if (--bracelev < 0)
-               {
-                 bracelev = 0;
-                 token.valid = FALSE; /* something gone amiss, token unreliable */
-               }
+             token.valid = FALSE; /* something gone amiss, token unreliable */
+             bracelev = 0;
            }
          if (bracelev == 0 && fvdef == vignore)
            fvdef = fvnone;             /* end of function */
@@ -4102,48 +3915,42 @@ C_entries (c_ext, inf)
  * of a global flag.
  */
 static void
-default_C_entries (inf)
-     FILE *inf;
+default_C_entries (FILE *inf)
 {
   C_entries (cplusplus ? C_PLPL : C_AUTO, inf);
 }
 
 /* Always do plain C. */
 static void
-plain_C_entries (inf)
-     FILE *inf;
+plain_C_entries (FILE *inf)
 {
   C_entries (0, inf);
 }
 
 /* Always do C++. */
 static void
-Cplusplus_entries (inf)
-     FILE *inf;
+Cplusplus_entries (FILE *inf)
 {
   C_entries (C_PLPL, inf);
 }
 
 /* Always do Java. */
 static void
-Cjava_entries (inf)
-     FILE *inf;
+Cjava_entries (FILE *inf)
 {
   C_entries (C_JAVA, inf);
 }
 
 /* Always do C*. */
 static void
-Cstar_entries (inf)
-     FILE *inf;
+Cstar_entries (FILE *inf)
 {
   C_entries (C_STAR, inf);
 }
 
 /* Always do Yacc. */
 static void
-Yacc_entries (inf)
-     FILE *inf;
+Yacc_entries (FILE *inf)
 {
   C_entries (YACC, inf);
 }
@@ -4176,8 +3983,7 @@ Yacc_entries (inf)
  * matching on files that have no language defined.
  */
 static void
-just_read_file (inf)
-     FILE *inf;
+just_read_file (FILE *inf)
 {
   register char *dummy;
 
@@ -4188,11 +3994,11 @@ just_read_file (inf)
 \f
 /* Fortran parsing */
 
-static void F_takeprec __P((void));
-static void F_getit __P((FILE *));
+static void F_takeprec (void);
+static void F_getit (FILE *);
 
 static void
-F_takeprec ()
+F_takeprec (void)
 {
   dbp = skip_spaces (dbp);
   if (*dbp != '*')
@@ -4215,8 +4021,7 @@ F_takeprec ()
 }
 
 static void
-F_getit (inf)
-     FILE *inf;
+F_getit (FILE *inf)
 {
   register char *cp;
 
@@ -4240,8 +4045,7 @@ F_getit (inf)
 
 
 static void
-Fortran_functions (inf)
-     FILE *inf;
+Fortran_functions (FILE *inf)
 {
   LOOP_ON_INPUT_LINES (inf, lb, dbp)
     {
@@ -4250,6 +4054,10 @@ Fortran_functions (inf)
       dbp = skip_spaces (dbp);
       if (*dbp == '\0')
        continue;
+
+      if (LOOKING_AT_NOCASE (dbp, "recursive"))
+       dbp = skip_spaces (dbp);
+
       switch (lowcase (*dbp))
        {
        case 'i':
@@ -4319,14 +4127,12 @@ Fortran_functions (inf)
  * Philippe Waroquiers (1998)
  */
 
-static void Ada_getit __P((FILE *, char *));
+static void Ada_getit (FILE *, char *);
 
 /* Once we are positioned after an "interesting" keyword, let's get
    the real tag value necessary. */
 static void
-Ada_getit (inf, name_qualifier)
-     FILE *inf;
-     char *name_qualifier;
+Ada_getit (FILE *inf, char *name_qualifier)
 {
   register char *cp;
   char *name;
@@ -4389,8 +4195,7 @@ Ada_getit (inf, name_qualifier)
 }
 
 static void
-Ada_funcs (inf)
-     FILE *inf;
+Ada_funcs (FILE *inf)
 {
   bool inquote = FALSE;
   bool skip_till_semicolumn = FALSE;
@@ -4503,8 +4308,7 @@ Ada_funcs (inf)
  * Idea by Bob Weiner, Motorola Inc. (1994)
  */
 static void
-Asm_labels (inf)
-     FILE *inf;
+Asm_labels (FILE *inf)
 {
   register char *cp;
 
@@ -4536,15 +4340,14 @@ Asm_labels (inf)
  * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
  */
 static void
-Perl_functions (inf)
-     FILE *inf;
+Perl_functions (FILE *inf)
 {
   char *package = savestr ("main"); /* current package name */
   register char *cp;
 
   LOOP_ON_INPUT_LINES (inf, lb, cp)
     {
-      skip_spaces(cp);
+      cp = skip_spaces (cp);
 
       if (LOOKING_AT (cp, "package"))
        {
@@ -4619,8 +4422,7 @@ Perl_functions (inf)
  * More ideas by seb bacon <seb@jamkit.com> (2002)
  */
 static void
-Python_functions (inf)
-     FILE *inf;
+Python_functions (FILE *inf)
 {
   register char *cp;
 
@@ -4650,8 +4452,7 @@ Python_functions (inf)
  * Idea by Diez B. Roggisch (2001)
  */
 static void
-PHP_functions (inf)
-     FILE *inf;
+PHP_functions (FILE *inf)
 {
   register char *cp, *name;
   bool search_identifier = FALSE;
@@ -4730,8 +4531,7 @@ PHP_functions (inf)
  * Idea by Corny de Souza (1993)
  */
 static void
-Cobol_paragraphs (inf)
-     FILE *inf;
+Cobol_paragraphs (FILE *inf)
 {
   register char *bp, *ep;
 
@@ -4759,8 +4559,7 @@ Cobol_paragraphs (inf)
  * Ideas by Assar Westerlund <assar@sics.se> (2001)
  */
 static void
-Makefile_targets (inf)
-     FILE *inf;
+Makefile_targets (FILE *inf)
 {
   register char *bp;
 
@@ -4795,8 +4594,7 @@ Makefile_targets (inf)
  *  the tag is skipped.
  */
 static void
-Pascal_functions (inf)
-     FILE *inf;
+Pascal_functions (FILE *inf)
 {
   linebuffer tline;            /* mostly copied from C_entries */
   long save_lcno;
@@ -4973,10 +4771,10 @@ Pascal_functions (inf)
  *  look for (def or (DEF, quote or QUOTE
  */
 
-static void L_getit __P((void));
+static void L_getit (void);
 
 static void
-L_getit ()
+L_getit (void)
 {
   if (*dbp == '\'')            /* Skip prefix quote */
     dbp++;
@@ -4992,8 +4790,7 @@ L_getit ()
 }
 
 static void
-Lisp_functions (inf)
-     FILE *inf;
+Lisp_functions (FILE *inf)
 {
   LOOP_ON_INPUT_LINES (inf, lb, dbp)
     {
@@ -5037,8 +4834,7 @@ Lisp_functions (inf)
  *  "function" and "local function" are tags if they start at column 1.
  */
 static void
-Lua_functions (inf)
-     FILE *inf;
+Lua_functions (FILE *inf)
 {
   register char *bp;
 
@@ -5064,8 +4860,7 @@ Lua_functions (inf)
  *   Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
  */
 static void
-PS_functions (inf)
-     FILE *inf;
+PS_functions (FILE *inf)
 {
   register char *bp, *ep;
 
@@ -5095,8 +4890,7 @@ PS_functions (inf)
  * Ideas by Eduardo Horvath <eeh@netbsd.org> (2004)
  */
 static void
-Forth_words (inf)
-     FILE *inf;
+Forth_words (FILE *inf)
 {
   register char *bp;
 
@@ -5132,8 +4926,7 @@ Forth_words (inf)
  * Original code by Ken Haase (1985?)
  */
 static void
-Scheme_functions (inf)
-     FILE *inf;
+Scheme_functions (FILE *inf)
 {
   register char *bp;
 
@@ -5142,8 +4935,9 @@ Scheme_functions (inf)
       if (strneq (bp, "(def", 4) || strneq (bp, "(DEF", 4))
        {
          bp = skip_non_spaces (bp+4);
-         /* Skip over open parens and white space */
-         while (notinname (*bp))
+         /* Skip over open parens and white space.  Don't continue past
+            '\0'. */
+         while (*bp && notinname (*bp))
            bp++;
          get_tag (bp, NULL);
        }
@@ -5172,8 +4966,8 @@ static char *TEX_defenv = "\
 :part:appendix:entry:index:def\
 :newcommand:renewcommand:newenvironment:renewenvironment";
 
-static void TEX_mode __P((FILE *));
-static void TEX_decode_env __P((char *, char *));
+static void TEX_mode (FILE *);
+static void TEX_decode_env (char *, char *);
 
 static char TEX_esc = '\\';
 static char TEX_opgrp = '{';
@@ -5183,8 +4977,7 @@ static char TEX_clgrp = '}';
  * TeX/LaTeX scanning loop.
  */
 static void
-TeX_commands (inf)
-     FILE *inf;
+TeX_commands (FILE *inf)
 {
   char *cp;
   linebuffer *key;
@@ -5248,8 +5041,7 @@ TeX_commands (inf)
 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
    chars accordingly. */
 static void
-TEX_mode (inf)
-     FILE *inf;
+TEX_mode (FILE *inf)
 {
   int c;
 
@@ -5283,9 +5075,7 @@ TEX_mode (inf)
 /* Read environment and prepend it to the default string.
    Build token table. */
 static void
-TEX_decode_env (evarname, defenv)
-     char *evarname;
-     char *defenv;
+TEX_decode_env (char *evarname, char *defenv)
 {
   register char *env, *p;
   int i, len;
@@ -5333,8 +5123,7 @@ TEX_decode_env (evarname, defenv)
 \f
 /* Texinfo support.  Dave Love, Mar. 2000.  */
 static void
-Texinfo_nodes (inf)
-     FILE * inf;
+Texinfo_nodes (FILE *inf)
 {
   char *cp, *start;
   LOOP_ON_INPUT_LINES (inf, lb, cp)
@@ -5357,8 +5146,7 @@ Texinfo_nodes (inf)
  * Francesco Potortì, 2002.
  */
 static void
-HTML_labels (inf)
-     FILE * inf;
+HTML_labels (FILE *inf)
 {
   bool getnext = FALSE;                /* next text outside of HTML tags is a tag */
   bool skiptag = FALSE;                /* skip to the end of the current HTML tag */
@@ -5478,13 +5266,12 @@ HTML_labels (inf)
  * Original code by Sunichirou Sugou (1989)
  * Rewritten by Anders Lindgren (1996)
  */
-static int prolog_pr __P((char *, char *));
-static void prolog_skip_comment __P((linebuffer *, FILE *));
-static int prolog_atom __P((char *, int));
+static int prolog_pr (char *, char *);
+static void prolog_skip_comment (linebuffer *, FILE *);
+static int prolog_atom (char *, int);
 
 static void
-Prolog_functions (inf)
-     FILE *inf;
+Prolog_functions (FILE *inf)
 {
   char *cp, *last;
   int len;
@@ -5515,15 +5302,12 @@ Prolog_functions (inf)
          last[len] = '\0';
        }
     }
-  if (last != NULL)
-    free (last);
+  free (last);
 }
 
 
 static void
-prolog_skip_comment (plb, inf)
-     linebuffer *plb;
-     FILE *inf;
+prolog_skip_comment (linebuffer *plb, FILE *inf)
 {
   char *cp;
 
@@ -5549,9 +5333,9 @@ prolog_skip_comment (plb, inf)
  * header was found.
  */
 static int
-prolog_pr (s, last)
-     char *s;
-     char *last;               /* Name of last clause. */
+prolog_pr (char *s, char *last)
+             
+                               /* Name of last clause. */
 {
   int pos;
   int len;
@@ -5587,9 +5371,7 @@ prolog_pr (s, last)
  *   Backslash quotes everything.
  */
 static int
-prolog_atom (s, pos)
-     char *s;
-     int pos;
+prolog_atom (char *s, int pos)
 {
   int origpos;
 
@@ -5644,13 +5426,12 @@ prolog_atom (s, pos)
  * Assumes that Erlang functions start at column 0.
  * Original code by Anders Lindgren (1996)
  */
-static int erlang_func __P((char *, char *));
-static void erlang_attribute __P((char *));
-static int erlang_atom __P((char *));
+static int erlang_func (char *, char *);
+static void erlang_attribute (char *);
+static int erlang_atom (char *);
 
 static void
-Erlang_functions (inf)
-     FILE *inf;
+Erlang_functions (FILE *inf)
 {
   char *cp, *last;
   int len;
@@ -5694,8 +5475,7 @@ Erlang_functions (inf)
          last[len] = '\0';
        }
     }
-  if (last != NULL)
-    free (last);
+  free (last);
 }
 
 
@@ -5710,9 +5490,9 @@ Erlang_functions (inf)
  * was found.
  */
 static int
-erlang_func (s, last)
-     char *s;
-     char *last;               /* Name of last clause. */
+erlang_func (char *s, char *last)
+             
+                               /* Name of last clause. */
 {
   int pos;
   int len;
@@ -5748,8 +5528,7 @@ erlang_func (s, last)
  * -record(graph, {vtab = notable, cyclic = true}).
  */
 static void
-erlang_attribute (s)
-     char *s;
+erlang_attribute (char *s)
 {
   char *cp = s;
 
@@ -5769,8 +5548,7 @@ erlang_attribute (s)
  * Return the number of bytes consumed, or -1 if there was an error.
  */
 static int
-erlang_atom (s)
-     char *s;
+erlang_atom (char *s)
 {
   int pos = 0;
 
@@ -5794,9 +5572,9 @@ erlang_atom (s)
 }
 
 \f
-static char *scan_separators __P((char *));
-static void add_regex __P((char *, language *));
-static char *substitute __P((char *, char *, struct re_registers *));
+static char *scan_separators (char *);
+static void add_regex (char *, language *);
+static char *substitute (char *, char *, struct re_registers *);
 
 /*
  * Take a string like "/blah/" and turn it into "blah", verifying
@@ -5808,8 +5586,7 @@ static char *substitute __P((char *, char *, struct re_registers *));
  * unterminated regexps.
  */
 static char *
-scan_separators (name)
-     char *name;
+scan_separators (char *name)
 {
   char sep = name[0];
   char *copyto = name;
@@ -5861,8 +5638,7 @@ scan_separators (name)
 /* Look at the argument of --regex or --no-regex and do the right
    thing.  Same for each line of a regexp file. */
 static void
-analyse_regex (regex_arg)
-     char *regex_arg;
+analyse_regex (char *regex_arg)
 {
   if (regex_arg == NULL)
     {
@@ -5933,9 +5709,7 @@ analyse_regex (regex_arg)
 /* Separate the regexp pattern, compile it,
    and care for optional name and modifiers. */
 static void
-add_regex (regexp_pattern, lang)
-     char *regexp_pattern;
-     language *lang;
+add_regex (char *regexp_pattern, language *lang)
 {
   static struct re_pattern_buffer zeropattern;
   char sep, *pat, *name, *modifiers;
@@ -6025,7 +5799,7 @@ add_regex (regexp_pattern, lang)
   else
     re_set_syntax (RE_SYNTAX_EMACS);
 
-  err = re_compile_pattern (pat, strlen (regexp_pattern), patbuf);
+  err = re_compile_pattern (pat, strlen (pat), patbuf);
   if (multi_line)
     free (pat);
   if (err != NULL)
@@ -6052,9 +5826,7 @@ add_regex (regexp_pattern, lang)
  * arguments.
  */
 static char *
-substitute (in, out, regs)
-     char *in, *out;
-     struct re_registers *regs;
+substitute (char *in, char *out, struct re_registers *regs)
 {
   char *result, *t;
   int size, dig, diglen;
@@ -6101,7 +5873,7 @@ substitute (in, out, regs)
 
 /* Deallocate all regexps. */
 static void
-free_regexps ()
+free_regexps (void)
 {
   regexp *rp;
   while (p_head != NULL)
@@ -6123,7 +5895,7 @@ free_regexps ()
  * Idea by Ben Wing <ben@666.com> (2002).
  */
 static void
-regex_tag_multiline ()
+regex_tag_multiline (void)
 {
   char *buffer = filebuf.buffer;
   regexp *rp;
@@ -6200,8 +5972,7 @@ regex_tag_multiline ()
 
 \f
 static bool
-nocase_tail (cp)
-     char *cp;
+nocase_tail (char *cp)
 {
   register int len = 0;
 
@@ -6216,9 +5987,7 @@ nocase_tail (cp)
 }
 
 static void
-get_tag (bp, namepp)
-     register char *bp;
-     char **namepp;
+get_tag (register char *bp, char **namepp)
 {
   register char *cp = bp;
 
@@ -6249,9 +6018,7 @@ get_tag (bp, namepp)
  * appended to `filebuf'.
  */
 static long
-readline_internal (lbp, stream)
-     linebuffer *lbp;
-     register FILE *stream;
+readline_internal (linebuffer *lbp, register FILE *stream)
 {
   char *buffer = lbp->buffer;
   register char *p = lbp->buffer;
@@ -6329,9 +6096,7 @@ readline_internal (lbp, stream)
  * directives.
  */
 static void
-readline (lbp, stream)
-     linebuffer *lbp;
-     FILE *stream;
+readline (linebuffer *lbp, FILE *stream)
 {
   long result;
 
@@ -6369,7 +6134,7 @@ readline (lbp, stream)
                  discard_until_line_directive = FALSE; /* found it */
                  name = lbp->buffer + start;
                  *endp = '\0';
-                 canonicalize_filename (name); /* for DOS */
+                 canonicalize_filename (name);
                  taggedabsname = absolute_filename (name, tagfiledir);
                  if (filename_is_absolute (name)
                      || filename_is_absolute (curfdp->infname))
@@ -6441,7 +6206,7 @@ readline (lbp, stream)
                  readline (lbp, stream);
                  return;
                } /* if a real #line directive */
-           } /* if #line is followed by a number */
+           } /* if #line is followed by a number */
        } /* if line begins with "#line " */
 
       /* If we are here, no #line directive was found. */
@@ -6524,8 +6289,7 @@ readline (lbp, stream)
  * with xnew where the string CP has been copied.
  */
 static char *
-savestr (cp)
-     char *cp;
+savestr (char *cp)
 {
   return savenstr (cp, strlen (cp));
 }
@@ -6535,9 +6299,7 @@ savestr (cp)
  * the string CP has been copied for at most the first LEN characters.
  */
 static char *
-savenstr (cp, len)
-     char *cp;
-     int len;
+savenstr (char *cp, int len)
 {
   register char *dp;
 
@@ -6554,9 +6316,7 @@ savenstr (cp, len)
  * Identical to POSIX strrchr, included for portability.
  */
 static char *
-etags_strrchr (sp, c)
-     register const char *sp;
-     register int c;
+etags_strrchr (register const char *sp, register int c)
 {
   register const char *r;
 
@@ -6576,9 +6336,7 @@ etags_strrchr (sp, c)
  * Identical to POSIX strchr, included for portability.
  */
 static char *
-etags_strchr (sp, c)
-     register const char *sp;
-     register int c;
+etags_strchr (register const char *sp, register int c)
 {
   do
     {
@@ -6594,9 +6352,7 @@ etags_strchr (sp, c)
  * Same as BSD's strcasecmp, included for portability.
  */
 static int
-etags_strcasecmp (s1, s2)
-     register const char *s1;
-     register const char *s2;
+etags_strcasecmp (register const char *s1, register const char *s2)
 {
   while (*s1 != '\0'
         && (ISALPHA (*s1) && ISALPHA (*s2)
@@ -6616,10 +6372,7 @@ etags_strcasecmp (s1, s2)
  * Same as BSD's strncasecmp, included for portability.
  */
 static int
-etags_strncasecmp (s1, s2, n)
-     register const char *s1;
-     register const char *s2;
-     register int n;
+etags_strncasecmp (register const char *s1, register const char *s2, register int n)
 {
   while (*s1 != '\0' && n-- > 0
         && (ISALPHA (*s1) && ISALPHA (*s2)
@@ -6637,8 +6390,7 @@ etags_strncasecmp (s1, s2, n)
 
 /* Skip spaces (end of string is not space), return new pointer. */
 static char *
-skip_spaces (cp)
-     char *cp;
+skip_spaces (char *cp)
 {
   while (iswhite (*cp))
     cp++;
@@ -6647,8 +6399,7 @@ skip_spaces (cp)
 
 /* Skip non spaces, except end of string, return new pointer. */
 static char *
-skip_non_spaces (cp)
-     char *cp;
+skip_non_spaces (char *cp)
 {
   while (*cp != '\0' && !iswhite (*cp))
     cp++;
@@ -6657,23 +6408,21 @@ skip_non_spaces (cp)
 
 /* Print error message and exit.  */
 void
-fatal (s1, s2)
-     char *s1, *s2;
+fatal (char *s1, char *s2)
 {
   error (s1, s2);
   exit (EXIT_FAILURE);
 }
 
 static void
-pfatal (s1)
-     char *s1;
+pfatal (char *s1)
 {
   perror (s1);
   exit (EXIT_FAILURE);
 }
 
 static void
-suggest_asking_for_help ()
+suggest_asking_for_help (void)
 {
   fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
           progname, NO_LONG_OPTIONS ? "-h" : "--help");
@@ -6682,8 +6431,7 @@ suggest_asking_for_help ()
 
 /* Print error message.  `s1' is printf control string, `s2' is arg for it. */
 static void
-error (s1, s2)
-     const char *s1, *s2;
+error (const char *s1, const char *s2)
 {
   fprintf (stderr, "%s: ", progname);
   fprintf (stderr, s1, s2);
@@ -6693,8 +6441,7 @@ error (s1, s2)
 /* Return a newly-allocated string whose contents
    concatenate those of s1, s2, s3.  */
 static char *
-concat (s1, s2, s3)
-     char *s1, *s2, *s3;
+concat (char *s1, char *s2, char *s3)
 {
   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
   char *result = xnew (len1 + len2 + len3 + 1, char);
@@ -6711,7 +6458,7 @@ concat (s1, s2, s3)
 /* Does the same work as the system V getcwd, but does not need to
    guess the buffer size in advance. */
 static char *
-etags_getcwd ()
+etags_getcwd (void)
 {
 #ifdef HAVE_GETCWD
   int bufsize = 200;
@@ -6761,8 +6508,7 @@ etags_getcwd ()
 /* Return a newly allocated string containing the file name of FILE
    relative to the absolute directory DIR (which should end with a slash). */
 static char *
-relative_filename (file, dir)
-     char *file, *dir;
+relative_filename (char *file, char *dir)
 {
   char *fp, *dp, *afn, *res;
   int i;
@@ -6801,8 +6547,7 @@ relative_filename (file, dir)
 /* Return a newly allocated string containing the absolute file name
    of FILE given DIR (which should end with a slash). */
 static char *
-absolute_filename (file, dir)
-     char *file, *dir;
+absolute_filename (char *file, char *dir)
 {
   char *slashp, *cp, *res;
 
@@ -6839,13 +6584,22 @@ absolute_filename (file, dir)
              else if (cp[0] != '/')
                cp = slashp;
 #endif
+#ifdef HAVE_MEMMOVE
+              memmove (cp, slashp + 3, strlen (slashp + 2));
+#else
+              /* Overlapping copy isn't really okay */
              strcpy (cp, slashp + 3);
+#endif
              slashp = cp;
              continue;
            }
          else if (slashp[2] == '/' || slashp[2] == '\0')
            {
-             strcpy (slashp, slashp + 2);
+#ifdef HAVE_MEMMOVE
+             memmove (slashp, slashp + 2, strlen (slashp + 1));
+#else
+              strcpy (slashp, slashp + 2);
+#endif
              continue;
            }
        }
@@ -6866,13 +6620,11 @@ absolute_filename (file, dir)
    file name of dir where FILE resides given DIR (which should
    end with a slash). */
 static char *
-absolute_dirname (file, dir)
-     char *file, *dir;
+absolute_dirname (char *file, char *dir)
 {
   char *slashp, *res;
   char save;
 
-  canonicalize_filename (file);
   slashp = etags_strrchr (file, '/');
   if (slashp == NULL)
     return savestr (dir);
@@ -6887,8 +6639,7 @@ absolute_dirname (file, dir)
 /* Whether the argument string is an absolute file name.  The argument
    string must have been canonicalized with canonicalize_filename. */
 static bool
-filename_is_absolute (fn)
-     char *fn;
+filename_is_absolute (char *fn)
 {
   return (fn[0] == '/'
 #ifdef DOS_NT
@@ -6897,30 +6648,39 @@ filename_is_absolute (fn)
          );
 }
 
-/* Translate backslashes into slashes.  Works in place. */
+/* Upcase DOS drive letter and collapse separators into single slashes.
+   Works in place. */
 static void
-canonicalize_filename (fn)
-     register char *fn;
+canonicalize_filename (register char *fn)
 {
+  register char* cp;
+  char sep = '/';
+
 #ifdef DOS_NT
   /* Canonicalize drive letter case.  */
   if (fn[0] != '\0' && fn[1] == ':' && ISLOWER (fn[0]))
     fn[0] = upcase (fn[0]);
-  /* Convert backslashes to slashes.  */
-  for (; *fn != '\0'; fn++)
-    if (*fn == '\\')
-      *fn = '/';
-#else
-  /* No action. */
-  fn = NULL;                   /* shut up the compiler */
+
+  sep = '\\';
 #endif
+
+  /* Collapse multiple separators into a single slash. */
+  for (cp = fn; *cp != '\0'; cp++, fn++)
+    if (*cp == sep)
+      {
+       *fn = '/';
+       while (cp[1] == sep)
+         cp++;
+      }
+    else
+      *fn = *cp;
+  *fn = '\0';
 }
 
 \f
-/* Initialize a linebuffer for use */
+/* Initialize a linebuffer for use. */
 static void
-linebuffer_init (lbp)
-     linebuffer *lbp;
+linebuffer_init (linebuffer *lbp)
 {
   lbp->size = (DEBUG) ? 3 : 200;
   lbp->buffer = xnew (lbp->size, char);
@@ -6930,9 +6690,7 @@ linebuffer_init (lbp)
 
 /* Set the minimum size of a string contained in a linebuffer. */
 static void
-linebuffer_setlen (lbp, toksize)
-     linebuffer *lbp;
-     int toksize;
+linebuffer_setlen (linebuffer *lbp, int toksize)
 {
   while (lbp->size <= toksize)
     {
@@ -6944,8 +6702,7 @@ linebuffer_setlen (lbp, toksize)
 
 /* Like malloc but get fatal error if memory is exhausted. */
 static PTR
-xmalloc (size)
-     unsigned int size;
+xmalloc (unsigned int size)
 {
   PTR result = (PTR) malloc (size);
   if (result == NULL)
@@ -6954,9 +6711,7 @@ xmalloc (size)
 }
 
 static PTR
-xrealloc (ptr, size)
-     char *ptr;
-     unsigned int size;
+xrealloc (char *ptr, unsigned int size)
 {
   PTR result = (PTR) realloc (ptr, size);
   if (result == NULL)