(describe-current-display-table):
[bpt/emacs.git] / lib-src / etags.c
index 4276c59..3057800 100644 (file)
@@ -24,10 +24,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  *     Ed Pelegri-Llopart added C typedefs.
  *     Gnu Emacs TAGS format and modifications by RMS?
  *     Sam Kendall added C++.
+ *
+ *     Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 9.7
  */
 
 #ifdef HAVE_CONFIG_H
-#include "../src/config.h"
+#include <../src/config.h>
 #endif
 
 #include <stdio.h>
@@ -35,6 +37,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#if !defined (S_ISREG) && defined (S_IFREG)
+# define S_ISREG(m)    (((m) & S_IFMT) == S_IFREG)
+#endif
+
 #include "getopt.h"
 
 extern char *malloc (), *realloc ();
@@ -136,7 +142,7 @@ struct nd_st
   char *name;                  /* function or type name        */
   char *file;                  /* file name                    */
   logical is_func;             /* use pattern or line no       */
-  logical rewritten;           /* list name separately         */
+  logical named;               /* list name separately         */
   logical been_warned;         /* set if noticed dup           */
   int lno;                     /* line number tag is on        */
   long cno;                    /* character number line starts on */
@@ -157,7 +163,7 @@ char *savenstr ();
 char *savestr ();
 char *xmalloc ();
 char *xrealloc ();
-int L_isdef ();
+int L_isdef (), L_isquote ();
 int PF_funcs ();
 int total_size_of_entries ();
 logical consider_token ();
@@ -324,7 +330,7 @@ typedef struct
   char *p;
   int len;
   LINENO lineno;
-  logical rewritten;
+  logical named;
 } TOKEN;
 
 /* C extensions.
@@ -430,7 +436,7 @@ print_version ()
 #ifdef ETAGS
   printf ("ETAGS ");
 #endif
-  printf ("for Emacs version 19.0.\n");
+  printf ("for Emacs version 19.\n");
 
   exit (0);
 }
@@ -441,14 +447,13 @@ print_help ()
   printf ("These are the options accepted by %s.  You may use unambiguous\n\
 abbreviations for the long option names.\n\n", progname);
 
-  fputs ("\
--a, --append\n\
-        Append tag entries to existing tags file.\n\
--C, --c++\n\
+  puts ("-a, --append\n\
+        Append tag entries to existing tags file.");
+  puts ("-C, --c++\n\
         Treat files with `.c' and `.h' extensions as C++ code, not C\n\
         code.  Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
-        extensions are always assumed to be C++ code.\n\
--d, --defines\n\
+        extensions are always assumed to be C++ code.");
+  fputs ("-d, --defines\n\
         Create tag entries for #defines, too.", stdout);
 
 #ifdef ETAGS
@@ -472,11 +477,11 @@ abbreviations for the long option names.\n\n", progname);
         Don't rely on indentation quite as much as normal.  Currently,\n\
         this means not to assume that a closing brace in the first\n\
         column is the final brace of a function or structure\n\
-        definition.\n\
--t, --typedefs\n\
+        definition.");
+  puts ("-t, --typedefs\n\
         Generate tag entries for typedefs.  This is the default\n\
-        behavior.\n\
--T, --typedefs-and-c++\n\
+        behavior.");
+  puts ("-T, --typedefs-and-c++\n\
         Generate tag entries for typedefs, struct/enum/union tags, and\n\
         C++ member functions.");
 
@@ -490,27 +495,27 @@ abbreviations for the long option names.\n\n", progname);
 #ifdef CTAGS
   puts ("-B, --backward-search\n\
         Write the search commands for the tag entries using '?', the\n\
-        backward-search command.\n\
--F, --forward-search\n\
+        backward-search command.");
+  puts ("-F, --forward-search\n\
         Write the search commands for the tag entries using '/', the\n\
-        forward-search command.\n\
--u, --update\n\
+        forward-search command.");
+  puts ("-u, --update\n\
         Update the tag entries for the given files, leaving tag\n\
         entries for other files in place.  Currently, this is\n\
         implemented by deleting the existing entries for the given\n\
         files and then rewriting the new entries at the end of the\n\
         tags file.  It is often faster to simply rebuild the entire\n\
-        tag file than to use this.\n\
--v, --vgrind\n\
+        tag file than to use this.");
+  puts ("-v, --vgrind\n\
         Generates an index of items intended for human consumption,\n\
         similar to the output of vgrind.  The index is sorted, and\n\
-        gives the page number of each item.\n\
--x, --cxref\n\
+        gives the page number of each item.");
+  puts ("-x, --cxref\n\
         Like --vgrind, but in the style of cxref, rather than vgrind.\n\
         The output uses line numbers instead of page numbers, but\n\
         beyond that the differences are cosmetic; try both to see\n\
-        which you like.\n\
--w, --no-warn\n\
+        which you like.");
+  puts ("-w, --no-warn\n\
         Suppress warning messages about entries defined in multiple\n\
         files.");
 #endif
@@ -783,12 +788,7 @@ process_file (file)
 {
   struct stat stat_buf;
 
-  stat (file, &stat_buf);
-  if (!(stat_buf.st_mode & S_IFREG)
-#ifdef S_IFLNK
-      || !(stat_buf.st_mode & S_IFLNK)
-#endif
-      )
+  if (stat (file, &stat_buf) || !S_ISREG (stat_buf.st_mode))
     {
       fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
       return;
@@ -799,19 +799,10 @@ process_file (file)
       fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
       return;
     }
-  if (emacs_tags_format)
-    {
-      char *cp = etags_rindex (file, '/');
-      if (cp)
-       ++cp;
-      else
-       cp = file;
-    }
   find_entries (file);
   if (emacs_tags_format)
     {
-      fprintf (outf, "\f\n%s,%d\n",
-              file, total_size_of_entries (head));
+      fprintf (outf, "\f\n%s,%d\n", file, total_size_of_entries (head));
       put_entries (head);
       free_tree (head);
       head = NULL;
@@ -992,10 +983,10 @@ string_numeric_p (str)
 /* Record a tag. */
 /* Should take a TOKEN* instead!! */
 void
-pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
+pfnote (name, is_func, named, linestart, linelen, lno, cno)
      char *name;               /* tag name */
      logical is_func;          /* function or type name? */
-     logical rewritten;                /* tag different from text of definition? */
+     logical named;            /* tag different from text of definition? */
      char *linestart;
      int linelen;
      int lno;
@@ -1030,12 +1021,12 @@ pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
       fp = etags_rindex (name, '.');
       if (fp && fp[1] != '\0' && fp[2] == '\0')
        *fp = 0;
-      rewritten = TRUE;
+      named = TRUE;
     }
   np->name = savestr (name);
   np->file = curfile;
   np->is_func = is_func;
-  np->rewritten = rewritten;
+  np->named = named;
   np->lno = lno;
   /* UNCOMMENT THE +1 HERE: */
   np->cno = cno /* + 1 */ ;    /* our char numbers are 0-base; emacs's are 1-base */
@@ -1173,15 +1164,17 @@ put_entries (node)
 
   if (emacs_tags_format)
     {
-      if (node->rewritten)
+      if (node->named)
        {
          fprintf (outf, "%s\177%s\001%d,%d\n",
-                  node->name, node->pat, node->lno, node->cno);
+                  node->pat, node->name,
+                  node->lno, node->cno);
        }
       else
        {
          fprintf (outf, "%s\177%d,%d\n",
-                  node->pat, node->lno, node->cno);
+                  node->pat,
+                  node->lno, node->cno);
        }
     }
   else if (!cxref_style)
@@ -1256,7 +1249,7 @@ total_size_of_entries (node)
       /* Count this entry */
       total += strlen (node->pat) + 1;
       total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
-      if (node->rewritten)
+      if (node->named)
        total += 1 + strlen (node->name);       /* \001name */
     }
 
@@ -1331,13 +1324,16 @@ C_create_stabs ()
 }
 \f
  /*
-  *    etags.c 4.2 1993/03/22 12:13:40 pot Exp
   * C functions are recognized using a simple finite automaton.
   * funcdef is its state variable.
   */
 typedef enum
 {
-  fnone, ftagseen, finlist, flistseen
+  fnone,                       /* nothing seen */
+  ftagseen,                    /* function-like tag seen */
+  finlist,                     /* in parameter list */
+  flistseen,                   /* after parameter list */
+  fignore,                     /* before open brace */
 } FUNCST;
 FUNCST funcdef;
 
@@ -1347,7 +1343,10 @@ FUNCST funcdef;
   */
 typedef enum
 {
-  tnone, ttypedseen, tinbody, tend
+  tnone,                       /* nothing seen */
+  ttypedseen,                  /* typedef keyword seen */
+  tinbody,                     /* inside typedef body */
+  tend,                                /* just before typedef tag */
 } TYPEDST;
 TYPEDST typdef;
 
@@ -1364,7 +1363,7 @@ typedef enum
   skeyseen,                    /* struct-like keyword seen */
   stagseen,                    /* struct-like tag seen */
   scolonseen,                  /* colon seen after struct-like tag */
-  sinbody                      /* in struct body: recognize member func defs*/
+  sinbody,                     /* in struct body: recognize member func defs*/
 } STRUCTST;
 STRUCTST structdef;
 /*
@@ -1382,7 +1381,7 @@ typedef enum
   dnone,                       /* nothing seen */
   dsharpseen,                  /* '#' seen as first char on line */
   ddefineseen,                 /* '#' and 'define' seen */
-  dignorerest                  /* ignore rest of line */
+  dignorerest,                 /* ignore rest of line */
 } DEFINEST;
 DEFINEST definedef;
 
@@ -1427,9 +1426,9 @@ do {                                                                      \
   definedef = dnone;                                                   \
 } while (FALSE)
 
-#define MAKE_TAG_FROM_NEW_LB(isfun)  pfnote (tokb, isfun, tok.rewritten, \
+#define MAKE_TAG_FROM_NEW_LB(isfun)  pfnote (nameb, isfun, tok.named,  \
   newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
-#define MAKE_TAG_FROM_OTH_LB(isfun)  pfnote (tokb, isfun, tok.rewritten, \
+#define MAKE_TAG_FROM_OTH_LB(isfun)  pfnote (nameb, isfun, tok.named,  \
   othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
 
 void
@@ -1440,7 +1439,7 @@ C_entries (c_ext)
   register char *lp;           /* pointer one beyond the character `c' */
   int curndx, newndx;          /* indices for current and new lb */
   TOKEN tok;                   /* latest token read for funcdef & structdef */
-  char tokb[BUFSIZ];           /* latest token name for funcdef & structdef */
+  char nameb[BUFSIZ];          /* latest token name for funcdef & structdef */
   register int tokoff;         /* offset in line of start of latest token */
   register int toklen;         /* length of latest token */
   int cblev;                   /* current curly brace level */
@@ -1581,30 +1580,36 @@ C_entries (c_ext)
                    }
                  else
                    {
-                     logical is_func;
+                     logical is_func = FALSE;
 
                      tok.lineno = lineno;
                      tok.p = newlb.buffer + tokoff;
                      tok.len = toklen;
-                     tok.rewritten = FALSE;
+                     tok.named = FALSE;
                      if (yacc_rules
                          || consider_token (c, lp, &tok,
                                             c_ext, cblev, &is_func))
                        {
                          if (structdef == sinbody
-                             && definedef == dnone && is_func)
-                           {   /* function defined in C++ class body */
-                             sprintf (tokb, "%s::%.*s",
+                             && definedef == dnone
+                             && is_func)
+                           /* function defined in C++ class body */
+                           {
+                             tok.named = TRUE;
+                             sprintf (nameb, "%s::%.*s",
                                       ((structtag[0] == '\0')
                                        ? "_anonymous_" : structtag),
                                       tok.len, tok.p);
-                             tok.rewritten = TRUE;
                            }
                          else
                            {
-                             sprintf (tokb, "%.*s", tok.len, tok.p);
+                             sprintf (nameb, "%.*s", tok.len, tok.p);
                            }
 
+                         if (structdef == stagseen
+                             || typdef == tend)
+                           tok.named = TRUE;
+
                          if (funcdef == ftagseen
                              || structdef == stagseen
                              || typdef == tend)
@@ -1630,7 +1635,8 @@ C_entries (c_ext)
                {
                case flistseen:
                  MAKE_TAG_FROM_OTH_LB (TRUE);
-                 /* FALLTHRU */
+                 funcdef = fignore;
+                 break;
                case ftagseen:
                  funcdef = fnone;
                  break;
@@ -1658,7 +1664,7 @@ C_entries (c_ext)
          else if (yacc_rules && funcdef == ftagseen)
            {
              MAKE_TAG_FROM_OTH_LB (FALSE);
-             funcdef == fnone;
+             funcdef = fignore;
            }
          break;
        case ';':
@@ -1667,12 +1673,13 @@ C_entries (c_ext)
              typdef = tnone;
              MAKE_TAG_FROM_OTH_LB (FALSE);
            }
-         funcdef = fnone;
+         if (funcdef != fignore)
+           funcdef = fnone;
          /* FALLTHRU */
        case ',':
          /* FALLTHRU */
        case '[':
-         if (funcdef != finlist)
+         if (funcdef != finlist && funcdef != fignore)
            funcdef = fnone;
          if (structdef == stagseen)
            structdef = snone;
@@ -1708,13 +1715,21 @@ C_entries (c_ext)
              MAKE_TAG_FROM_OTH_LB (FALSE);
              break;
            }
+         switch (funcdef)
+           {
+           case flistseen:
+             MAKE_TAG_FROM_OTH_LB (TRUE);
+             /* FALLTHRU */
+           case fignore:
+             funcdef = fnone;
+           }
          cblev++;
-         /* FALLTHRU */
+         break;
        case '*':
          if (funcdef == flistseen)
            {
              MAKE_TAG_FROM_OTH_LB (TRUE);
-             funcdef = fnone;
+             funcdef = fignore;
            }
          break;
        case '}':
@@ -1773,12 +1788,9 @@ consider_token (c, lp, tokp, c_ext, cblev, is_func)
      int cblev;                        /* IN: curly brace level */
      logical *is_func;         /* OUT */
 {
-  logical firsttok;            /* TRUE if have seen first token in ()'s */
   Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
   enum sym_type toktype = stab_type (tokse);
 
-  *is_func = FALSE;            /* not a function */
-
   /*
    * Advance the definedef state machine.
    */
@@ -1919,7 +1931,8 @@ consider_token (c, lp, tokp, c_ext, cblev, is_func)
   if (next_token_is_func)
     {
       next_token_is_func = FALSE;
-      *is_func = TRUE;
+      funcdef = fnone;
+      *is_func = TRUE;         /* to force search string in ctags */
       return (TRUE);
     }
 
@@ -1930,10 +1943,15 @@ consider_token (c, lp, tokp, c_ext, cblev, is_func)
       funcdef = fnone;         /* should be useless */
       return (FALSE);
     default:
-      funcdef = ftagseen;
-      *is_func = TRUE;
-      return (TRUE);
+      if (funcdef == fnone)
+       {
+         funcdef = ftagseen;
+         *is_func = TRUE;
+         return (TRUE);
+       }
     }
+
+  return (FALSE);
 }
 \f
 /* Fortran parsing */
@@ -2342,15 +2360,17 @@ L_funcs (fi)
          else
            {
              /* Check for (foo::defmumble name-defined ... */
-             while (*dbp && *dbp != ':' && !isspace (*dbp)
-                    && *dbp != '(' && *dbp != ')')
+             do
                dbp++;
+             while (*dbp && !isspace (*dbp)
+                    && *dbp != ':' && *dbp != '(' && *dbp != ')');
              if (*dbp == ':')
                {
-                 while (*dbp == ':')
+                 do
                    dbp++;
+                 while (*dbp == ':');
 
-                 if (L_isdef (dbp))
+                 if (L_isdef (dbp - 1))
                    {
                      while (!isspace (*dbp))
                        dbp++;
@@ -2366,11 +2386,23 @@ L_funcs (fi)
 
 int
 L_isdef (dbp)
-     char *dbp;
+     register char *dbp;
 {
-  return ((dbp[1] == 'D' || dbp[1] == 'd') &&
-         (dbp[2] == 'E' || dbp[2] == 'e') &&
-         (dbp[3] == 'F' || dbp[3] == 'f'));
+  return ((dbp[1] == 'd' || dbp[1] == 'D')
+         && (dbp[2] == 'e' || dbp[2] == 'E')
+         && (dbp[3] == 'f' || dbp[3] == 'F'));
+}
+
+int
+L_isquote (dbp)
+     register char *dbp;
+{
+  return ((*(++dbp) == 'q' || *dbp == 'Q')
+         && (*(++dbp) == 'u' || *dbp == 'U')
+         && (*(++dbp) == 'o' || *dbp == 'O')
+         && (*(++dbp) == 't' || *dbp == 'T')
+         && (*(++dbp) == 'e' || *dbp == 'E')
+         && isspace(*(++dbp)));
 }
 
 void
@@ -2380,10 +2412,19 @@ L_getit ()
   char c;
   char nambuf[BUFSIZ];
 
-  if (*dbp == 0)
-    return;
-  for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
+  if (*dbp == '\'')            /* Skip prefix quote */
+    dbp++;
+  else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
+  {
+    dbp += 7;
+    while (isspace(*dbp))
+      dbp++;
+  }
+  for (cp = dbp /*+1*/; *cp && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
     continue;
+  if (cp == dbp)
+    return;
+  
   c = cp[0];
   cp[0] = 0;
   (void) strcpy (nambuf, dbp);
@@ -2734,7 +2775,7 @@ prolog_getit (s, lineno, linecharno)
   *s = '\0';
   strcpy (nambuf, save_s);
   *s = tmpc;
-  pfnote (nambuf, TRUE, save_s, strlen (nambuf), lineno, linecharno);
+  pfnote (nambuf, TRUE, FALSE, save_s, strlen (nambuf), lineno, linecharno);
 }
 
 /* It is assumed that prolog predicate starts from column 0. */