Add NO_RETURN specifiers to functions in lib-src.
[bpt/emacs.git] / lib-src / etags.c
index 56a84d6..b78686d 100644 (file)
@@ -29,7 +29,7 @@ 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, 2008
+  2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
@@ -59,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ì reorganized 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ì.
  *
@@ -75,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.38";
+char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 
 #define        TRUE    1
 #define        FALSE   0
@@ -100,15 +100,10 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38";
 # 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
@@ -158,20 +153,20 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38";
 #  include <stdlib.h>
 #  include <string.h>
 # else /* no standard C headers */
-   extern char *getenv __P((const char *));
-   extern char *strcpy __P((char *, const char *));
-   extern char *strncpy __P((char *, const char *, unsigned long));
-   extern char *strcat __P((char *, const char *));
-   extern char *strncat __P((char *, const char *, unsigned long));
-   extern int strcmp __P((const char *, const char *));
-   extern int strncmp __P((const char *, const char *, unsigned long));
-   extern int system __P((const char *));
-   extern unsigned long strlen __P((const char *));
-   extern void *malloc __P((unsigned long));
-   extern void *realloc __P((void *, unsigned long));
-   extern void exit __P((int));
-   extern void free __P((void *));
-   extern void *memmove __P((void *, const void *, unsigned long));
+   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
@@ -188,9 +183,6 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38";
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
-#ifndef errno
-  extern int errno;
-#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -276,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
 {
@@ -368,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) NO_RETURN;
+void fatal (char *, char *) NO_RETURN;
+static void pfatal (char *) NO_RETURN;
+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 */
@@ -856,7 +848,7 @@ static language lang_names [] =
 
 \f
 static void
-print_language_names ()
+print_language_names (void)
 {
   language *lang;
   char **name, **ext;
@@ -892,13 +884,13 @@ etags --help --lang=ada.");
 # define EMACS_NAME "standalone"
 #endif
 #ifndef VERSION
-# define VERSION "17.38"
+# 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) 2008 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);
@@ -912,8 +904,7 @@ print_version ()
 #endif
 
 static void
-print_help (argbuffer)
-     argument *argbuffer;
+print_help (argument *argbuffer)
 {
   bool help_for_lang = FALSE;
 
@@ -1090,9 +1081,7 @@ Relative ones are stored relative to the output file's directory.\n");
 
 \f
 int
-main (argc, argv)
-     int argc;
-     char *argv[];
+main (int argc, char **argv)
 {
   int i;
   unsigned int nincluded_files;
@@ -1251,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] != '/')
     {
@@ -1259,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" */
 
@@ -1413,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, '.');
@@ -1451,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;
 
@@ -1474,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;
@@ -1497,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;
@@ -1533,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;
@@ -1657,10 +1642,7 @@ process_file_name (file, lang)
 }
 
 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;
@@ -1737,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;
@@ -1760,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;
@@ -1919,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);
 
@@ -1962,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;
 
@@ -2022,8 +2003,7 @@ 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)
     {
@@ -2041,8 +2021,7 @@ free_tree (np)
  *     delete a file description
  */
 static void
-free_fdesc (fdp)
-     register fdesc *fdp;
+free_fdesc (register fdesc *fdp)
 {
   free (fdp->infname);
   free (fdp->infabsname);
@@ -2062,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;
@@ -2143,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;
 
@@ -2177,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)
@@ -2198,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;
 
@@ -2219,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;
@@ -2329,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
@@ -2399,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[] =
     {
@@ -2447,9 +2418,7 @@ 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
     {
@@ -2515,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);
 
@@ -2645,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 */
@@ -2662,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;
 
@@ -2684,8 +2647,7 @@ pushclass_above (bracelev, str, len)
 }
 
 static void
-popclass_above (bracelev)
-     int bracelev;
+popclass_above (int bracelev)
 {
   int nl;
 
@@ -2699,9 +2661,7 @@ popclass_above (bracelev)
 }
 
 static void
-write_classname (cn, qualifier)
-     linebuffer *cn;
-     char *qualifier;
+write_classname (linebuffer *cn, char *qualifier)
 {
   int i, len;
   int qlen = strlen (qualifier);
@@ -2735,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 ()
@@ -2756,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
@@ -3097,8 +3057,7 @@ 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. */
@@ -3124,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' */
@@ -3956,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);
 }
@@ -4030,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;
 
@@ -4042,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 != '*')
@@ -4069,8 +4021,7 @@ F_takeprec ()
 }
 
 static void
-F_getit (inf)
-     FILE *inf;
+F_getit (FILE *inf)
 {
   register char *cp;
 
@@ -4094,8 +4045,7 @@ F_getit (inf)
 
 
 static void
-Fortran_functions (inf)
-     FILE *inf;
+Fortran_functions (FILE *inf)
 {
   LOOP_ON_INPUT_LINES (inf, lb, dbp)
     {
@@ -4104,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':
@@ -4173,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;
@@ -4243,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;
@@ -4357,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;
 
@@ -4390,8 +4340,7 @@ 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;
@@ -4473,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;
 
@@ -4504,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;
@@ -4584,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;
 
@@ -4613,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;
 
@@ -4649,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;
@@ -4827,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++;
@@ -4846,8 +4790,7 @@ L_getit ()
 }
 
 static void
-Lisp_functions (inf)
-     FILE *inf;
+Lisp_functions (FILE *inf)
 {
   LOOP_ON_INPUT_LINES (inf, lb, dbp)
     {
@@ -4891,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;
 
@@ -4918,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;
 
@@ -4949,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;
 
@@ -4986,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;
 
@@ -4996,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);
        }
@@ -5026,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 = '{';
@@ -5037,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;
@@ -5102,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;
 
@@ -5137,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;
@@ -5187,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)
@@ -5211,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 */
@@ -5332,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;
@@ -5374,9 +5307,7 @@ Prolog_functions (inf)
 
 
 static void
-prolog_skip_comment (plb, inf)
-     linebuffer *plb;
-     FILE *inf;
+prolog_skip_comment (linebuffer *plb, FILE *inf)
 {
   char *cp;
 
@@ -5402,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;
@@ -5440,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;
 
@@ -5497,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;
@@ -5562,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;
@@ -5600,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;
 
@@ -5621,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;
 
@@ -5646,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
@@ -5660,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;
@@ -5713,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)
     {
@@ -5785,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;
@@ -5877,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)
@@ -5904,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;
@@ -5953,7 +5873,7 @@ substitute (in, out, regs)
 
 /* Deallocate all regexps. */
 static void
-free_regexps ()
+free_regexps (void)
 {
   regexp *rp;
   while (p_head != NULL)
@@ -5975,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;
@@ -6052,8 +5972,7 @@ regex_tag_multiline ()
 
 \f
 static bool
-nocase_tail (cp)
-     char *cp;
+nocase_tail (char *cp)
 {
   register int len = 0;
 
@@ -6068,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;
 
@@ -6101,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;
@@ -6181,9 +6096,7 @@ readline_internal (lbp, stream)
  * directives.
  */
 static void
-readline (lbp, stream)
-     linebuffer *lbp;
-     FILE *stream;
+readline (linebuffer *lbp, FILE *stream)
 {
   long result;
 
@@ -6221,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))
@@ -6293,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. */
@@ -6376,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));
 }
@@ -6387,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;
 
@@ -6406,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;
 
@@ -6428,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
     {
@@ -6446,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)
@@ -6468,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)
@@ -6489,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++;
@@ -6499,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++;
@@ -6509,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");
@@ -6534,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);
@@ -6545,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);
@@ -6563,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;
@@ -6613,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;
@@ -6636,14 +6530,8 @@ relative_filename (file, dir)
 
   /* Build a sequence of "../" strings for the resulting relative file name. */
   i = 0;
-  while (*dp == '/')
-    ++dp;
   while ((dp = etags_strchr (dp + 1, '/')) != NULL)
-    {
-      i += 1;
-      while (*dp == '/')
-       ++dp;
-    }
+    i += 1;
   res = xnew (3*i + strlen (fp + 1) + 1, char);
   res[0] = '\0';
   while (i-- > 0)
@@ -6659,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;
 
@@ -6697,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;
            }
        }
@@ -6724,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);
@@ -6745,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
@@ -6755,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);
@@ -6788,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)
     {
@@ -6802,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)
@@ -6812,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)