Add GCC-style 'const' attribute to functions that can use it.
[bpt/emacs.git] / lib-src / etags.c
index 693c999..7141811 100644 (file)
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2011
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2012
   Free Software Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
@@ -91,25 +91,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 #  define NDEBUG               /* disable assert */
 #endif
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-  /* This is probably not necessary any more.  On some systems, config.h
-     used to define static as nothing for the sake of unexec.  We don't
-     want that here since we don't use unexec.  None of these systems
-     are supported any more, but the idea is still mentioned in
-     etc/PROBLEMS.  */
-# undef static
-# ifndef PTR                   /* for XEmacs */
-#   define PTR void *
-# endif
-#else  /* no config.h */
-# if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
-#   define PTR void *          /* for generic pointers */
-# else /* not standard C */
-#   define const               /* remove const for old compilers' sake */
-#   define PTR long *          /* don't use void* */
-# endif
-#endif /* !HAVE_CONFIG_H */
+#include <config.h>
 
 #ifndef _GNU_SOURCE
 # define _GNU_SOURCE 1         /* enables some compiler checks on GNU */
@@ -129,18 +111,12 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 # include <fcntl.h>
 # include <sys/param.h>
 # include <io.h>
-# ifndef HAVE_CONFIG_H
-#   define DOS_NT
-#   include <sys/config.h>
-# endif
 #else
 # define MSDOS FALSE
 #endif /* MSDOS */
 
 #ifdef WINDOWSNT
-# include <stdlib.h>
 # include <fcntl.h>
-# include <string.h>
 # include <direct.h>
 # include <io.h>
 # define MAXPATHLEN _MAX_PATH
@@ -151,27 +127,6 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 #   define HAVE_GETCWD
 # endif /* undef HAVE_GETCWD */
 #else /* not WINDOWSNT */
-# ifdef STDC_HEADERS
-#  include <stdlib.h>
-#  include <string.h>
-# else /* no standard C headers */
-   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 */
 
 #include <unistd.h>
@@ -181,11 +136,15 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 # endif
 #endif /* HAVE_UNISTD_H */
 
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <c-strcase.h>
 
 #include <assert.h>
 #ifdef NDEBUG
@@ -203,14 +162,6 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 # include <getopt.h>
 #endif /* NO_LONG_OPTIONS */
 
-#ifndef HAVE_CONFIG_H          /* this is a standalone compilation */
-# ifdef __CYGWIN__             /* compiling on Cygwin */
-                            !!! NOTICE !!!
- the regex.h distributed with Cygwin is not compatible with etags, alas!
-If you want regular expression support, you should delete this notice and
-             arrange to use the GNU regex.h and regex.c.
-# endif
-#endif
 #include <regex.h>
 
 /* Define CTAGS to make the program "ctags" compatible with the usual one.
@@ -223,25 +174,25 @@ If you want regular expression support, you should delete this notice and
 # define CTAGS FALSE
 #endif
 
-#define streq(s,t)     (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
-#define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
-#define strneq(s,t,n)  (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
-#define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
+#define streq(s,t)     (assert ((s)!=NULL || (t)!=NULL), !strcmp (s, t))
+#define strcaseeq(s,t) (assert ((s)!=NULL && (t)!=NULL), !c_strcasecmp (s, t))
+#define strneq(s,t,n)  (assert ((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
+#define strncaseeq(s,t,n) (assert ((s)!=NULL && (t)!=NULL), !c_strncasecmp (s, t, n))
 
 #define CHARS 256              /* 2^sizeof(char) */
 #define CHAR(x)                ((unsigned int)(x) & (CHARS - 1))
-#define        iswhite(c)      (_wht[CHAR(c)]) /* c is white (see white) */
-#define notinname(c)   (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
-#define        begtoken(c)     (_btk[CHAR(c)]) /* c can start token (see begtk) */
-#define        intoken(c)      (_itk[CHAR(c)]) /* c can be in token (see midtk) */
-#define        endtoken(c)     (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
+#define        iswhite(c)      (_wht[CHAR (c)]) /* c is white (see white) */
+#define notinname(c)   (_nin[CHAR (c)]) /* c is not in a name (see nonam) */
+#define        begtoken(c)     (_btk[CHAR (c)]) /* c can start token (see begtk) */
+#define        intoken(c)      (_itk[CHAR (c)]) /* c can be in token (see midtk) */
+#define        endtoken(c)     (_etk[CHAR (c)]) /* c ends tokens (see endtk) */
 
-#define ISALNUM(c)     isalnum (CHAR(c))
-#define ISALPHA(c)     isalpha (CHAR(c))
-#define ISDIGIT(c)     isdigit (CHAR(c))
-#define ISLOWER(c)     islower (CHAR(c))
+#define ISALNUM(c)     isalnum (CHAR (c))
+#define ISALPHA(c)     isalpha (CHAR (c))
+#define ISDIGIT(c)     isdigit (CHAR (c))
+#define ISLOWER(c)     islower (CHAR (c))
 
-#define lowcase(c)     tolower (CHAR(c))
+#define lowcase(c)     tolower (CHAR (c))
 
 
 /*
@@ -347,7 +298,7 @@ typedef struct regexp
   struct re_pattern_buffer *pat; /* the compiled pattern */
   struct re_registers regs;    /* re registers */
   bool error_signaled;         /* already signaled for this regexp */
-  bool force_explicit_name;    /* do not allow implict tag name */
+  bool force_explicit_name;    /* do not allow implicit tag name */
   bool ignore_case;            /* ignore case when matching */
   bool multi_line;             /* do a multi-line match on the whole file */
 } regexp;
@@ -401,10 +352,10 @@ 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 (const char *, const char *) NO_RETURN;
-static void pfatal (const char *) NO_RETURN;
+static void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
+static _Noreturn void suggest_asking_for_help (void);
+_Noreturn void fatal (const char *, const char *);
+static _Noreturn void pfatal (const char *);
 static void add_node (node *, node **);
 
 static void init (void);
@@ -425,8 +376,6 @@ static char *savenstr (const char *, int);
 static char *savestr (const 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 *);
@@ -435,8 +384,8 @@ 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);
+static void *xmalloc (size_t);
+static void *xrealloc (char *, size_t);
 
 \f
 static char searchar = '/';    /* use /.../ searches */
@@ -446,6 +395,7 @@ static char *progname;              /* name this program was invoked with */
 static char *cwd;              /* current working directory */
 static char *tagfiledir;       /* directory of tagfile */
 static FILE *tagf;             /* ioptr for tags file */
+static ptrdiff_t whatlen_max;  /* maximum length of any 'what' member */
 
 static fdesc *fdhead;          /* head of file description list */
 static fdesc *curfdp;          /* current file description */
@@ -631,7 +581,7 @@ using `--declarations'.";
 static const char *Cplusplus_suffixes [] =
   { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
     "M",                       /* Objective C++ */
-    "pdb",                     /* Postscript with C syntax */
+    "pdb",                     /* PostScript with C syntax */
     NULL };
 static const char Cplusplus_help [] =
 "In C++ code, all the tag constructs of C code are tagged.  (Use\n\
@@ -887,7 +837,7 @@ static void
 print_version (void)
 {
   /* Makes it easier to update automatically. */
-  char emacs_copyright[] = "Copyright (C) 2011 Free Software Foundation, Inc.";
+  char emacs_copyright[] = "Copyright (C) 2012 Free Software Foundation, Inc.";
 
   printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
   puts (emacs_copyright);
@@ -1087,6 +1037,7 @@ main (int argc, char **argv)
   int current_arg, file_count;
   linebuffer filename_lb;
   bool help_asked = FALSE;
+  ptrdiff_t len;
  char *optstring;
  int opt;
 
@@ -1131,6 +1082,9 @@ main (int argc, char **argv)
        /* This means that a file name has been seen.  Record it. */
        argbuffer[current_arg].arg_type = at_filename;
        argbuffer[current_arg].what     = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        ++file_count;
        break;
@@ -1139,6 +1093,9 @@ main (int argc, char **argv)
        /* Parse standard input.  Idea by Vivek <vivek@etla.org>. */
        argbuffer[current_arg].arg_type = at_stdin;
        argbuffer[current_arg].what     = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        ++file_count;
        if (parsing_stdin)
@@ -1153,7 +1110,7 @@ main (int argc, char **argv)
       case 'o':
        if (tagfile)
          {
-           error ("-o option may only be given once.", (char *)NULL);
+           error ("-o option may only be given once.");
            suggest_asking_for_help ();
            /* NOTREACHED */
          }
@@ -1181,6 +1138,9 @@ main (int argc, char **argv)
       case 'r':
        argbuffer[current_arg].arg_type = at_regexp;
        argbuffer[current_arg].what = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        break;
       case 'R':
@@ -1219,6 +1179,9 @@ main (int argc, char **argv)
     {
       argbuffer[current_arg].arg_type = at_filename;
       argbuffer[current_arg].what = argv[optind];
+      len = strlen (argv[optind]);
+      if (whatlen_max < len)
+       whatlen_max = len;
       ++current_arg;
       ++file_count;
     }
@@ -1231,7 +1194,7 @@ main (int argc, char **argv)
 
   if (nincluded_files == 0 && file_count == 0)
     {
-      error ("no input files specified.", (char *)NULL);
+      error ("no input files specified.");
       suggest_asking_for_help ();
       /* NOTREACHED */
     }
@@ -1352,7 +1315,9 @@ main (int argc, char **argv)
   /* From here on, we are in (CTAGS && !cxref_style) */
   if (update)
     {
-      char cmd[BUFSIZ];
+      char *cmd =
+       xmalloc (strlen (tagfile) + whatlen_max +
+                sizeof "mv..OTAGS;fgrep -v '\t\t' OTAGS >;rm OTAGS");
       for (i = 0; i < current_arg; ++i)
        {
          switch (argbuffer[i].arg_type)
@@ -1363,12 +1328,17 @@ main (int argc, char **argv)
            default:
              continue;         /* the for loop */
            }
-         sprintf (cmd,
-                  "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
-                  tagfile, argbuffer[i].what, tagfile);
+         strcpy (cmd, "mv ");
+         strcat (cmd, tagfile);
+         strcat (cmd, " OTAGS;fgrep -v '\t");
+         strcat (cmd, argbuffer[i].what);
+         strcat (cmd, "\t' OTAGS >");
+         strcat (cmd, tagfile);
+         strcat (cmd, ";rm OTAGS");
          if (system (cmd) != EXIT_SUCCESS)
            fatal ("failed to execute shell command", (char *)NULL);
        }
+      free (cmd);
       append_to_tagfile = TRUE;
     }
 
@@ -1384,11 +1354,14 @@ main (int argc, char **argv)
   if (CTAGS)
     if (append_to_tagfile || update)
       {
-       char cmd[2*BUFSIZ+20];
+       char *cmd = xmalloc (2 * strlen (tagfile) + sizeof "sort -u -o..");
        /* Maybe these should be used:
           setenv ("LC_COLLATE", "C", 1);
           setenv ("LC_ALL", "C", 1); */
-       sprintf (cmd, "sort -u -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile);
+       strcpy (cmd, "sort -u -o ");
+       strcat (cmd, tagfile);
+       strcat (cmd, " ");
+       strcat (cmd, tagfile);
        exit (system (cmd));
       }
   return EXIT_SUCCESS;
@@ -1444,7 +1417,7 @@ get_language_from_langname (const char *name)
   language *lang;
 
   if (name == NULL)
-    error ("empty language name", (char *)NULL);
+    error ("empty language name");
   else
     {
       for (lang = lang_names; lang->name != NULL; lang++)
@@ -1722,16 +1695,16 @@ init (void)
   register int i;
 
   for (i = 0; i < CHARS; i++)
-    iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
+    iswhite (i) = notinname (i) = begtoken (i) = intoken (i) = endtoken (i) = FALSE;
   for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
   for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
-  notinname('\0') = notinname('\n');
+  notinname ('\0') = notinname ('\n');
   for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
-  begtoken('\0') = begtoken('\n');
+  begtoken ('\0') = begtoken ('\n');
   for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
-  intoken('\0') = intoken('\n');
+  intoken ('\0') = intoken ('\n');
   for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
-  endtoken('\0') = endtoken('\n');
+  endtoken ('\0') = endtoken ('\n');
 }
 
 /*
@@ -1859,10 +1832,10 @@ find_entries (FILE *inf)
 
   assert (parser != NULL);
 
-  /* Generic initialisations before reading from file. */
+  /* Generic initializations before reading from file. */
   linebuffer_setlen (&filebuf, 0); /* reset the file buffer */
 
-  /* Generic initialisations before parsing file with readline. */
+  /* Generic initializations before parsing file with readline. */
   lineno = 0;                 /* reset global line number */
   charno = 0;                 /* reset global char number */
   linecharno = 0;             /* reset global char number of line start */
@@ -1892,7 +1865,7 @@ find_entries (FILE *inf)
  *  4. the character, if any, immediately after NAME in LINESTART must
  *     also be a character in NONAM.
  *
- * The implementation uses the notinname() macro, which recognises the
+ * The implementation uses the notinname() macro, which recognizes the
  * characters stored in the string `nonam'.
  * etags.el needs to use the same characters that are in NONAM.
  */
@@ -2150,7 +2123,7 @@ invalidate_nodes (fdesc *badfdp, node **npp)
 
 \f
 static int total_size_of_entries (node *);
-static int number_len (long);
+static int number_len (long) ATTRIBUTE_CONST;
 
 /* Length of a non-negative number's decimal representation. */
 static int
@@ -2230,7 +2203,7 @@ put_entries (register node *np)
        {
          /* Ctags mode */
          if (np->name == NULL)
-           error ("internal error: NULL name in ctags mode.", (char *)NULL);
+           error ("internal error: NULL name in ctags mode.");
 
          if (cxref_style)
            {
@@ -2770,7 +2743,7 @@ consider_token (register char *str, register int len, register int c, int *c_ext
      case dignorerest:
        return FALSE;
      default:
-       error ("internal error: definedef value.", (char *)NULL);
+       error ("internal error: definedef value.");
      }
 
    /*
@@ -3054,11 +3027,11 @@ make_C_tag (int isfun)
     make_tag (token_name.buffer, token_name.len, isfun, token.line,
              token.offset+token.length+1, token.lineno, token.linepos);
   else if (DEBUG)
-    {                            /* this branch is optimised away if !DEBUG */
+    {                            /* this branch is optimized 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);
+      error ("INVALID TOKEN");
     }
 
   token.valid = FALSE;
@@ -3186,24 +3159,12 @@ C_entries (int c_ext, FILE *inf)
            }
          continue;
        }
-      else if (bracketlev > 0)
-       {
-         switch (c)
-           {
-           case ']':
-             if (--bracketlev > 0)
-               continue;
-             break;
-           case '\0':
-             CNL_SAVE_DEFINEDEF ();
-             break;
-           }
-         continue;
-       }
       else switch (c)
        {
        case '"':
          inquote = TRUE;
+         if (bracketlev > 0)
+           continue;
          if (inattribute)
            break;
          switch (fvdef)
@@ -3221,9 +3182,11 @@ C_entries (int c_ext, FILE *inf)
          continue;
        case '\'':
          inchar = TRUE;
+         if (bracketlev > 0)
+           continue;
          if (inattribute)
            break;
-         if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
+         if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
            {
              fvextern = FALSE;
              fvdef = fvnone;
@@ -3235,6 +3198,8 @@ C_entries (int c_ext, FILE *inf)
              incomm = TRUE;
              lp++;
              c = ' ';
+             if (bracketlev > 0)
+               continue;
            }
          else if (/* cplpl && */ *lp == '/')
            {
@@ -3267,7 +3232,7 @@ C_entries (int c_ext, FILE *inf)
              for (cp = newlb.buffer; cp < lp-1; cp++)
                if (!iswhite (*cp))
                  {
-                   if (*cp == '*' && *(cp+1) == '/')
+                   if (*cp == '*' && cp[1] == '/')
                      {
                        cp++;
                        cpptoken = TRUE;
@@ -3281,7 +3246,17 @@ C_entries (int c_ext, FILE *inf)
          continue;
        case '[':
          bracketlev++;
-           continue;
+         continue;
+       default:
+         if (bracketlev > 0)
+           {
+             if (c == ']')
+               --bracketlev;
+             else if (c == '\0')
+               CNL_SAVE_DEFINEDEF ();
+             continue;
+           }
+         break;
        } /* switch (c) */
 
 
@@ -3301,7 +3276,7 @@ C_entries (int c_ext, FILE *inf)
                  if (c == ':' && *lp == ':' && begtoken (lp[1]))
                    /* This handles :: in the middle,
                       but not at the beginning of an identifier.
-                      Also, space-separated :: is not recognised. */
+                      Also, space-separated :: is not recognized. */
                    {
                      if (c_ext & C_AUTO) /* automatic detection of C++ */
                        c_ext = (c_ext | C_PLPL) & ~C_AUTO;
@@ -3956,16 +3931,16 @@ Yacc_entries (FILE *inf)
       )
 
 #define LOOKING_AT(cp, kw)  /* kw is the keyword, a literal string */  \
-  ((assert("" kw), TRUE)   /* syntax error if not a literal string */  \
-   && strneq ((cp), kw, sizeof(kw)-1)          /* cp points at kw */   \
-   && notinname ((cp)[sizeof(kw)-1])           /* end of kw */         \
-   && ((cp) = skip_spaces((cp)+sizeof(kw)-1))) /* skip spaces */
+  ((assert ("" kw), TRUE)   /* syntax error if not a literal string */ \
+   && strneq ((cp), kw, sizeof (kw)-1)         /* cp points at kw */   \
+   && notinname ((cp)[sizeof (kw)-1])          /* end of kw */         \
+   && ((cp) = skip_spaces ((cp)+sizeof (kw)-1))) /* skip spaces */
 
 /* Similar to LOOKING_AT but does not use notinname, does not skip */
 #define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */        \
-  ((assert("" kw), TRUE)     /* syntax error if not a literal string */        \
-   && strncaseeq ((cp), kw, sizeof(kw)-1)      /* cp points at kw */   \
-   && ((cp) += sizeof(kw)-1))                  /* skip spaces */
+  ((assert ("" kw), TRUE) /* syntax error if not a literal string */   \
+   && strncaseeq ((cp), kw, sizeof (kw)-1)     /* cp points at kw */   \
+   && ((cp) += sizeof (kw)-1))                 /* skip spaces */
 
 /*
  * Read a file, but do no processing.  This is used to do regexp
@@ -4045,6 +4020,12 @@ Fortran_functions (FILE *inf)
       if (LOOKING_AT_NOCASE (dbp, "recursive"))
        dbp = skip_spaces (dbp);
 
+      if (LOOKING_AT_NOCASE (dbp, "pure"))
+       dbp = skip_spaces (dbp);
+
+      if (LOOKING_AT_NOCASE (dbp, "elemental"))
+       dbp = skip_spaces (dbp);
+
       switch (lowcase (*dbp))
        {
        case 'i':
@@ -4132,7 +4113,7 @@ Ada_getit (FILE *inf, const char *name_qualifier)
          readline (&lb, inf);
          dbp = lb.buffer;
        }
-      switch (lowcase(*dbp))
+      switch (lowcase (*dbp))
         {
         case 'b':
           if (nocase_tail ("body"))
@@ -4236,7 +4217,7 @@ Ada_funcs (FILE *inf)
            }
 
          /* We are at the beginning of a token. */
-         switch (lowcase(*dbp))
+         switch (lowcase (*dbp))
            {
            case 'f':
              if (!packages_only && nocase_tail ("function"))
@@ -4362,7 +4343,7 @@ Perl_functions (FILE *inf)
              *cp = '\0';
              name = concat (package, "::", sp);
              *cp = savechar;
-             make_tag (name, strlen(name), TRUE,
+             make_tag (name, strlen (name), TRUE,
                        lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
              free (name);
            }
@@ -4457,9 +4438,9 @@ PHP_functions (FILE *inf)
        }
       else if (LOOKING_AT (cp, "function"))
        {
-         if(*cp == '&')
+         if (*cp == '&')
            cp = skip_spaces (cp+1);
-         if(*cp != '\0')
+         if (*cp != '\0')
            {
              name = cp;
              while (!notinname (*cp))
@@ -4500,7 +4481,7 @@ PHP_functions (FILE *inf)
               && *cp == '$')
        {
          name = cp;
-         while (!notinname(*cp))
+         while (!notinname (*cp))
            cp++;
          make_tag (name, cp - name, FALSE,
                    lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
@@ -4837,7 +4818,7 @@ Lua_functions (FILE *inf)
 
 \f
 /*
- * Postscript tags
+ * PostScript tags
  * Just look for lines where the first character is '/'
  * Also look at "defineps" for PSWrap
  * Ideas by:
@@ -4881,13 +4862,13 @@ Forth_words (FILE *inf)
 
   LOOP_ON_INPUT_LINES (inf, lb, bp)
     while ((bp = skip_spaces (bp))[0] != '\0')
-      if (bp[0] == '\\' && iswhite(bp[1]))
+      if (bp[0] == '\\' && iswhite (bp[1]))
        break;                  /* read next line */
-      else if (bp[0] == '(' && iswhite(bp[1]))
+      else if (bp[0] == '(' && iswhite (bp[1]))
        do                      /* skip to ) or eol */
          bp++;
        while (*bp != ')' && *bp != '\0');
-      else if ((bp[0] == ':' && iswhite(bp[1]) && bp++)
+      else if ((bp[0] == ':' && iswhite (bp[1]) && bp++)
               || LOOKING_AT_NOCASE (bp, "constant")
               || LOOKING_AT_NOCASE (bp, "code")
               || LOOKING_AT_NOCASE (bp, "create")
@@ -5276,7 +5257,7 @@ Prolog_functions (FILE *inf)
          /* Predicate or rule.  Store the function name so that we
             only generate a tag for the first clause.  */
          if (last == NULL)
-           last = xnew(len + 1, char);
+           last = xnew (len + 1, char);
          else if (len + 1 > allocated)
            xrnew (last, len + 1, char);
          allocated = len + 1;
@@ -5300,7 +5281,7 @@ prolog_skip_comment (linebuffer *plb, FILE *inf)
          return;
       readline (plb, inf);
     }
-  while (!feof(inf));
+  while (!feof (inf));
 }
 
 /*
@@ -5359,11 +5340,11 @@ prolog_atom (char *s, size_t pos)
 
   origpos = pos;
 
-  if (ISLOWER(s[pos]) || (s[pos] == '_'))
+  if (ISLOWER (s[pos]) || (s[pos] == '_'))
     {
       /* The atom is unquoted. */
       pos++;
-      while (ISALNUM(s[pos]) || (s[pos] == '_'))
+      while (ISALNUM (s[pos]) || (s[pos] == '_'))
        {
          pos++;
        }
@@ -5695,7 +5676,7 @@ add_regex (char *regexp_pattern, language *lang)
 {
   static struct re_pattern_buffer zeropattern;
   char sep, *pat, *name, *modifiers;
-  char empty[] = "";
+  char empty = '\0';
   const char *err;
   struct re_pattern_buffer *patbuf;
   regexp *rp;
@@ -5706,9 +5687,9 @@ add_regex (char *regexp_pattern, language *lang)
     single_line = FALSE;       /* dot does not match newline */
 
 
-  if (strlen(regexp_pattern) < 3)
+  if (strlen (regexp_pattern) < 3)
     {
-      error ("null regexp", (char *)NULL);
+      error ("null regexp");
       return;
     }
   sep = regexp_pattern[0];
@@ -5727,7 +5708,7 @@ add_regex (char *regexp_pattern, language *lang)
   if (modifiers == NULL)       /* no terminating separator --> no name */
     {
       modifiers = name;
-      name = empty;
+      name = &empty;
     }
   else
     modifiers += 1;            /* skip separator */
@@ -5738,7 +5719,7 @@ add_regex (char *regexp_pattern, language *lang)
       {
       case 'N':
        if (modifiers == name)
-         error ("forcing explicit tag name but no name, ignoring", NULL);
+         error ("forcing explicit tag name but no name, ignoring");
        force_explicit_name = TRUE;
        break;
       case 'i':
@@ -5752,12 +5733,7 @@ add_regex (char *regexp_pattern, language *lang)
        need_filebuf = TRUE;
        break;
       default:
-       {
-         char wrongmod [2];
-         wrongmod[0] = modifiers[0];
-         wrongmod[1] = '\0';
-         error ("invalid regexp modifier `%s', ignoring", wrongmod);
-       }
+       error ("invalid regexp modifier `%c', ignoring", modifiers[0]);
        break;
       }
 
@@ -5891,7 +5867,7 @@ regex_tag_multiline (void)
       if (!rp->multi_line)
        continue;               /* skip normal regexps */
 
-      /* Generic initialisations before parsing file from memory. */
+      /* Generic initializations before parsing file from memory. */
       lineno = 1;              /* reset global line number */
       charno = 0;              /* reset global char number */
       linecharno = 0;          /* reset global char number of line start */
@@ -6088,7 +6064,7 @@ readline (linebuffer *lbp, FILE *stream)
   lineno += 1;                 /* increment global line number */
   charno += result;            /* increment global char number */
 
-  /* Honour #line directives. */
+  /* Honor #line directives. */
   if (!no_line_directive)
     {
       static bool discard_until_line_directive;
@@ -6329,48 +6305,6 @@ etags_strchr (register const char *sp, register int c)
   return NULL;
 }
 
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- *
- * Same as BSD's strcasecmp, included for portability.
- */
-static int
-etags_strcasecmp (register const char *s1, register const char *s2)
-{
-  while (*s1 != '\0'
-        && (ISALPHA (*s1) && ISALPHA (*s2)
-            ? lowcase (*s1) == lowcase (*s2)
-            : *s1 == *s2))
-    s1++, s2++;
-
-  return (ISALPHA (*s1) && ISALPHA (*s2)
-         ? lowcase (*s1) - lowcase (*s2)
-         : *s1 - *s2);
-}
-
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- * Stop after a given number of characters
- *
- * Same as BSD's strncasecmp, included for portability.
- */
-static int
-etags_strncasecmp (register const char *s1, register const char *s2, register int n)
-{
-  while (*s1 != '\0' && n-- > 0
-        && (ISALPHA (*s1) && ISALPHA (*s2)
-            ? lowcase (*s1) == lowcase (*s2)
-            : *s1 == *s2))
-    s1++, s2++;
-
-  if (n < 0)
-    return 0;
-  else
-    return (ISALPHA (*s1) && ISALPHA (*s2)
-           ? lowcase (*s1) - lowcase (*s2)
-           : *s1 - *s2);
-}
-
 /* Skip spaces (end of string is not space), return new pointer. */
 static char *
 skip_spaces (char *cp)
@@ -6412,13 +6346,16 @@ suggest_asking_for_help (void)
   exit (EXIT_FAILURE);
 }
 
-/* Print error message.  `s1' is printf control string, `s2' is arg for it. */
+/* Output a diagnostic with printf-style FORMAT and args.  */
 static void
-error (const char *s1, const char *s2)
+error (const char *format, ...)
 {
+  va_list ap;
+  va_start (ap, format);
   fprintf (stderr, "%s: ", progname);
-  fprintf (stderr, s1, s2);
+  vfprintf (stderr, format, ap);
   fprintf (stderr, "\n");
+  va_end (ap);
 }
 
 /* Return a newly-allocated string whose contents
@@ -6567,22 +6504,13 @@ absolute_filename (char *file, char *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')
            {
-#ifdef HAVE_MEMMOVE
              memmove (slashp, slashp + 2, strlen (slashp + 1));
-#else
-              strcpy (slashp, slashp + 2);
-#endif
              continue;
            }
        }
@@ -6626,7 +6554,7 @@ filename_is_absolute (char *fn)
 {
   return (fn[0] == '/'
 #ifdef DOS_NT
-         || (ISALPHA(fn[0]) && fn[1] == ':' && fn[2] == '/')
+         || (ISALPHA (fn[0]) && fn[1] == ':' && fn[2] == '/')
 #endif
          );
 }
@@ -6641,7 +6569,7 @@ canonicalize_filename (register char *fn)
 
 #ifdef DOS_NT
   /* Canonicalize drive letter case.  */
-# define ISUPPER(c)    isupper (CHAR(c))
+# define ISUPPER(c)    isupper (CHAR (c))
   if (fn[0] != '\0' && fn[1] == ':' && ISUPPER (fn[0]))
     fn[0] = lowcase (fn[0]);
 
@@ -6685,19 +6613,19 @@ linebuffer_setlen (linebuffer *lbp, int toksize)
 }
 
 /* Like malloc but get fatal error if memory is exhausted. */
-static PTR
-xmalloc (unsigned int size)
+static void *
+xmalloc (size_t size)
 {
-  PTR result = (PTR) malloc (size);
+  void *result = malloc (size);
   if (result == NULL)
     fatal ("virtual memory exhausted", (char *)NULL);
   return result;
 }
 
-static PTR
-xrealloc (char *ptr, unsigned int size)
+static void *
+xrealloc (char *ptr, size_t size)
 {
-  PTR result = (PTR) realloc (ptr, size);
+  void *result = realloc (ptr, size);
   if (result == NULL)
     fatal ("virtual memory exhausted", (char *)NULL);
   return result;