Add GCC-style 'const' attribute to functions that can use it.
[bpt/emacs.git] / lib-src / etags.c
index b739e8f..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,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.
@@ -203,9 +175,9 @@ If you want regular expression support, you should delete this notice and
 #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 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), !etags_strncasecmp (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))
@@ -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 */
@@ -867,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);
@@ -1140,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 */
          }
@@ -1224,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 */
     }
@@ -1447,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++)
@@ -1862,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 */
@@ -1895,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.
  */
@@ -2153,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
@@ -2233,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)
            {
@@ -2773,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.");
      }
 
    /*
@@ -3057,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;
@@ -3189,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)
@@ -3224,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;
@@ -3238,6 +3198,8 @@ C_entries (int c_ext, FILE *inf)
              incomm = TRUE;
              lp++;
              c = ' ';
+             if (bracketlev > 0)
+               continue;
            }
          else if (/* cplpl && */ *lp == '/')
            {
@@ -3270,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;
@@ -3284,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) */
 
 
@@ -3304,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;
@@ -5704,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;
@@ -5717,7 +5689,7 @@ add_regex (char *regexp_pattern, language *lang)
 
   if (strlen (regexp_pattern) < 3)
     {
-      error ("null regexp", (char *)NULL);
+      error ("null regexp");
       return;
     }
   sep = regexp_pattern[0];
@@ -5736,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 */
@@ -5747,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':
@@ -5761,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;
       }
 
@@ -5900,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 */
@@ -6338,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)
@@ -6421,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
@@ -6685,19 +6613,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;