mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-25 10:47:00 +00:00
* etags.c (cwd, outfiledir): vars added.
(relative_filename, absolute_filename, absolute_dirname): functions added to compute filenames in tags files. (process_file): filenames in tags file are relative to the directory where the tags file is (useful with the -o option). (main): initialise the outfiledir var. (TYPEDST): added the `tignore' value. (C_entries): corrected various small bugs.
This commit is contained in:
parent
6af6cbb530
commit
46c145db6c
257
lib-src/etags.c
257
lib-src/etags.c
@ -25,9 +25,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
* Gnu Emacs TAGS format and modifications by RMS?
|
||||
* Sam Kendall added C++.
|
||||
*
|
||||
* Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 10.7
|
||||
* Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
|
||||
*/
|
||||
|
||||
char etags_version[] = "@(#) pot revision number is 10.15";
|
||||
|
||||
#ifdef MSDOS
|
||||
#include <fcntl.h>
|
||||
#endif /* MSDOS */
|
||||
@ -48,9 +50,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "getopt.h"
|
||||
|
||||
extern char *getenv ();
|
||||
extern char *getcwd ();
|
||||
|
||||
char *etags_index (), *etags_rindex ();
|
||||
char *savenstr ();
|
||||
|
||||
/* Define the symbol ETAGS to make the program "etags",
|
||||
which makes emacs-style tag tables by default.
|
||||
@ -151,19 +152,20 @@ struct nd_st
|
||||
struct nd_st *left, *right; /* left and right sons */
|
||||
};
|
||||
|
||||
long ftell ();
|
||||
typedef struct nd_st NODE;
|
||||
|
||||
logical header_file; /* TRUE if .h file, FALSE o.w. */
|
||||
/* boolean "functions" (see init) */
|
||||
logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
|
||||
|
||||
char cwd [BUFSIZ]; /* current working directory */
|
||||
char *outfiledir; /* directory of tagfile */
|
||||
|
||||
char *concat ();
|
||||
char *savenstr ();
|
||||
char *savestr ();
|
||||
char *xmalloc ();
|
||||
char *xrealloc ();
|
||||
char *savenstr (), *savestr ();
|
||||
char *etags_index (), *etags_rindex ();
|
||||
char *relative_filename (), *absolute_filename (), *absolute_dirname ();
|
||||
char *xmalloc (), *xrealloc ();
|
||||
int L_isdef (), L_isquote ();
|
||||
int PF_funcs ();
|
||||
int total_size_of_entries ();
|
||||
@ -241,7 +243,7 @@ char *curfile, /* current input file name */
|
||||
*endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
|
||||
/* token starting chars */
|
||||
*begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
|
||||
/* valid in-token chars */
|
||||
/* valid in-token chars */
|
||||
*intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
|
||||
|
||||
int append_to_tagfile; /* -a: append to tags */
|
||||
@ -442,7 +444,7 @@ main (argc, argv)
|
||||
extern char *gfnames ();
|
||||
extern char *massage_name ();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MSDOS
|
||||
_fmode = O_BINARY; /* all of files are treated as binary files */
|
||||
#endif /* MSDOS */
|
||||
@ -465,7 +467,7 @@ main (argc, argv)
|
||||
for (;;)
|
||||
{
|
||||
int opt;
|
||||
opt = getopt_long (argc, argv, "aACdDo:f:StTi:BFuvxwVH", longopts, 0);
|
||||
opt = getopt_long (argc, argv, "aCdDo:f:StTi:BFuvxwVH", longopts, 0);
|
||||
|
||||
if (opt == EOF)
|
||||
break;
|
||||
@ -569,10 +571,20 @@ main (argc, argv)
|
||||
exit (BAD);
|
||||
}
|
||||
|
||||
if (outfile == 0)
|
||||
if (outfile == NULL)
|
||||
{
|
||||
outfile = emacs_tags_format ? "TAGS" : "tags";
|
||||
}
|
||||
getcwd (cwd, BUFSIZ); /* the current working directory */
|
||||
strcat (cwd, "/");
|
||||
if (streq (outfile, "-"))
|
||||
{
|
||||
outfiledir = cwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
outfiledir = absolute_dirname (outfile, cwd);
|
||||
}
|
||||
|
||||
init (); /* set up boolean "functions" */
|
||||
|
||||
@ -619,18 +631,18 @@ main (argc, argv)
|
||||
this_file = argv[optind];
|
||||
#endif
|
||||
/* Input file named "-" means read file names from stdin and use them. */
|
||||
if (streq (this_file, "-"))
|
||||
if (streq (this_file, "-"))
|
||||
{
|
||||
while (!feof (stdin))
|
||||
{
|
||||
while (!feof (stdin))
|
||||
{
|
||||
(void) readline (&filename_lb, stdin);
|
||||
if (strlen (filename_lb.buffer) > 0)
|
||||
process_file (filename_lb.buffer);
|
||||
}
|
||||
(void) readline (&filename_lb, stdin);
|
||||
if (strlen (filename_lb.buffer) > 0)
|
||||
process_file (filename_lb.buffer);
|
||||
}
|
||||
else
|
||||
process_file (this_file);
|
||||
}
|
||||
else
|
||||
process_file (this_file);
|
||||
}
|
||||
|
||||
if (emacs_tags_format)
|
||||
{
|
||||
@ -701,7 +713,20 @@ process_file (file)
|
||||
}
|
||||
if (emacs_tags_format)
|
||||
{
|
||||
fprintf (outf, "\f\n%s,%d\n", file, total_size_of_entries (head));
|
||||
char *filename;
|
||||
|
||||
if (file[0] == '/')
|
||||
{
|
||||
/* file is an absolute filename. Canonicalise it. */
|
||||
filename = absolute_filename (file, cwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* file is a filename relative to cwd. Make it relative
|
||||
to the directory of the tags file. */
|
||||
filename = relative_filename (file, outfiledir);
|
||||
}
|
||||
fprintf (outf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
|
||||
put_entries (head);
|
||||
free_tree (head);
|
||||
head = NULL;
|
||||
@ -1318,7 +1343,8 @@ typedef enum
|
||||
FUNCST funcdef;
|
||||
|
||||
|
||||
/* typedefs are recognized using a simple finite automaton.
|
||||
/*
|
||||
* typedefs are recognized using a simple finite automaton.
|
||||
* typeddef is its state variable.
|
||||
*/
|
||||
typedef enum
|
||||
@ -1326,16 +1352,16 @@ typedef enum
|
||||
tnone, /* nothing seen */
|
||||
ttypedseen, /* typedef keyword seen */
|
||||
tinbody, /* inside typedef body */
|
||||
tend /* just before typedef tag */
|
||||
tend, /* just before typedef tag */
|
||||
tignore /* junk after typedef tag */
|
||||
} TYPEDST;
|
||||
TYPEDST typdef;
|
||||
|
||||
|
||||
/* struct tags for C++ are recognized using another simple
|
||||
* finite automaton. `structdef' is its state variable.
|
||||
* This machinery is only invoked for C++; otherwise structdef
|
||||
* should remain snone. However, this machinery can easily be
|
||||
* adapted to find structure tags in normal C code.
|
||||
/*
|
||||
* struct-like structures (enum, struct and union) are recognized
|
||||
* using another simple finite automaton. `structdef' is its state
|
||||
* variable.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@ -1346,6 +1372,7 @@ typedef enum
|
||||
sinbody /* in struct body: recognize member func defs*/
|
||||
} STRUCTST;
|
||||
STRUCTST structdef;
|
||||
|
||||
/*
|
||||
* When structdef is stagseen, scolonseen, or sinbody, structtag is the
|
||||
* struct tag, and structtype is the type of the preceding struct-like
|
||||
@ -1448,7 +1475,7 @@ C_entries (c_ext)
|
||||
lp = curlb.buffer;
|
||||
*lp = 0;
|
||||
|
||||
definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
|
||||
definedef = dnone; funcdef = fnone; typdef = tnone; structdef = snone;
|
||||
next_token_is_func = yacc_rules = FALSE;
|
||||
midtoken = inquote = inchar = incomm = quotednl = FALSE;
|
||||
cblev = 0;
|
||||
@ -1515,7 +1542,7 @@ C_entries (c_ext)
|
||||
CNL;
|
||||
/* FALLTHRU */
|
||||
case '\'':
|
||||
inchar = FALSE;
|
||||
inchar = FALSE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@ -1553,7 +1580,7 @@ C_entries (c_ext)
|
||||
/* entering or exiting rules section in yacc file */
|
||||
lp++;
|
||||
definedef = dnone; funcdef = fnone;
|
||||
typdef= tnone; structdef= snone;
|
||||
typdef = tnone; structdef = snone;
|
||||
next_token_is_func = FALSE;
|
||||
midtoken = inquote = inchar = incomm = quotednl = FALSE;
|
||||
cblev = 0;
|
||||
@ -1572,9 +1599,10 @@ C_entries (c_ext)
|
||||
/* Consider token only if some complicated conditions are satisfied. */
|
||||
if (((cblev == 0 && structdef != scolonseen)
|
||||
|| (cblev == 1 && cplpl && structdef == sinbody))
|
||||
&& typdef != tignore
|
||||
&& definedef != dignorerest
|
||||
&& (funcdef != finlist
|
||||
|| (definedef != dnone && definedef != dignorerest)))
|
||||
|| definedef != dnone))
|
||||
{
|
||||
if (midtoken)
|
||||
{
|
||||
@ -1714,19 +1742,37 @@ C_entries (c_ext)
|
||||
case ';':
|
||||
if (definedef != dnone)
|
||||
break;
|
||||
if (cblev == 0 && typdef == tend)
|
||||
{
|
||||
typdef = tnone;
|
||||
MAKE_TAG_FROM_OTH_LB (FALSE);
|
||||
}
|
||||
if (cblev == 0)
|
||||
switch (typdef)
|
||||
{
|
||||
case tend:
|
||||
MAKE_TAG_FROM_OTH_LB (FALSE);
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
typdef = tnone;
|
||||
}
|
||||
if (funcdef != fignore)
|
||||
funcdef = fnone;
|
||||
/* FALLTHRU */
|
||||
if (structdef == stagseen)
|
||||
structdef = snone;
|
||||
break;
|
||||
case ',':
|
||||
/* FALLTHRU */
|
||||
if (definedef != dnone)
|
||||
break;
|
||||
if (funcdef != finlist && funcdef != fignore)
|
||||
funcdef = fnone;
|
||||
if (structdef == stagseen)
|
||||
structdef = snone;
|
||||
break;
|
||||
case '[':
|
||||
if (definedef != dnone)
|
||||
break;
|
||||
if (cblev == 0 && typdef == tend)
|
||||
{
|
||||
typdef = tignore;
|
||||
MAKE_TAG_FROM_OTH_LB (FALSE);
|
||||
break;
|
||||
}
|
||||
if (funcdef != finlist && funcdef != fignore)
|
||||
funcdef = fnone;
|
||||
if (structdef == stagseen)
|
||||
@ -1758,6 +1804,11 @@ C_entries (c_ext)
|
||||
funcdef = flistseen;
|
||||
break;
|
||||
}
|
||||
if (cblev == 0 && typdef == tend)
|
||||
{
|
||||
typdef = tignore;
|
||||
MAKE_TAG_FROM_OTH_LB (FALSE);
|
||||
}
|
||||
}
|
||||
else if (parlev < 0) /* can happen due to ill-conceived #if's. */
|
||||
parlev = 0;
|
||||
@ -1786,6 +1837,11 @@ C_entries (c_ext)
|
||||
/* FALLTHRU */
|
||||
case fignore:
|
||||
funcdef = fnone;
|
||||
break;
|
||||
case fnone:
|
||||
/* Neutralize `extern "C" {' grot.
|
||||
if (cblev == 0 && structdef == snone && typdef == tnone)
|
||||
cblev--; */;
|
||||
}
|
||||
cblev++;
|
||||
break;
|
||||
@ -1910,6 +1966,7 @@ consider_token (c, tokp, c_ext, cblev, is_func)
|
||||
{
|
||||
if (typedefs)
|
||||
typdef = ttypedseen;
|
||||
funcdef = fnone;
|
||||
return (FALSE);
|
||||
}
|
||||
break;
|
||||
@ -2015,7 +2072,8 @@ consider_token (c, tokp, c_ext, cblev, is_func)
|
||||
switch (toktype)
|
||||
{
|
||||
case st_C_typespec:
|
||||
funcdef = fnone; /* should be useless */
|
||||
if (funcdef != finlist && funcdef != fignore)
|
||||
funcdef = fnone; /* should be useless */
|
||||
return (FALSE);
|
||||
default:
|
||||
if (funcdef == fnone)
|
||||
@ -2176,7 +2234,7 @@ getit (fi)
|
||||
dbp++;
|
||||
}
|
||||
if (!isalpha (*dbp)
|
||||
&& *dbp != '_'
|
||||
&& *dbp != '_'
|
||||
&& *dbp != '$')
|
||||
return;
|
||||
for (cp = dbp + 1;
|
||||
@ -2364,7 +2422,7 @@ PAS_funcs (fi)
|
||||
verify_tag = FALSE;
|
||||
}
|
||||
}
|
||||
if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
|
||||
if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
|
||||
{
|
||||
found_tag = FALSE;
|
||||
verify_tag = FALSE;
|
||||
@ -3073,7 +3131,8 @@ error (s1, s2)
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
|
||||
/* Return a newly-allocated string whose contents
|
||||
concatenate those of s1, s2, s3. */
|
||||
|
||||
char *
|
||||
concat (s1, s2, s3)
|
||||
@ -3085,11 +3144,119 @@ concat (s1, s2, s3)
|
||||
strcpy (result, s1);
|
||||
strcpy (result + len1, s2);
|
||||
strcpy (result + len1 + len2, s3);
|
||||
*(result + len1 + len2 + len3) = 0;
|
||||
result[len1 + len2 + len3] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return a newly allocated string containing the filename of FILE relative
|
||||
to the absolute directory DIR (which should end with a slash). */
|
||||
|
||||
char *
|
||||
relative_filename (file, dir)
|
||||
char *file, *dir;
|
||||
{
|
||||
char *fp, *dp, *res;
|
||||
|
||||
/* Find the common root of file and dir. */
|
||||
fp = absolute_filename (file, cwd);
|
||||
dp = dir;
|
||||
while (*fp++ == *dp++)
|
||||
continue;
|
||||
do
|
||||
{
|
||||
fp--;
|
||||
dp--;
|
||||
}
|
||||
while (*fp != '/');
|
||||
|
||||
/* Build a sequence of "../" strings for the resulting relative filename. */
|
||||
for (dp = etags_index (dp + 1, '/'), res = "";
|
||||
dp != NULL;
|
||||
dp = etags_index (dp + 1, '/'))
|
||||
{
|
||||
res = concat (res, "../", "");
|
||||
}
|
||||
|
||||
/* Add the filename relative to the common root of file and dir. */
|
||||
res = concat (res, fp + 1, "");
|
||||
|
||||
return res; /* temporary stub */
|
||||
}
|
||||
|
||||
/* Return a newly allocated string containing the
|
||||
absolute filename of FILE given CWD (which should end with a slash). */
|
||||
char *
|
||||
absolute_filename (file, cwd)
|
||||
char *file, *cwd;
|
||||
{
|
||||
char *slashp, *cp, *res;
|
||||
|
||||
if (file[0] == '/')
|
||||
res = concat (file, "", "");
|
||||
else
|
||||
res = concat (cwd, file, "");
|
||||
|
||||
/* Delete the "/dirname/.." and "/." substrings. */
|
||||
slashp = etags_index (res, '/');
|
||||
while (slashp != NULL && slashp[0] != '\0')
|
||||
{
|
||||
if (slashp[1] == '.')
|
||||
{
|
||||
if (slashp[2] == '.'
|
||||
&& (slashp[3] == '/' || slashp[3] == '\0'))
|
||||
{
|
||||
cp = slashp;
|
||||
do
|
||||
cp--;
|
||||
while (cp >= res && *cp != '/');
|
||||
if (*cp == '/')
|
||||
{
|
||||
strcpy (cp, slashp + 3);
|
||||
}
|
||||
else /* else (cp == res) */
|
||||
{
|
||||
if (slashp[3] != NULL)
|
||||
strcpy (cp, slashp + 4);
|
||||
else
|
||||
return ".";
|
||||
}
|
||||
slashp = cp;
|
||||
}
|
||||
else if (slashp[2] == '/' || slashp[2] == '\0')
|
||||
{
|
||||
strcpy (slashp, slashp + 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
slashp = etags_index (slashp + 1, '/');
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Return a newly allocated string containing the absolute filename
|
||||
of dir where FILE resides given CWD (which should end with a slash). */
|
||||
char *
|
||||
absolute_dirname (file, cwd)
|
||||
char *file, *cwd;
|
||||
{
|
||||
char *slashp, *res;
|
||||
char save;
|
||||
|
||||
slashp = etags_rindex (file, '/');
|
||||
if (slashp == NULL)
|
||||
return cwd;
|
||||
save = slashp[1];
|
||||
slashp[1] = '\0';
|
||||
res = absolute_filename (file, cwd);
|
||||
slashp[1] = save;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Like malloc but get fatal error if memory is exhausted. */
|
||||
|
||||
char *
|
||||
|
Loading…
Reference in New Issue
Block a user