]> code.delx.au - gnu-emacs/blobdiff - lib-src/etags.c
Fix Lua tags when a function name includes '.' or ':'
[gnu-emacs] / lib-src / etags.c
index 73dd5a8a405164675dd8401a79eaa14e9f3d72ea..5f985b027b22ce5e0b93b46a1e673d8c85bd21bf 100644 (file)
@@ -150,10 +150,29 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
 # 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), !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))
+static bool
+streq (char const *s, char const *t)
+{
+  return strcmp (s, t) == 0;
+}
+
+static bool
+strcaseeq (char const *s, char const *t)
+{
+  return c_strcasecmp (s, t) == 0;
+}
+
+static bool
+strneq (char const *s, char const *t, size_t n)
+{
+  return strncmp (s, t, n) == 0;
+}
+
+static bool
+strncaseeq (char const *s, char const *t, size_t n)
+{
+  return c_strncasecmp (s, t, n) == 0;
+}
 
 /* C is not in a name.  */
 static bool
@@ -361,8 +380,9 @@ static void analyze_regex (char *);
 static void free_regexps (void);
 static void regex_tag_multiline (void);
 static void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
+static void verror (char const *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
 static _Noreturn void suggest_asking_for_help (void);
-_Noreturn void fatal (const char *, const char *);
+static _Noreturn void fatal (char const *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
 static _Noreturn void pfatal (const char *);
 static void add_node (node *, node **);
 
@@ -515,7 +535,7 @@ static const char *Ada_suffixes [] =
   { "ads", "adb", "ada", NULL };
 static const char Ada_help [] =
 "In Ada code, functions, procedures, packages, tasks and types are\n\
-tags.  Use the `--packages-only' option to create tags for\n\
+tags.  Use the '--packages-only' option to create tags for\n\
 packages only.\n\
 Ada tag names have suffixes indicating the type of entity:\n\
        Entity type:    Qualifier:\n\
@@ -526,9 +546,9 @@ Ada tag names have suffixes indicating the type of entity:\n\
        package body    /b\n\
        type            /t\n\
        task            /k\n\
-Thus, `M-x find-tag <RET> bidule/b <RET>' will go directly to the\n\
-body of the package `bidule', while `M-x find-tag <RET> bidule <RET>'\n\
-will just search for any tag `bidule'.";
+Thus, 'M-x find-tag <RET> bidule/b <RET>' will go directly to the\n\
+body of the package 'bidule', while 'M-x find-tag <RET> bidule <RET>'\n\
+will just search for any tag 'bidule'.";
 
 /* Assembly code */
 static const char *Asm_suffixes [] =
@@ -555,22 +575,22 @@ static const char *default_C_suffixes [] =
 #if CTAGS                              /* C help for Ctags */
 static const 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 -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'.";
+using '--declarations', and struct members by using '--members'.";
 #else                                  /* C help for Etags */
 static const 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\
-definitions and `enum' constants are tags unless you specify\n\
-`--no-defines'.  Global variables are tags unless you specify\n\
-`--no-globals' and so are struct members unless you specify\n\
-`--no-members'.  Use of `--no-globals', `--no-defines' and\n\
-`--no-members' can make the tags table file much smaller.\n\
+definitions of 'struct', 'union' and 'enum'.  '#define' macro\n\
+definitions and 'enum' constants are tags unless you specify\n\
+'--no-defines'.  Global variables are tags unless you specify\n\
+'--no-globals' and so are struct members unless you specify\n\
+'--no-members'.  Use of '--no-globals', '--no-defines' and\n\
+'--no-members' can make the tags table file much smaller.\n\
 You can tag function declarations and external variables by\n\
-using `--declarations'.";
+using '--declarations'.";
 #endif /* C help for Ctags and Etags */
 
 static const char *Cplusplus_suffixes [] =
@@ -582,10 +602,10 @@ static const char Cplusplus_help [] =
 "In C++ code, all the tag constructs of C code are tagged.  (Use\n\
 --help --lang=c --lang=c++ for full help.)\n\
 In addition to C tags, member functions are also recognized.  Member\n\
-variables are recognized unless you use the `--no-members' option.\n\
-Tags for variables and functions in classes are named `CLASS::VARIABLE'\n\
-and `CLASS::FUNCTION'.  `operator' definitions have tag names like\n\
-`operator+'.";
+variables are recognized unless you use the '--no-members' option.\n\
+Tags for variables and functions in classes are named 'CLASS::VARIABLE'\n\
+and 'CLASS::FUNCTION'.  'operator' definitions have tag names like\n\
+'operator+'.";
 
 static const char *Cjava_suffixes [] =
   { "java", NULL };
@@ -612,7 +632,7 @@ defined in the file.";
 const char *Forth_suffixes [] =
   { "fth", "tok", NULL };
 static const char Forth_help [] =
-"In Forth code, tags are words defined by `:',\n\
+"In Forth code, tags are words defined by ':',\n\
 constant, code, create, defer, value, variable, buffer:, field.";
 
 static const char *Fortran_suffixes [] =
@@ -623,18 +643,18 @@ static const char Fortran_help [] =
 static const char *HTML_suffixes [] =
   { "htm", "html", "shtml", NULL };
 static const char HTML_help [] =
-"In HTML input files, the tags are the `title' and the `h1', `h2',\n\
-`h3' headers.  Also, tags are `name=' in anchors and all\n\
-occurrences of `id='.";
+"In HTML input files, the tags are the 'title' and the 'h1', 'h2',\n\
+'h3' headers.  Also, tags are 'name=' in anchors and all\n\
+occurrences of 'id='.";
 
 static const char *Lisp_suffixes [] =
   { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
 static const char Lisp_help [] =
-"In Lisp code, any function defined with `defun', any variable\n\
-defined with `defvar' or `defconst', and in general the first\n\
-argument of any expression that starts with `(def' in column zero\n\
+"In Lisp code, any function defined with 'defun', any variable\n\
+defined with 'defvar' or 'defconst', and in general the first\n\
+argument of any expression that starts with '(def' in column zero\n\
 is a tag.\n\
-The `--declarations' option tags \"(defvar foo)\" constructs too.";
+The '--declarations' option tags \"(defvar foo)\" constructs too.";
 
 static const char *Lua_suffixes [] =
   { "lua", "LUA", NULL };
@@ -645,7 +665,7 @@ static const char *Makefile_filenames [] =
   { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};
 static const char Makefile_help [] =
 "In makefiles, targets are tags; additionally, variables are tags\n\
-unless you specify `--no-globals'.";
+unless you specify '--no-globals'.";
 
 static const char *Objc_suffixes [] =
   { "lm",                      /* Objective lex file */
@@ -654,7 +674,7 @@ static const char *Objc_suffixes [] =
 static const char Objc_help [] =
 "In Objective C code, tags include Objective C definitions for classes,\n\
 class categories, methods and protocols.  Tags for variables and\n\
-functions in classes are named `CLASS::VARIABLE' and `CLASS::FUNCTION'.\n\
+functions in classes are named 'CLASS::VARIABLE' and 'CLASS::FUNCTION'.\n\
 (Use --help --lang=c --lang=objc --lang=java for full help.)";
 
 static const char *Pascal_suffixes [] =
@@ -670,16 +690,16 @@ static const char *Perl_interpreters [] =
   { "perl", "@PERL@", NULL };
 static const char Perl_help [] =
 "In Perl code, the tags are the packages, subroutines and variables\n\
-defined by the `package', `sub', `my' and `local' keywords.  Use\n\
-`--globals' if you want to tag global variables.  Tags for\n\
-subroutines are named `PACKAGE::SUB'.  The name for subroutines\n\
-defined in the default package is `main::SUB'.";
+defined by the 'package', 'sub', 'my' and 'local' keywords.  Use\n\
+'--globals' if you want to tag global variables.  Tags for\n\
+subroutines are named 'PACKAGE::SUB'.  The name for subroutines\n\
+defined in the default package is 'main::SUB'.";
 
 static const char *PHP_suffixes [] =
   { "php", "php3", "php4", NULL };
 static const char PHP_help [] =
 "In PHP code, tags are functions, classes and defines.  Unless you use\n\
-the `--no-members' option, vars are tags too.";
+the '--no-members' option, vars are tags too.";
 
 static const char *plain_C_suffixes [] =
   { "pc",                      /* Pro*C file */
@@ -699,28 +719,28 @@ line.";
 static const char *Python_suffixes [] =
   { "py", NULL };
 static const char Python_help [] =
-"In Python code, `def' or `class' at the beginning of a line\n\
+"In Python code, 'def' or 'class' at the beginning of a line\n\
 generate a tag.";
 
 /* Can't do the `SCM' or `scm' prefix with a version number. */
 static const char *Scheme_suffixes [] =
   { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };
 static const char Scheme_help [] =
-"In Scheme code, tags include anything defined with `def' or with a\n\
-construct whose name starts with `def'.  They also include\n\
-variables set with `set!' at top level in the file.";
+"In Scheme code, tags include anything defined with 'def' or with a\n\
+construct whose name starts with 'def'.  They also include\n\
+variables set with 'set!' at top level in the file.";
 
 static const char *TeX_suffixes [] =
   { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };
 static const char TeX_help [] =
-"In LaTeX text, the argument of any of the commands `\\chapter',\n\
-`\\section', `\\subsection', `\\subsubsection', `\\eqno', `\\label',\n\
-`\\ref', `\\cite', `\\bibitem', `\\part', `\\appendix', `\\entry',\n\
-`\\index', `\\def', `\\newcommand', `\\renewcommand',\n\
-`\\newenvironment' or `\\renewenvironment' is a tag.\n\
+"In LaTeX text, the argument of any of the commands '\\chapter',\n\
+'\\section', '\\subsection', '\\subsubsection', '\\eqno', '\\label',\n\
+'\\ref', '\\cite', '\\bibitem', '\\part', '\\appendix', '\\entry',\n\
+'\\index', '\\def', '\\newcommand', '\\renewcommand',\n\
+'\\newenvironment' or '\\renewenvironment' is a tag.\n\
 \n\
 Other commands can be specified by setting the environment variable\n\
-`TEXTAGS' to a colon-separated list like, for example,\n\
+'TEXTAGS' to a colon-separated list like, for example,\n\
      TEXTAGS=\"mycommand:myothercommand\".";
 
 
@@ -738,11 +758,11 @@ C code are parsed as C code (use --help --lang=c --lang=yacc\n\
 for full help).";
 
 static const char auto_help [] =
-"`auto' is not a real language, it indicates to use\n\
+"'auto' is not a real language, it indicates to use\n\
 a default language for files base on file name suffix and file contents.";
 
 static const char none_help [] =
-"`none' is not a real language, it indicates to only do\n\
+"'none' is not a real language, it indicates to only do\n\
 regexp processing on files.";
 
 static const char no_lang_help [] =
@@ -809,8 +829,8 @@ default file names and dot suffixes:");
          printf (" .%s", *ext);
       puts ("");
     }
-  puts ("where `auto' means use default language for files based on file\n\
-name suffix, and `none' means only do regexp processing on files.\n\
+  puts ("where 'auto' means use default language for files based on file\n\
+name suffix, and 'none' means only do regexp processing on files.\n\
 If no language is specified and no matching suffix is found,\n\
 the first line of the file is read for a sharp-bang (#!) sequence\n\
 followed by the name of an interpreter.  If no such sequence is found,\n\
@@ -950,8 +970,8 @@ Relative ones are stored relative to the output file's directory.\n");
   puts ("      If TAGNAME/ is present, the tags created are named.\n\
        For example Tcl named tags can be created with:\n\
          --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
-       MODS are optional one-letter modifiers: `i' means to ignore case,\n\
-       `m' means to allow multi-line matches, `s' implies `m' and\n\
+       MODS are optional one-letter modifiers: 'i' means to ignore case,\n\
+       'm' means to allow multi-line matches, 's' implies 'm' and\n\
        causes dot to match any character, including newline.");
 
   puts ("-R, --no-regex\n\
@@ -1012,7 +1032,7 @@ Relative ones are stored relative to the output file's directory.\n");
         Print the version of the program.\n\
 -h, --help\n\
         Print this help message.\n\
-        Followed by one or more `--language' options prints detailed\n\
+        Followed by one or more '--language' options prints detailed\n\
         help about tag generation for the specified languages.");
 
   print_language_names ();
@@ -1091,7 +1111,7 @@ main (int argc, char **argv)
        ++current_arg;
        ++file_count;
        if (parsing_stdin)
-         fatal ("cannot parse standard input more than once", (char *)NULL);
+         fatal ("cannot parse standard input more than once");
        parsing_stdin = true;
        break;
 
@@ -1255,8 +1275,8 @@ main (int argc, char **argv)
              if (streq (this_file, "-"))
                {
                  if (parsing_stdin)
-                   fatal ("cannot parse standard input AND read file names from it",
-                          (char *)NULL);
+                   fatal ("cannot parse standard input "
+                          "AND read file names from it");
                  while (readline_internal (&filename_lb, stdin, "-") > 0)
                    process_file_name (filename_lb.buffer, lang);
                }
@@ -1267,6 +1287,8 @@ main (int argc, char **argv)
           this_file = argbuffer[i].what;
           process_file (stdin, this_file, lang);
           break;
+       default:
+         error ("internal error: arg_type");
        }
     }
 
@@ -1324,7 +1346,7 @@ main (int argc, char **argv)
          z = stpcpy (z, tagfile);
          strcpy (z, ";rm OTAGS");
          if (system (cmd) != EXIT_SUCCESS)
-           fatal ("failed to execute shell command", (char *)NULL);
+           fatal ("failed to execute shell command");
        }
       free (cmd);
       append_to_tagfile = true;
@@ -2753,6 +2775,9 @@ consider_token (char *str, int len, int c, int *c_extp,
         case st_C_struct:
         case st_C_enum:
           typdef = ttypeseen;
+          break;
+        default:
+          break;
         }
        break;
      case ttypeseen:
@@ -2769,8 +2794,11 @@ consider_token (char *str, int len, int c, int *c_extp,
         case st_C_struct:
         case st_C_enum:
           return false;
+        default:
+          return true;
         }
-       return true;
+     default:
+       break;
      }
 
    switch (toktype)
@@ -2803,6 +2831,8 @@ consider_token (char *str, int len, int c, int *c_extp,
             fvdef = fvnone;
         }
        return false;
+     default:
+       break;
      }
 
    if (structdef == skeyseen)
@@ -2826,6 +2856,8 @@ consider_token (char *str, int len, int c, int *c_extp,
         case st_C_objimpl:
           objdef = oimplementation;
           return false;
+        default:
+          break;
         }
        break;
      case oimplementation:
@@ -2887,6 +2919,8 @@ consider_token (char *str, int len, int c, int *c_extp,
           objdef = onone;
         }
        return false;
+     default:
+       break;
      }
 
    /* A function, variable or enum constant? */
@@ -2942,6 +2976,8 @@ consider_token (char *str, int len, int c, int *c_extp,
                   return false;
                 }
               break;
+            default:
+              break;
             }
          /* FALLTHRU */
          case fvnameseen:
@@ -2958,8 +2994,12 @@ consider_token (char *str, int len, int c, int *c_extp,
          fvdef = fvnameseen;   /* function or variable */
          *is_func_or_var = true;
          return true;
+        default:
+          break;
        }
       break;
+     default:
+       break;
     }
 
   return false;
@@ -3355,7 +3395,7 @@ C_entries (int c_ext, FILE *inf)
                                {
                                  linebuffer_setlen (&token_name, toklen);
                                  sprintf (token_name.buffer, "%.*s",
-                                          newlb.buffer + tokoff);
+                                          toklen, newlb.buffer + tokoff);
                                }
                              token.named = true;
                            }
@@ -3469,6 +3509,8 @@ C_entries (int c_ext, FILE *inf)
                          fvdef = fignore;
                        }
                      break;
+                   default:
+                     break;
                    }
                  if (structdef == stagseen && !cjava)
                    {
@@ -3479,6 +3521,8 @@ C_entries (int c_ext, FILE *inf)
                case dsharpseen:
                  savetoken = token;
                  break;
+               default:
+                 break;
                }
              if (!yacc_rules || lp == newlb.buffer + 1)
                {
@@ -3507,7 +3551,7 @@ C_entries (int c_ext, FILE *inf)
            break;
          switch (objdef)
            {
-           case  otagseen:
+           case otagseen:
              objdef = oignore;
              make_C_tag (true); /* an Objective C class */
              break;
@@ -3521,6 +3565,8 @@ C_entries (int c_ext, FILE *inf)
                  strcpy (token_name.buffer + toklen, ":");
                }
              break;
+           default:
+             break;
            }
          if (structdef == stagseen)
            {
@@ -3598,6 +3644,8 @@ C_entries (int c_ext, FILE *inf)
              make_C_tag (true); /* an Objective C method */
              objdef = oinbody;
              break;
+           default:
+             break;
            }
          switch (fvdef)
            {
@@ -3671,6 +3719,8 @@ C_entries (int c_ext, FILE *inf)
                  fvdef = fvnone;
                }
              break;
+           default:
+             break;
            }
          break;
        case '(':
@@ -3704,6 +3754,8 @@ C_entries (int c_ext, FILE *inf)
            case flistseen:
              fvdef = finlist;
              break;
+           default:
+             break;
            }
          parlev++;
          break;
@@ -3729,6 +3781,8 @@ C_entries (int c_ext, FILE *inf)
                case finlist:
                  fvdef = flistseen;
                  break;
+               default:
+                 break;
                }
              if (!instruct
                  && (typdef == tend
@@ -3800,6 +3854,8 @@ C_entries (int c_ext, FILE *inf)
                    bracelev = -1;
                }
              break;
+           default:
+             break;
            }
          switch (structdef)
            {
@@ -3813,6 +3869,8 @@ C_entries (int c_ext, FILE *inf)
              structdef = snone;
              make_C_tag (false);  /* a struct or enum */
              break;
+           default:
+             break;
            }
          bracelev += 1;
          break;
@@ -4896,7 +4954,22 @@ Lua_functions (FILE *inf)
       (void)LOOKING_AT (bp, "local"); /* skip possible "local" */
 
       if (LOOKING_AT (bp, "function"))
-       get_tag (bp, NULL);
+       {
+         char *tag_name, *tp_dot, *tp_colon;
+
+         get_tag (bp, &tag_name);
+         /* If the tag ends with ".foo" or ":foo", make an additional tag for
+            "foo".  */
+         tp_dot = strrchr (tag_name, '.');
+         tp_colon = strrchr (tag_name, ':');
+         if (tp_dot || tp_colon)
+           {
+             char *p = tp_dot > tp_colon ? tp_dot : tp_colon;
+             int len_add = p - tag_name + 1;
+
+             get_tag (bp + len_add, NULL);
+           }
+       }
     }
 }
 
@@ -5797,7 +5870,7 @@ add_regex (char *regexp_pattern, language *lang)
        need_filebuf = true;
        break;
       default:
-       error ("invalid regexp modifier `%c', ignoring", modifiers[0]);
+       error ("invalid regexp modifier '%c', ignoring", modifiers[0]);
        break;
       }
 
@@ -6075,16 +6148,7 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
          if (p > buffer && p[-1] == '\r')
            {
              p -= 1;
-#ifdef DOS_NT
-            /* Assume CRLF->LF translation will be performed by Emacs
-               when loading this file, so CRs won't appear in the buffer.
-               It would be cleaner to compensate within Emacs;
-               however, Emacs does not know how many CRs were deleted
-               before any given point in the file.  */
-             chars_deleted = 1;
-#else
              chars_deleted = 2;
-#endif
            }
          else
            {
@@ -6360,10 +6424,13 @@ skip_name (char *cp)
 }
 
 /* Print error message and exit.  */
-void
-fatal (const char *s1, const char *s2)
+static void
+fatal (char const *format, ...)
 {
-  error (s1, s2);
+  va_list ap;
+  va_start (ap, format);
+  verror (format, ap);
+  va_end (ap);
   exit (EXIT_FAILURE);
 }
 
@@ -6377,7 +6444,7 @@ pfatal (const char *s1)
 static void
 suggest_asking_for_help (void)
 {
-  fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
+  fprintf (stderr, "\tTry '%s --help' for a complete list of options.\n",
           progname);
   exit (EXIT_FAILURE);
 }
@@ -6388,10 +6455,16 @@ error (const char *format, ...)
 {
   va_list ap;
   va_start (ap, format);
+  verror (format, ap);
+  va_end (ap);
+}
+
+static void
+verror (char const *format, va_list ap)
+{
   fprintf (stderr, "%s: ", progname);
   vfprintf (stderr, format, ap);
   fprintf (stderr, "\n");
-  va_end (ap);
 }
 
 /* Return a newly-allocated string whose contents
@@ -6682,7 +6755,7 @@ xmalloc (size_t size)
 {
   void *result = malloc (size);
   if (result == NULL)
-    fatal ("virtual memory exhausted", (char *)NULL);
+    fatal ("virtual memory exhausted");
   return result;
 }
 
@@ -6691,7 +6764,7 @@ xrealloc (void *ptr, size_t size)
 {
   void *result = realloc (ptr, size);
   if (result == NULL)
-    fatal ("virtual memory exhausted", (char *)NULL);
+    fatal ("virtual memory exhausted");
   return result;
 }