* net/dbus.el (dbus-introspect): Use `dbus-call-method-non-blocking'.
[bpt/emacs.git] / lib-src / etags.c
index 0412137..46e3b6e 100644 (file)
@@ -29,15 +29,15 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 Copyright (C) 1984, 1987, 1988, 1989, 1993, 1994, 1995, 1998, 1999,
-  2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+  2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
   Free Software Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
 
-This program is free software; you can redistribute it and/or modify
+This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -45,9 +45,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 /* NB To comply with the above BSD license, copyright information is
@@ -61,14 +59,14 @@ University of California, as described above. */
 
 /*
  * Authors:
- * 1983        Ctags originally by Ken Arnold.
- * 1984        Fortran added by Jim Kleckner.
- * 1984        Ed Pelegri-Llopart added C typedefs.
- * 1985        Emacs TAGS format by Richard Stallman.
- * 1989        Sam Kendall added C++.
+ * 1983 Ctags originally by Ken Arnold.
+ * 1984 Fortran added by Jim Kleckner.
+ * 1984 Ed Pelegri-Llopart added C typedefs.
+ * 1985 Emacs TAGS format by Richard Stallman.
+ * 1989 Sam Kendall added C++.
  * 1992 Joseph B. Wells improved C and C++ parsing.
- * 1993        Francesco Potortì reorganised C and C++.
- * 1994        Line-by-line regexp tags by Tom Tromey.
+ * 1993 Francesco Potortì reorganized C and C++.
+ * 1994 Line-by-line regexp tags by Tom Tromey.
  * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
  * 2002 #line directives by Francesco Potortì.
  *
@@ -77,11 +75,11 @@ University of California, as described above. */
 
 /*
  * If you want to add support for a new language, start by looking at the LUA
- * language, which is the simplest.  Alternatively, consider shipping a
- * configuration file containing regexp definitions for etags.
+ * language, which is the simplest.  Alternatively, consider distributing etags
+ * together with a configuration file containing regexp definitions for etags.
  */
 
-char pot_etags_version[] = "@(#) pot revision number is 17.34";
+char pot_etags_version[] = "@(#) pot revision number is 17.38.1.3";
 
 #define        TRUE    1
 #define        FALSE   0
@@ -160,21 +158,22 @@ char pot_etags_version[] = "@(#) pot revision number is 17.34";
 #  include <stdlib.h>
 #  include <string.h>
 # else /* no standard C headers */
-   extern char *getenv ();
-   extern char *strcpy ();
-   extern char *strncpy ();
-   extern char *strcat ();
-   extern char *strncat ();
-   extern unsigned long strlen ();
-   extern PTR malloc ();
-   extern PTR realloc ();
-#  ifdef VMS
-#   define EXIT_SUCCESS        1
-#   define EXIT_FAILURE        0
-#  else /* no VMS */
-#   define EXIT_SUCCESS        0
-#   define EXIT_FAILURE        1
-#  endif
+   extern char *getenv __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));
+#  define EXIT_SUCCESS 0
+#  define EXIT_FAILURE 1
 # endif
 #endif /* !WINDOWSNT */
 
@@ -491,7 +490,7 @@ static char
   *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
 
 static bool append_to_tagfile; /* -a: append to tags */
-/* The next five default to TRUE for etags, but to FALSE for ctags.  */
+/* The next five default to TRUE in C and derived languages.  */
 static bool typedefs;          /* -t: create tags for C and Ada typedefs */
 static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
                                /* 0 struct/enum/union decls, and C++ */
@@ -508,7 +507,7 @@ static bool update;         /* -u: update tags */
 static bool vgrind_style;      /* -v: create vgrind style index output */
 static bool no_warnings;       /* -w: suppress warnings (undocumented) */
 static bool cxref_style;       /* -x: create cxref style output */
-static bool cplusplus;         /* .[hc] means C++, not C */
+static bool cplusplus;         /* .[hc] means C++, not C (undocumented) */
 static bool ignoreindent;      /* -I: ignore indentation in C */
 static bool packages_only;     /* --packages-only: in Ada, only tag packages*/
 
@@ -615,10 +614,19 @@ followed by a colon, are tags.";
 
 
 /* Note that .c and .h can be considered C++, if the --c++ flag was
-   given, or if the `class' or `template' keyowrds are met inside the file.
+   given, or if the `class' or `template' keywords are met inside the file.
    That is why default_C_entries is called for these. */
 static char *default_C_suffixes [] =
   { "c", "h", NULL };
+#if CTAGS                              /* C help for Ctags */
+static char default_C_help [] =
+"In C code, any C function is a tag.  Use -t to tag typedefs.\n\
+Use -T to tag definitions of `struct', `union' and `enum'.\n\
+Use -d to tag `#define' macro definitions and `enum' constants.\n\
+Use --globals to tag global variables.\n\
+You can tag function declarations and external variables by\n\
+using `--declarations', and struct members by using `--members'.";
+#else                                  /* C help for Etags */
 static char default_C_help [] =
 "In C code, any C function or typedef is a tag, and so are\n\
 definitions of `struct', `union' and `enum'.  `#define' macro\n\
@@ -629,6 +637,7 @@ definitions and `enum' constants are tags unless you specify\n\
 `--no-members' can make the tags table file much smaller.\n\
 You can tag function declarations and external variables by\n\
 using `--declarations'.";
+#endif /* C help for Ctags and Etags */
 
 static char *Cplusplus_suffixes [] =
   { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
@@ -883,13 +892,13 @@ etags --help --lang=ada.");
 # define EMACS_NAME "standalone"
 #endif
 #ifndef VERSION
-# define VERSION "17.34"
+# define VERSION "17.38.1.3"
 #endif
 static void
 print_version ()
 {
   /* Makes it easier to update automatically. */
-  char emacs_copyright[] = "Copyright (C) 2007 Free Software Foundation, Inc.";
+  char emacs_copyright[] = "Copyright (C) 2008 Free Software Foundation, Inc.";
 
   printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
   puts (emacs_copyright);
@@ -1080,131 +1089,6 @@ Relative ones are stored relative to the output file's directory.\n");
 }
 
 \f
-#ifdef VMS                     /* VMS specific functions */
-
-#define        EOS     '\0'
-
-/* This is a BUG!  ANY arbitrary limit is a BUG!
-   Won't someone please fix this?  */
-#define        MAX_FILE_SPEC_LEN       255
-typedef struct {
-  short   curlen;
-  char    body[MAX_FILE_SPEC_LEN + 1];
-} vspec;
-
-/*
- v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
- returning in each successive call the next file name matching the input
- spec. The function expects that each in_spec passed
- to it will be processed to completion; in particular, up to and
- including the call following that in which the last matching name
- is returned, the function ignores the value of in_spec, and will
- only start processing a new spec with the following call.
- If an error occurs, on return out_spec contains the value
- of in_spec when the error occurred.
-
- With each successive file name returned in out_spec, the
- function's return value is one. When there are no more matching
- names the function returns zero. If on the first call no file
- matches in_spec, or there is any other error, -1 is returned.
-*/
-
-#include       <rmsdef.h>
-#include       <descrip.h>
-#define                OUTSIZE MAX_FILE_SPEC_LEN
-static short
-fn_exp (out, in)
-     vspec *out;
-     char *in;
-{
-  static long context = 0;
-  static struct dsc$descriptor_s o;
-  static struct dsc$descriptor_s i;
-  static bool pass1 = TRUE;
-  long status;
-  short retval;
-
-  if (pass1)
-    {
-      pass1 = FALSE;
-      o.dsc$a_pointer = (char *) out;
-      o.dsc$w_length = (short)OUTSIZE;
-      i.dsc$a_pointer = in;
-      i.dsc$w_length = (short)strlen(in);
-      i.dsc$b_dtype = DSC$K_DTYPE_T;
-      i.dsc$b_class = DSC$K_CLASS_S;
-      o.dsc$b_dtype = DSC$K_DTYPE_VT;
-      o.dsc$b_class = DSC$K_CLASS_VS;
-    }
-  if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
-    {
-      out->body[out->curlen] = EOS;
-      return 1;
-    }
-  else if (status == RMS$_NMF)
-    retval = 0;
-  else
-    {
-      strcpy(out->body, in);
-      retval = -1;
-    }
-  lib$find_file_end(&context);
-  pass1 = TRUE;
-  return retval;
-}
-
-/*
-  v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
-  name of each file specified by the provided arg expanding wildcards.
-*/
-static char *
-gfnames (arg, p_error)
-     char *arg;
-     bool *p_error;
-{
-  static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
-
-  switch (fn_exp (&filename, arg))
-    {
-    case 1:
-      *p_error = FALSE;
-      return filename.body;
-    case 0:
-      *p_error = FALSE;
-      return NULL;
-    default:
-      *p_error = TRUE;
-      return filename.body;
-    }
-}
-
-#ifndef OLD  /* Newer versions of VMS do provide `system'.  */
-system (cmd)
-     char *cmd;
-{
-  error ("%s", "system() function not implemented under VMS");
-}
-#endif
-
-#define        VERSION_DELIM   ';'
-char *massage_name (s)
-     char *s;
-{
-  char *start = s;
-
-  for ( ; *s; s++)
-    if (*s == VERSION_DELIM)
-      {
-       *s = EOS;
-       break;
-      }
-    else
-      *s = lowcase (*s);
-  return start;
-}
-#endif /* VMS */
-
-\f
 int
 main (argc, argv)
      int argc;
@@ -1217,9 +1101,6 @@ main (argc, argv)
   int current_arg, file_count;
   linebuffer filename_lb;
   bool help_asked = FALSE;
-#ifdef VMS
-  bool got_err;
-#endif
  char *optstring;
  int opt;
 
@@ -1239,15 +1120,12 @@ main (argc, argv)
   argbuffer = xnew (argc, argument);
 
   /*
-   * If etags, always find typedefs and structure tags.  Why not?
+   * Always find typedefs and structure tags.
    * Also default to find macro constants, enum constants, struct
-   * members and global variables.
+   * members and global variables.  Do it for both etags and ctags.
    */
-  if (!CTAGS)
-    {
-      typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
-      globals = members = TRUE;
-    }
+  typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
+  globals = members = TRUE;
 
   /* When the optstring begins with a '-' getopt_long does not rearrange the
      non-options arguments to be at the end, but leaves them alone. */
@@ -1386,7 +1264,10 @@ main (argc, argv)
       || strneq (tagfile, "/dev/", 5))
     tagfiledir = cwd;
   else
-    tagfiledir = absolute_dirname (tagfile, cwd);
+    {
+      canonicalize_filename (tagfile);
+      tagfiledir = absolute_dirname (tagfile, cwd);
+    }
 
   init ();                     /* set up boolean "functions" */
 
@@ -1430,21 +1311,7 @@ main (argc, argv)
          analyse_regex (argbuffer[i].what);
          break;
        case at_filename:
-#ifdef VMS
-         while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
-           {
-             if (got_err)
-               {
-                 error ("can't find file %s\n", this_file);
-                 argc--, argv++;
-               }
-             else
-               {
-                 this_file = massage_name (this_file);
-               }
-#else
              this_file = argbuffer[i].what;
-#endif
              /* Input file named "-" means read file names from stdin
                 (one per line) and use them. */
              if (streq (this_file, "-"))
@@ -1457,9 +1324,6 @@ main (argc, argv)
                }
              else
                process_file_name (this_file, lang);
-#ifdef VMS
-           }
-#endif
          break;
         case at_stdin:
           this_file = argbuffer[i].what;
@@ -1498,6 +1362,7 @@ main (argc, argv)
       exit (EXIT_SUCCESS);
     }
 
+  /* From here on, we are in (CTAGS && !cxref_style) */
   if (update)
     {
       char cmd[BUFSIZ];
@@ -1558,7 +1423,7 @@ get_compressor_from_suffix (file, 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, '.');
@@ -1787,8 +1652,8 @@ process_file_name (file, lang)
     pfatal (file);
 
  cleanup:
-  if (compressed_name) free (compressed_name);
-  if (uncompressed_name) free (uncompressed_name);
+  free (compressed_name);
+  free (uncompressed_name);
   last_node = NULL;
   curfdp = NULL;
   return;
@@ -2167,8 +2032,7 @@ free_tree (np)
     {
       register node *node_right = np->right;
       free_tree (np->left);
-      if (np->name != NULL)
-       free (np->name);
+      free (np->name);
       free (np->regex);
       free (np);
       np = node_right;
@@ -2183,11 +2047,11 @@ static void
 free_fdesc (fdp)
      register fdesc *fdp;
 {
-  if (fdp->infname != NULL) free (fdp->infname);
-  if (fdp->infabsname != NULL) free (fdp->infabsname);
-  if (fdp->infabsdir != NULL) free (fdp->infabsdir);
-  if (fdp->taggedfname != NULL) free (fdp->taggedfname);
-  if (fdp->prop != NULL) free (fdp->prop);
+  free (fdp->infname);
+  free (fdp->infabsname);
+  free (fdp->infabsdir);
+  free (fdp->taggedfname);
+  free (fdp->prop);
   free (fdp);
 }
 
@@ -2486,6 +2350,7 @@ while,            0,                      st_C_ignore
 switch,                0,                      st_C_ignore
 return,                0,                      st_C_ignore
 __attribute__, 0,                      st_C_attribute
+GTY,            0,                      st_C_attribute
 @interface,    0,                      st_C_objprot
 @protocol,     0,                      st_C_objprot
 @implementation,0,                     st_C_objimpl
@@ -2549,9 +2414,9 @@ hash (str, len)
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
       35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-      35, 35, 35, 35, 35, 35, 35, 35, 35, 15,
-      14, 35, 35, 35, 35, 35, 35, 35, 14, 35,
-      35, 35, 35, 12, 13, 35, 35, 35, 35, 12,
+      35, 35, 35, 35, 35, 35, 35, 35, 35,  3,
+      26, 35, 35, 35, 35, 35, 35, 35, 27, 35,
+      35, 35, 35, 24,  0, 35, 35, 35, 35,  0,
       35, 35, 35, 35, 35,  1, 35, 16, 35,  6,
       23,  0,  0, 35, 22,  0, 35, 35,  5,  0,
        0, 15,  1, 35,  6, 35,  8, 19, 35, 16,
@@ -2591,7 +2456,7 @@ in_word_set (str, len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 32,
+      TOTAL_KEYWORDS = 33,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 15,
       MIN_HASH_VALUE = 2,
@@ -2602,7 +2467,7 @@ in_word_set (str, len)
     {
       {""}, {""},
       {"if",           0,                      st_C_ignore},
-      {""},
+      {"GTY",           0,                      st_C_attribute},
       {"@end",         0,                      st_C_objend},
       {"union",                0,                      st_C_struct},
       {"define",               0,                      st_C_define},
@@ -2831,8 +2696,7 @@ popclass_above (bracelev)
        nl >= 0 && cstack.bracelev[nl] >= bracelev;
        nl--)
     {
-      if (cstack.cname[nl] != NULL)
-       free (cstack.cname[nl]);
+      free (cstack.cname[nl]);
       cstack.nl = nl;
     }
 }
@@ -3006,11 +2870,6 @@ consider_token (str, len, c, c_extp, bracelev, parlev, is_func_or_var)
        return TRUE;
      }
 
-   /*
-    * This structdef business is NOT invoked when we are ctags and the
-    * file is plain C.  This is because a struct tag may have the same
-    * name as another tag, and this loses with ctags.
-    */
    switch (toktype)
      {
      case st_C_javastruct:
@@ -3246,16 +3105,16 @@ make_C_tag (isfun)
 {
   /* This function is never called when token.valid is FALSE, but
      we must protect against invalid input or internal errors. */
-  if (!DEBUG && !token.valid)
-    return;
-
   if (token.valid)
     make_tag (token_name.buffer, token_name.len, isfun, token.line,
              token.offset+token.length+1, token.lineno, token.linepos);
-  else                         /* this case is optimised away if !DEBUG */
-    make_tag (concat ("INVALID TOKEN:-->", token_name.buffer, ""),
-             token_name.len + 17, isfun, token.line,
-             token.offset+token.length+1, token.lineno, token.linepos);
+  else if (DEBUG)
+    {                            /* this branch is optimised away if !DEBUG */
+      make_tag (concat ("INVALID TOKEN:-->", token_name.buffer, ""),
+               token_name.len + 17, isfun, token.line,
+               token.offset+token.length+1, token.lineno, token.linepos);
+      error ("INVALID TOKEN", NULL);
+    }
 
   token.valid = FALSE;
 }
@@ -3978,7 +3837,7 @@ C_entries (c_ext, inf)
              make_C_tag (FALSE);  /* a struct or enum */
              break;
            }
-         bracelev++;
+         bracelev += 1;
          break;
        case '*':
          if (definedef != dnone)
@@ -3992,23 +3851,21 @@ C_entries (c_ext, inf)
        case '}':
          if (definedef != dnone)
            break;
+         bracelev -= 1;
          if (!ignoreindent && lp == newlb.buffer + 1)
            {
              if (bracelev != 0)
-               token.valid = FALSE;
+               token.valid = FALSE; /* unexpected value, token unreliable */
              bracelev = 0;     /* reset brace level if first column */
              parlev = 0;       /* also reset paren level, just in case... */
            }
-         else
+         else if (bracelev < 0)
            {
-             if (--bracelev < 0)
-               {
-                 bracelev = 0;
-                 token.valid = FALSE; /* something gone amiss, token unreliable */
-               }
-             if (bracelev == 0 && fvdef == vignore)
-               fvdef = fvnone;         /* end of function */
+             token.valid = FALSE; /* something gone amiss, token unreliable */
+             bracelev = 0;
            }
+         if (bracelev == 0 && fvdef == vignore)
+           fvdef = fvnone;             /* end of function */
          popclass_above (bracelev);
          structdef = snone;
          /* Only if typdef == tinbody is typdefbracelev significant. */
@@ -4544,7 +4401,7 @@ Perl_functions (inf)
 
   LOOP_ON_INPUT_LINES (inf, lb, cp)
     {
-      skip_spaces(cp);
+      cp = skip_spaces (cp);
 
       if (LOOKING_AT (cp, "package"))
        {
@@ -5515,8 +5372,7 @@ Prolog_functions (inf)
          last[len] = '\0';
        }
     }
-  if (last != NULL)
-    free (last);
+  free (last);
 }
 
 
@@ -5694,8 +5550,7 @@ Erlang_functions (inf)
          last[len] = '\0';
        }
     }
-  if (last != NULL)
-    free (last);
+  free (last);
 }
 
 
@@ -6369,7 +6224,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))
@@ -6872,7 +6727,6 @@ absolute_dirname (file, dir)
   char *slashp, *res;
   char save;
 
-  canonicalize_filename (file);
   slashp = etags_strrchr (file, '/');
   if (slashp == NULL)
     return savestr (dir);
@@ -6897,27 +6751,38 @@ 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;
 {
+  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;