]> code.delx.au - gnu-emacs/blobdiff - lib-src/etags.c
* variables.texi (File Local Variables): Fix reference.
[gnu-emacs] / lib-src / etags.c
index 0197bbd49cc3c2fe7ff18525412ea27230d879ae..73462c83ad7839b0004b3a3302cc06a928df507d 100644 (file)
@@ -28,8 +28,8 @@ 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
-  Free Software Foundation, Inc.
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2013 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,10 +111,6 @@ 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 */
@@ -158,6 +136,7 @@ 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>
@@ -165,6 +144,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <c-strcase.h>
 
 #include <assert.h>
 #ifdef NDEBUG
@@ -182,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.
@@ -202,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))
 
 
 /*
@@ -326,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;
@@ -380,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);
@@ -404,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 *);
@@ -414,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 (size_t);
-static PTR xrealloc (char *, size_t);
+static void *xmalloc (size_t);
+static void *xrealloc (char *, size_t);
 
 \f
 static char searchar = '/';    /* use /.../ searches */
@@ -611,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\
@@ -866,8 +836,7 @@ etags --help --lang=ada.");
 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;
 
   printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
   puts (emacs_copyright);
@@ -1140,7 +1109,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 */
          }
@@ -1224,7 +1193,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 */
     }
@@ -1447,7 +1416,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++)
@@ -1725,16 +1694,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');
 }
 
 /*
@@ -1862,10 +1831,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 */
@@ -1895,7 +1864,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.
  */
@@ -2153,7 +2122,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
@@ -2233,7 +2202,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)
            {
@@ -2672,17 +2641,11 @@ write_classname (linebuffer *cn, const char *qualifier)
     }
   for (i = 1; i < cstack.nl; i++)
     {
-      char *s;
-      int slen;
-
-      s = cstack.cname[i];
+      char *s = cstack.cname[i];
       if (s == NULL)
        continue;
-      slen = strlen (s);
-      len += slen + qlen;
-      linebuffer_setlen (cn, len);
-      strncat (cn->buffer, qualifier, qlen);
-      strncat (cn->buffer, s, slen);
+      linebuffer_setlen (cn, len + qlen + strlen (s));
+      len += sprintf (cn->buffer + len, "%s%s", qualifier, s);
     }
 }
 
@@ -2773,7 +2736,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.");
      }
 
    /*
@@ -2897,7 +2860,7 @@ consider_token (register char *str, register int len, register int c, int *c_ext
           fvdef = fvnone;
           objdef = omethodtag;
           linebuffer_setlen (&token_name, len);
-          strncpy (token_name.buffer, str, len);
+          memcpy (token_name.buffer, str, len);
           token_name.buffer[len] = '\0';
           return TRUE;
         }
@@ -2909,10 +2872,12 @@ consider_token (register char *str, register int len, register int c, int *c_ext
      case omethodparm:
        if (parlev == 0)
         {
+          int oldlen = token_name.len;
           fvdef = fvnone;
           objdef = omethodtag;
-          linebuffer_setlen (&token_name, token_name.len + len);
-          strncat (token_name.buffer, str, len);
+          linebuffer_setlen (&token_name, oldlen + len);
+          memcpy (token_name.buffer + oldlen, str, len);
+          token_name.buffer[oldlen + len] = '\0';
           return TRUE;
         }
        return FALSE;
@@ -3057,11 +3022,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;
@@ -3189,24 +3154,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)
@@ -3224,9 +3177,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;
@@ -3238,6 +3193,8 @@ C_entries (int c_ext, FILE *inf)
              incomm = TRUE;
              lp++;
              c = ' ';
+             if (bracketlev > 0)
+               continue;
            }
          else if (/* cplpl && */ *lp == '/')
            {
@@ -3270,7 +3227,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;
@@ -3284,7 +3241,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) */
 
 
@@ -3304,7 +3271,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;
@@ -3339,12 +3306,12 @@ C_entries (int c_ext, FILE *inf)
                              && nestlev > 0 && definedef == dnone)
                            /* in struct body */
                            {
+                             int len;
                               write_classname (&token_name, qualifier);
-                             linebuffer_setlen (&token_name,
-                                                token_name.len+qlen+toklen);
-                             strcat (token_name.buffer, qualifier);
-                             strncat (token_name.buffer,
-                                      newlb.buffer + tokoff, toklen);
+                             len = token_name.len;
+                             linebuffer_setlen (&token_name, len+qlen+toklen);
+                             sprintf (token_name.buffer + len, "%s%.*s",
+                                      qualifier, toklen, newlb.buffer + tokoff);
                              token.named = TRUE;
                            }
                          else if (objdef == ocatseen)
@@ -3352,11 +3319,8 @@ C_entries (int c_ext, FILE *inf)
                            {
                              int len = strlen (objtag) + 2 + toklen;
                              linebuffer_setlen (&token_name, len);
-                             strcpy (token_name.buffer, objtag);
-                             strcat (token_name.buffer, "(");
-                             strncat (token_name.buffer,
-                                      newlb.buffer + tokoff, toklen);
-                             strcat (token_name.buffer, ")");
+                             sprintf (token_name.buffer, "%s(%.*s)",
+                                      objtag, toklen, newlb.buffer + tokoff);
                              token.named = TRUE;
                            }
                          else if (objdef == omethodtag
@@ -3380,8 +3344,8 @@ C_entries (int c_ext, FILE *inf)
                                  len -= 1;
                                }
                              linebuffer_setlen (&token_name, len);
-                             strncpy (token_name.buffer,
-                                      newlb.buffer + off, len);
+                             memcpy (token_name.buffer,
+                                     newlb.buffer + off, len);
                              token_name.buffer[len] = '\0';
                              if (defun)
                                while (--len >= 0)
@@ -3392,8 +3356,8 @@ C_entries (int c_ext, FILE *inf)
                          else
                            {
                              linebuffer_setlen (&token_name, toklen);
-                             strncpy (token_name.buffer,
-                                      newlb.buffer + tokoff, toklen);
+                             memcpy (token_name.buffer,
+                                     newlb.buffer + tokoff, toklen);
                              token_name.buffer[toklen] = '\0';
                              /* Name macros and members. */
                              token.named = (structdef == stagseen
@@ -3959,16 +3923,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
@@ -4051,6 +4015,9 @@ Fortran_functions (FILE *inf)
       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':
@@ -4138,7 +4105,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"))
@@ -4242,7 +4209,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"))
@@ -4368,7 +4335,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);
            }
@@ -4463,9 +4430,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))
@@ -4506,7 +4473,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);
@@ -4684,7 +4651,7 @@ Pascal_functions (FILE *inf)
          /* Check if this is an "extern" declaration. */
          if (*dbp == '\0')
            continue;
-         if (lowcase (*dbp == 'e'))
+         if (lowcase (*dbp) == 'e')
            {
              if (nocase_tail ("extern")) /* superfluous, really! */
                {
@@ -4843,7 +4810,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:
@@ -4887,13 +4854,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")
@@ -5186,7 +5153,7 @@ HTML_labels (FILE *inf)
                  for (end = dbp; *end != '\0' && intoken (*end); end++)
                    continue;
                linebuffer_setlen (&token_name, end - dbp);
-               strncpy (token_name.buffer, dbp, end - dbp);
+               memcpy (token_name.buffer, dbp, end - dbp);
                token_name.buffer[end - dbp] = '\0';
 
                dbp = end;
@@ -5282,11 +5249,11 @@ 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;
-         strncpy (last, cp, len);
+         memcpy (last, cp, len);
          last[len] = '\0';
        }
     }
@@ -5306,7 +5273,7 @@ prolog_skip_comment (linebuffer *plb, FILE *inf)
          return;
       readline (plb, inf);
     }
-  while (!feof(inf));
+  while (!feof (inf));
 }
 
 /*
@@ -5365,11 +5332,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++;
        }
@@ -5459,7 +5426,7 @@ Erlang_functions (FILE *inf)
          else if (len + 1 > allocated)
            xrnew (last, len + 1, char);
          allocated = len + 1;
-         strncpy (last, cp, len);
+         memcpy (last, cp, len);
          last[len] = '\0';
        }
     }
@@ -5701,7 +5668,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;
@@ -5712,9 +5679,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];
@@ -5733,7 +5700,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 */
@@ -5744,7 +5711,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':
@@ -5758,12 +5725,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;
       }
 
@@ -5847,7 +5809,7 @@ substitute (char *in, char *out, struct re_registers *regs)
       {
        dig = *out - '0';
        diglen = regs->end[dig] - regs->start[dig];
-       strncpy (t, in + regs->start[dig], diglen);
+       memcpy (t, in + regs->start[dig], diglen);
        t += diglen;
       }
     else
@@ -5897,7 +5859,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 */
@@ -6070,7 +6032,7 @@ readline_internal (linebuffer *lbp, register FILE *stream)
          filebuf.size *= 2;
          xrnew (filebuf.buffer, filebuf.size, char);
        }
-      strncpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
+      memcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
       filebuf.len += lbp->len;
       filebuf.buffer[filebuf.len++] = '\n';
       filebuf.buffer[filebuf.len] = '\0';
@@ -6094,7 +6056,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;
@@ -6293,7 +6255,7 @@ savenstr (const char *cp, int len)
   register char *dp;
 
   dp = xnew (len + 1, char);
-  strncpy (dp, cp, len);
+  memcpy (dp, cp, len);
   dp[len] = '\0';
   return dp;
 }
@@ -6335,48 +6297,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)
@@ -6418,13 +6338,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
@@ -6623,7 +6546,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
          );
 }
@@ -6638,7 +6561,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]);
 
@@ -6682,19 +6605,19 @@ linebuffer_setlen (linebuffer *lbp, int toksize)
 }
 
 /* Like malloc but get fatal error if memory is exhausted. */
-static PTR
+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
+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;