X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/cf347d3cca09faef8c09c651192da60e50b825fd..2f608d34a6e27761d00a9ffdfbb7e4187a16d77d:/lib-src/etags.c?ds=inline diff --git a/lib-src/etags.c b/lib-src/etags.c index 3445d2de8a..8b21906b88 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -31,7 +31,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer. */ -char pot_etags_version[] = "@(#) pot revision number is 11.63"; +char pot_etags_version[] = "@(#) pot revision number is $Revision: 11.84 $"; #define TRUE 1 #define FALSE 0 @@ -54,6 +54,11 @@ char pot_etags_version[] = "@(#) pot revision number is 11.63"; # define MAXPATHLEN _MAX_PATH #endif +#if !defined (MSDOS) && !defined (WINDOWSNT) && defined (STDC_HEADERS) +#include +#include +#endif + #ifdef HAVE_CONFIG_H # include /* On some systems, Emacs defines static as nothing for the sake @@ -81,7 +86,7 @@ extern int errno; #endif /* ETAGS_REGEXPS */ /* Define CTAGS to make the program "ctags" compatible with the usual one. - Let it undefined to make the program "etags", which makes emacs-style + Leave it undefined to make the program "etags", which makes emacs-style tag tables and tags typedefs, #defines and struct/union/enum by default. */ #ifdef CTAGS # undef CTAGS @@ -104,10 +109,12 @@ extern int errno; #define C_STAR 0x00003 /* C* */ #define YACC 0x10000 /* yacc file */ -#define streq(s,t) ((DEBUG &&!(s)&&!(t)&&(abort(),1)) || !strcmp(s,t)) -#define strneq(s,t,n) ((DEBUG &&!(s)&&!(t)&&(abort(),1)) || !strncmp(s,t,n)) +#define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \ + && (abort (), 1)) || !strcmp (s, t)) +#define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \ + && (abort (), 1)) || !strncmp (s, t, n)) -#define lowcase(c) tolower ((unsigned char)c) +#define lowcase(c) tolower ((char)c) #define iswhite(arg) (_wht[arg]) /* T if char is white */ #define begtoken(arg) (_btk[arg]) /* T if char can start token */ @@ -127,7 +134,13 @@ extern int errno; * * SYNOPSIS: Type *xnew (int n, Type); */ -#define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) +#ifdef chkmalloc +# include "chkmalloc.h" +# define xnew(n,Type) ((Type *) trace_xmalloc (__FILE__, __LINE__, \ + (n) * sizeof (Type))) +#else +# define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) +#endif typedef int logical; @@ -150,6 +163,7 @@ char *savenstr (), *savestr (); char *etags_strchr (), *etags_strrchr (); char *etags_getcwd (); char *relative_filename (), *absolute_filename (), *absolute_dirname (); +void grow_linebuffer (); long *xmalloc (), *xrealloc (); typedef void Lang_function (); @@ -232,9 +246,6 @@ NODE *head; /* the head of the binary tree of tags */ * `readline' reads a line from a stream into a linebuffer and works * regardless of the length of the line. */ -#define GROW_LINEBUFFER(buf,toksize) \ -while (buf.size < toksize) \ - buf.buffer = (char *) xrealloc (buf.buffer, buf.size *= 2) struct linebuffer { long size; @@ -268,7 +279,7 @@ logical typedefs_and_cplusplus; /* -T: create tags for typedefs, level */ /* 0 struct/enum/union decls, and C++ */ /* member functions. */ logical constantypedefs; /* -d: create tags for C #define and enum */ - /* constants. Enum consts not implemented. */ + /* constants. */ /* -D: opposite of -d. Default under ctags. */ logical update; /* -u: update tags */ logical vgrind_style; /* -v: create vgrind style index output */ @@ -450,7 +461,9 @@ Fortran is tried first; if no tags are found, C is tried next."); void print_version () { - printf ("%s for Emacs version %s\n", (CTAGS) ? "ctags" : "etags", VERSION); + printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION); + puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold"); + puts ("This program is distributed under the same terms as Emacs"); exit (GOOD); } @@ -479,11 +492,11 @@ are. Relative ones are stored relative to the output file's directory."); if (CTAGS) puts ("-d, --defines\n\ - Create tag entries for constant C #defines, too."); + Create tag entries for C #define constants and enum constants, too."); else puts ("-D, --no-defines\n\ - Don't create tag entries for constant C #defines. This makes\n\ - the tags file smaller."); + Don't create tag entries for C #define constants and enum constants.\n\ + This makes the tags file smaller."); if (!CTAGS) { @@ -549,6 +562,9 @@ are. Relative ones are stored relative to the output file's directory."); print_language_names (); + puts (""); + puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu"); + exit (GOOD); } @@ -560,7 +576,7 @@ enum argument_type at_filename }; -/* This structure helps us allow mixing of --lang and filenames. */ +/* This structure helps us allow mixing of --lang and file names. */ typedef struct { enum argument_type arg_type; @@ -582,7 +598,7 @@ typedef struct { /* v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names - returning in each successive call the next filename matching the input + 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 @@ -591,7 +607,7 @@ typedef struct { If an error occurs, on return out_spec contains the value of in_spec when the error occurred. - With each successive filename returned in out_spec, the + 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. @@ -670,7 +686,7 @@ gfnames (arg, p_error) system (cmd) char *cmd; { - fprintf (stderr, "system() function not implemented under VMS\n"); + error ("%s", "system() function not implemented under VMS"); } #endif @@ -693,17 +709,17 @@ char *massage_name (s) #endif /* VMS */ -void +int main (argc, argv) int argc; char *argv[]; { int i; - unsigned int nincluded_files = 0; - char **included_files = xnew (argc, char *); + unsigned int nincluded_files; + char **included_files; char *this_file; argument *argbuffer; - int current_arg = 0, file_count = 0; + int current_arg, file_count; struct linebuffer filename_lb; #ifdef VMS logical got_err; @@ -714,6 +730,10 @@ main (argc, argv) #endif /* DOS_NT */ progname = argv[0]; + nincluded_files = 0; + included_files = xnew (argc, char *); + current_arg = 0; + file_count = 0; /* Allocate enough no matter what happens. Overkill, but each one is small. */ @@ -726,7 +746,7 @@ main (argc, argv) /* * If etags, always find typedefs and structure tags. Why not? - * Also default is to find macro constants. + * Also default is to find macro constants and enum constants. */ if (!CTAGS) typedefs = typedefs_and_cplusplus = constantypedefs = TRUE; @@ -747,7 +767,7 @@ main (argc, argv) break; case 1: - /* This means that a filename has been seen. Record it. */ + /* This means that a file name has been seen. Record it. */ argbuffer[current_arg].arg_type = at_filename; argbuffer[current_arg].what = optarg; ++current_arg; @@ -771,8 +791,7 @@ main (argc, argv) case 'o': if (tagfile) { - fprintf (stderr, "%s: -%c option may only be given once.\n", - progname, opt); + error ("-%c option may only be given once.", opt); suggest_asking_for_help (); } tagfile = optarg; @@ -849,15 +868,15 @@ main (argc, argv) if (nincluded_files == 0 && file_count == 0) { - fprintf (stderr, "%s: No input files specified.\n", progname); + error ("%s", "No input files specified."); suggest_asking_for_help (); } if (tagfile == NULL) tagfile = CTAGS ? "tags" : "TAGS"; cwd = etags_getcwd (); /* the current working directory */ - if (cwd[strlen(cwd)-1] != '/') - strcat (cwd, "/"); + if (cwd[strlen (cwd) - 1] != '/') + cwd = concat (cwd, "/", ""); if (streq (tagfile, "-")) tagfiledir = cwd; else @@ -947,9 +966,6 @@ main (argc, argv) because we want them ordered. Let's do it now. */ if (cxref_style) { - tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); - if (tagf == NULL) - pfatal (tagfile); put_entries (head); exit (GOOD); } @@ -965,7 +981,7 @@ main (argc, argv) "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS", tagfile, argbuffer[i].what, tagfile); if (system (cmd) != GOOD) - fatal ("failed to execute shell command"); + fatal ("failed to execute shell command", (char *)NULL); } append_to_tagfile = TRUE; } @@ -982,7 +998,7 @@ main (argc, argv) sprintf (cmd, "sort %s -o %s", tagfile, tagfile); exit (system (cmd)); } - exit (GOOD); + return GOOD; } @@ -1002,8 +1018,7 @@ get_language_from_name (name) return lang->function; } - fprintf (stderr, "%s: language \"%s\" not recognized.\n", - progname, optarg); + error ("language \"%s\" not recognized.", optarg); suggest_asking_for_help (); /* This point should never be reached. The function should either @@ -1078,12 +1093,12 @@ process_file (file) if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode)) { - fprintf (stderr, "Skipping %s: it is not a regular file.\n", file); + error ("Skipping %s: it is not a regular file.", file); return; } if (streq (file, tagfile) && !streq (tagfile, "-")) { - fprintf (stderr, "Skipping inclusion of %s in self.\n", file); + error ("Skipping inclusion of %s in self.", file); return; } inf = fopen (file, "r"); @@ -1101,12 +1116,12 @@ process_file (file) if (absolutefn (file)) { - /* file is an absolute filename. Canonicalise it. */ + /* file is an absolute file name. Canonicalise it. */ filename = absolute_filename (file, cwd); } else { - /* file is a filename relative to cwd. Make it relative + /* file is a file name relative to cwd. Make it relative to the directory of the tags file. */ filename = relative_filename (file, tagfiledir); } @@ -1337,7 +1352,7 @@ add_node (node, cur_node_p) { /* Etags Mode */ if (last_node == NULL) - fatal ("internal error in add_node", 0); + fatal ("internal error in add_node", (char *)NULL); last_node->right = node; last_node = node; } @@ -1403,7 +1418,7 @@ put_entries (node) else { if (node->name == NULL) - error ("internal error: NULL name in ctags mode.", 0); + error ("internal error: NULL name in ctags mode.", (char *)NULL); if (cxref_style) { @@ -1498,7 +1513,7 @@ enum sym_type }; /* Feed stuff between (but not including) %[ and %] lines to: - gperf -c -k1,3 -o -p -r -t + gperf -c -k 1,3 -o -p -r -t %[ struct C_stab_entry { char *name; int c_ext; enum sym_type type; } %% @@ -1507,12 +1522,14 @@ struct C_stab_entry { char *name; int c_ext; enum sym_type type; } @implementation,0, st_C_objimpl @end, 0, st_C_objend class, C_PLPL, st_C_struct +namespace, C_PLPL, st_C_struct domain, C_STAR, st_C_struct union, 0, st_C_struct struct, 0, st_C_struct enum, 0, st_C_enum typedef, 0, st_C_typedef define, 0, st_C_define +bool, C_PLPL, st_C_typespec long, 0, st_C_typespec short, 0, st_C_typespec int, 0, st_C_typespec @@ -1527,6 +1544,9 @@ extern, 0, st_C_typespec static, 0, st_C_typespec const, 0, st_C_typespec volatile, 0, st_C_typespec +explicit, C_PLPL, st_C_typespec +mutable, C_PLPL, st_C_typespec +typename, C_PLPL, st_C_typespec # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach). DEFUN, 0, st_C_gnumacro SYSCALL, 0, st_C_gnumacro @@ -1539,94 +1559,107 @@ PSEUDO, 0, st_C_gnumacro %] and replace lines between %< and %> with its output. */ /*%<*/ -/* C code produced by gperf version 1.8.1 (K&R C version) */ -/* Command-line: gperf -c -k1,3 -o -p -r -t */ +/* C code produced by gperf version 2.1 (K&R C version) */ +/* Command-line: gperf -c -k 1,3 -o -p -r -t */ struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; #define MIN_WORD_LENGTH 3 #define MAX_WORD_LENGTH 15 -#define MIN_HASH_VALUE 7 -#define MAX_HASH_VALUE 63 +#define MIN_HASH_VALUE 34 +#define MAX_HASH_VALUE 121 /* - 29 keywords - 57 is the maximum key range + 34 keywords + 88 is the maximum key range */ static int hash (str, len) - register char *str; - register int len; + register char *str; + register unsigned int len; { static unsigned char hash_table[] = { - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 17, 63, 63, 63, 4, 14, - 4, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 8, 63, 63, 0, 23, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 28, 63, 28, - 10, 31, 27, 18, 63, 6, 63, 63, 26, 1, - 11, 2, 29, 63, 29, 16, 26, 13, 15, 63, - 63, 63, 63, 63, 63, 63, 63, 63, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 45, 121, 121, 121, 16, 19, + 61, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 10, 121, 121, 20, 53, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 41, 45, 22, + 60, 47, 37, 28, 121, 55, 121, 121, 20, 14, + 29, 30, 5, 121, 50, 59, 30, 54, 6, 121, + 121, 121, 121, 121, 121, 121, 121, 121, }; return len + hash_table[str[2]] + hash_table[str[0]]; } struct C_stab_entry * -in_word_set (str, len) +in_word_set (str, len) register char *str; - register int len; + register unsigned int len; { static struct C_stab_entry wordlist[] = { - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"volatile", 0, st_C_typespec}, + {"PSEUDO", 0, st_C_gnumacro}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"typedef", 0, st_C_typedef}, + {"typename", C_PLPL, st_C_typespec}, + {"",}, {"",}, {"",}, {"SYSCALL", 0, st_C_gnumacro}, - {"",}, {"",}, {"",}, {"",}, {"",}, - {"DEFUN", 0, st_C_gnumacro}, - {"",}, {"",}, {"",}, - {"domain", C_STAR, st_C_struct}, - {"",}, {"",}, {"",}, {"",}, {"",}, - {"short", 0, st_C_typespec}, - {"union", 0, st_C_struct}, + {"",}, {"",}, {"",}, + {"mutable", C_PLPL, st_C_typespec}, + {"namespace", C_PLPL, st_C_struct}, + {"long", 0, st_C_typespec}, + {"",}, {"",}, + {"const", 0, st_C_typespec}, + {"",}, {"",}, {"",}, + {"explicit", C_PLPL, st_C_typespec}, + {"",}, {"",}, {"",}, {"",}, {"void", 0, st_C_typespec}, - {"",}, {"",}, - {"PSEUDO", 0, st_C_gnumacro}, - {"double", 0, st_C_typespec}, - {"",}, {"",}, - {"@end", 0, st_C_objend}, - {"@implementation", 0, st_C_objimpl}, + {"",}, + {"char", 0, st_C_typespec}, + {"class", C_PLPL, st_C_struct}, + {"",}, {"",}, {"",}, {"float", 0, st_C_typespec}, - {"int", 0, st_C_typespec}, - {"",}, - {"unsigned", 0, st_C_typespec}, + {"",}, + {"@implementation", 0, st_C_objimpl}, + {"auto", 0, st_C_typespec}, + {"",}, + {"ENTRY", 0, st_C_gnumacro}, + {"@end", 0, st_C_objend}, + {"bool", C_PLPL, st_C_typespec}, + {"domain", C_STAR, st_C_struct}, + {"",}, + {"DEFUN", 0, st_C_gnumacro}, + {"extern", 0, st_C_typespec}, {"@interface", 0, st_C_objprot}, - {"",}, + {"",}, {"",}, {"",}, + {"int", 0, st_C_typespec}, + {"",}, {"",}, {"",}, {"",}, {"signed", 0, st_C_typespec}, - {"long", 0, st_C_typespec}, - {"ENTRY", 0, st_C_gnumacro}, + {"short", 0, st_C_typespec}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"define", 0, st_C_define}, - {"const", 0, st_C_typespec}, - {"",}, {"",}, {"",}, + {"@protocol", 0, st_C_objprot}, {"enum", 0, st_C_enum}, - {"volatile", 0, st_C_typespec}, {"static", 0, st_C_typespec}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"union", 0, st_C_struct}, {"struct", 0, st_C_struct}, - {"",}, {"",}, {"",}, - {"@protocol", 0, st_C_objprot}, - {"",}, {"",}, - {"auto", 0, st_C_typespec}, - {"",}, - {"char", 0, st_C_typespec}, - {"class", C_PLPL, st_C_struct}, - {"typedef", 0, st_C_typedef}, - {"extern", 0, st_C_typespec}, + {"",}, {"",}, {"",}, {"",}, + {"double", 0, st_C_typespec}, + {"unsigned", 0, st_C_typespec}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -1646,12 +1679,12 @@ in_word_set (str, len) /*%>*/ enum sym_type -C_symtype(str, len, c_ext) +C_symtype (str, len, c_ext) char *str; int len; int c_ext; { - register struct C_stab_entry *se = in_word_set(str, len); + register struct C_stab_entry *se = in_word_set (str, len); if (se == NULL || (se->c_ext && !(c_ext & se->c_ext))) return st_none; @@ -1764,10 +1797,10 @@ int methodlen; * consider_token () * checks to see if the current token is at the start of a * function, or corresponds to a typedef, or is a struct/union/enum - * tag. + * tag, or #define, or an enum constant. * - * *IS_FUNC gets TRUE iff the token is a function or macro with args. - * C_EXT is which language we are looking at. + * *IS_FUNC gets TRUE iff the token is a function or #define macro + * with args. C_EXT is which language we are looking at. * * In the future we will need some way to adjust where the end of * the token is; for instance, implementing the C++ keyword @@ -1827,7 +1860,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) case dignorerest: return FALSE; default: - error ("internal error: definedef value.", 0); + error ("internal error: definedef value.", (char *)NULL); } /* @@ -1877,11 +1910,6 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) * 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. - * - * This if statement deals with the typdef state machine as - * follows: if typdef==ttypedseen and token is struct/union/class/enum, - * return FALSE. All the other code here is for the structdef - * state machine. */ switch (toktype) { @@ -1895,6 +1923,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) } return FALSE; } + if (structdef == skeyseen) { /* Save the tag for struct/union/class, for functions that may be @@ -1914,7 +1943,20 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) return FALSE; } - /* Detect GNU macros. */ + /* Detect GNU macros. + + DEFUN note for writers of emacs C code: + The DEFUN macro, used in emacs C source code, has a first arg + that is a string (the lisp function name), and a second arg that + is a C function name. Since etags skips strings, the second arg + is tagged. This is unfortunate, as it would be better to tag the + first arg. The simplest way to deal with this problem would be + to name the tag with a name built from the function name, by + removing the initial 'F' character and substituting '-' for '_'. + Anyway, this assumes that the conventions of naming lisp + functions will never change. Currently, this method is not + implemented, so writers of emacs code are recommended to put the + first two args of a DEFUN on the same line. */ if (definedef == dnone && toktype == st_C_gnumacro) { next_token_is_func = TRUE; @@ -1928,9 +1970,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) return TRUE; } - /* - * Detecting Objective C constructs. - */ + /* Detect Objective C constructs. */ switch (objdef) { case onone: @@ -1966,7 +2006,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) { objdef = omethodtag; methodlen = len; - GROW_LINEBUFFER (token_name, methodlen+1); + grow_linebuffer (&token_name, methodlen+1); strncpy (token_name.buffer, str, len); token_name.buffer[methodlen] = '\0'; return TRUE; @@ -1981,7 +2021,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) { objdef = omethodtag; methodlen += len; - GROW_LINEBUFFER (token_name, methodlen+1); + grow_linebuffer (&token_name, methodlen+1); strncat (token_name.buffer, str, len); return TRUE; } @@ -2000,14 +2040,16 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) return FALSE; } - /* A function? */ + /* A function or enum constant? */ switch (toktype) { case st_C_typespec: if (funcdef != finlist && funcdef != fignore) funcdef = fnone; /* should be useless */ return FALSE; - default: + case st_none: + if (constantypedefs && structdef == sinbody && structtype == st_C_enum) + return TRUE; if (funcdef == fnone) { funcdef = ftagseen; @@ -2021,9 +2063,9 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func) /* * C_entries () - * This routine finds functions, typedefs, #define's and - * struct/union/enum definitions in C syntax and adds them - * to the list. + * This routine finds functions, typedefs, #define's, enum + * constants and struct/union/enum definitions in C syntax + * and adds them to the list. */ typedef struct { @@ -2068,16 +2110,28 @@ do { \ definedef = dnone; \ } while (0) -/* Ideally this macro should never be called wihen tok.valid is FALSE, - but this would mean that the state machines always guess right. */ -#define make_tag(isfun) do \ -if (tok.valid) { \ - char *name = NULL; \ - if (CTAGS || tok.named) \ - name = savestr (token_name.buffer); \ - pfnote (name, isfun, tok.buffer, tok.linelen, tok.lineno, tok.linepos); \ - tok.valid = FALSE; \ -} while (0) + +void +make_C_tag (isfun, tokp) + logical isfun; + TOKEN *tokp; +{ + char *name = NULL; + + /* This function should never be called when tok.valid is FALSE, but + we must protect against invalid input or internal errors. */ + if (tokp->valid) + { + if (CTAGS || tokp->named) + name = savestr (token_name.buffer); + pfnote (name, isfun, + tokp->buffer, tokp->linelen, tokp->lineno, tokp->linepos); + tokp->valid = FALSE; + } + else if (DEBUG) + abort (); +} + void C_entries (c_ext, inf) @@ -2250,7 +2304,8 @@ C_entries (c_ext, inf) /* Consider token only if some complicated conditions are satisfied. */ if ((definedef != dnone || (cblev == 0 && structdef != scolonseen) - || (cblev == 1 && cplpl && structdef == sinbody)) + || (cblev == 1 && cplpl && structdef == sinbody) + || (structdef == sinbody && structtype == st_C_enum)) && typdef != tignore && definedef != dignorerest && funcdef != finlist) @@ -2281,7 +2336,7 @@ C_entries (c_ext, inf) && is_func) /* function defined in C++ class body */ { - GROW_LINEBUFFER (token_name, + grow_linebuffer (&token_name, strlen(structtag)+2+toklen+1); strcpy (token_name.buffer, structtag); strcat (token_name.buffer, "::"); @@ -2292,7 +2347,7 @@ C_entries (c_ext, inf) else if (objdef == ocatseen) /* Objective C category */ { - GROW_LINEBUFFER (token_name, + grow_linebuffer (&token_name, strlen(objtag)+2+toklen+1); strcpy (token_name.buffer, objtag); strcat (token_name.buffer, "("); @@ -2309,7 +2364,7 @@ C_entries (c_ext, inf) } else { - GROW_LINEBUFFER (token_name, toklen+1); + grow_linebuffer (&token_name, toklen+1); strncpy (token_name.buffer, newlb.buffer+tokoff, toklen); token_name.buffer[toklen] = '\0'; @@ -2337,7 +2392,7 @@ C_entries (c_ext, inf) switch_line_buffers (); } else - make_tag (is_func); + make_C_tag (is_func, &tok); } midtoken = FALSE; } @@ -2359,7 +2414,7 @@ C_entries (c_ext, inf) funcdef = finlist; continue; case flistseen: - make_tag (TRUE); + make_C_tag (TRUE, &tok); funcdef = fignore; break; case ftagseen: @@ -2394,13 +2449,13 @@ C_entries (c_ext, inf) { case otagseen: objdef = oignore; - make_tag (TRUE); + make_C_tag (TRUE, &tok); break; case omethodtag: case omethodparm: objdef = omethodcolon; methodlen += 1; - GROW_LINEBUFFER (token_name, methodlen+1); + grow_linebuffer (&token_name, methodlen+1); strcat (token_name.buffer, ":"); break; } @@ -2412,7 +2467,7 @@ C_entries (c_ext, inf) case ftagseen: if (yacc_rules) { - make_tag (FALSE); + make_C_tag (FALSE, &tok); funcdef = fignore; } break; @@ -2428,7 +2483,7 @@ C_entries (c_ext, inf) switch (typdef) { case tend: - make_tag (FALSE); + make_C_tag (FALSE, &tok); /* FALLTHRU */ default: typdef = tnone; @@ -2451,7 +2506,7 @@ C_entries (c_ext, inf) { case omethodtag: case omethodparm: - make_tag (TRUE); + make_C_tag (TRUE, &tok); objdef = oinbody; break; } @@ -2466,7 +2521,7 @@ C_entries (c_ext, inf) if (cblev == 0 && typdef == tend) { typdef = tignore; - make_tag (FALSE); + make_C_tag (FALSE, &tok); break; } if (funcdef != finlist && funcdef != fignore) @@ -2489,10 +2544,10 @@ C_entries (c_ext, inf) /* Make sure that the next char is not a '*'. This handles constructs like: typedef void OperatorFun (int fun); */ - if (*lp != '*') + if (tok.valid && *lp != '*') { typdef = tignore; - make_tag (FALSE); + make_C_tag (FALSE, &tok); } break; } /* switch (typdef) */ @@ -2511,7 +2566,7 @@ C_entries (c_ext, inf) break; if (objdef == ocatseen && parlev == 1) { - make_tag (TRUE); + make_C_tag (TRUE, &tok); objdef = oignore; } if (--parlev == 0) @@ -2526,7 +2581,7 @@ C_entries (c_ext, inf) if (cblev == 0 && typdef == tend) { typdef = tignore; - make_tag (FALSE); + make_C_tag (FALSE, &tok); } } else if (parlev < 0) /* can happen due to ill-conceived #if's. */ @@ -2540,19 +2595,19 @@ C_entries (c_ext, inf) switch (structdef) { case skeyseen: /* unnamed struct */ - structtag = "_anonymous_"; structdef = sinbody; + structtag = "_anonymous_"; break; case stagseen: case scolonseen: /* named struct */ structdef = sinbody; - make_tag (FALSE); + make_C_tag (FALSE, &tok); break; } switch (funcdef) { case flistseen: - make_tag (TRUE); + make_C_tag (TRUE, &tok); /* FALLTHRU */ case fignore: funcdef = fnone; @@ -2561,16 +2616,16 @@ C_entries (c_ext, inf) switch (objdef) { case otagseen: - make_tag (TRUE); + make_C_tag (TRUE, &tok); objdef = oignore; break; case omethodtag: case omethodparm: - make_tag (TRUE); + make_C_tag (TRUE, &tok); objdef = oinbody; break; default: - /* Neutralize `extern "C" {' grot and look inside structs. */ + /* Neutralize `extern "C" {' grot. */ if (cblev == 0 && structdef == snone && typdef == tnone) cblev = -1; } @@ -2628,7 +2683,7 @@ C_entries (c_ext, inf) case '\0': if (objdef == otagseen) { - make_tag (TRUE); + make_C_tag (TRUE, &tok); objdef = oignore; } /* If a macro spans multiple lines don't reset its state. */ @@ -3059,7 +3114,7 @@ Pascal_functions (inf) continue; /* save all values for later tagging */ - GROW_LINEBUFFER (tline, strlen (lb.buffer) + 1); + grow_linebuffer (&tline, strlen (lb.buffer) + 1); strcpy (tline.buffer, lb.buffer); save_lineno = lineno; save_lcno = linecharno; @@ -3331,7 +3386,7 @@ TeX_functions (inf) i = TEX_Token (lasthit); if (0 <= i) { - pfnote (NULL, TRUE, + pfnote ((char *)NULL, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno); #if TeX_named_tokens TEX_getit (lasthit, TEX_toktab[i].len); @@ -3505,11 +3560,11 @@ Prolog_functions (inf) else if (isspace (dbp[0])) /* Not a predicate */ continue; else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */ - prolog_skip_comment (&lb, inf, &lineno, &linecharno); + prolog_skip_comment (&lb, inf); else if (len = prolog_pred (dbp, last)) { /* Predicate. Store the function name so that we only - * generates a tag for the first clause. */ + generate a tag for the first clause. */ if (last == NULL) last = xnew(len + 1, char); else if (len + 1 > allocated) @@ -3938,7 +3993,7 @@ add_regex (regexp_pattern) if (regexp_pattern[0] == '\0') { - error ("missing regexp", 0); + error ("missing regexp", (char *)NULL); return; } if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0]) @@ -3949,7 +4004,7 @@ add_regex (regexp_pattern) name = scan_separators (regexp_pattern); if (regexp_pattern[0] == '\0') { - error ("null regexp", 0); + error ("null regexp", (char *)NULL); return; } (void) scan_separators (name); @@ -3988,52 +4043,40 @@ substitute (in, out, regs) char *in, *out; struct re_registers *regs; { - char *result = NULL, *t; - int size = 0; + char *result, *t; + int size, i; + + result = NULL; + size = strlen (out); /* Pass 1: figure out how much size to allocate. */ - for (t = out; *t; ++t) - { - if (*t == '\\') - { - ++t; - if (!*t) - { - fprintf (stderr, "%s: pattern substitution ends prematurely\n", - progname); - return NULL; - } - if (isdigit (*t)) - { - int dig = *t - '0'; - size += regs->end[dig] - regs->start[dig]; - } - } - } + if (out[strlen (out) - 1] == '\\') + fatal ("pattern error in %s", out); + for (t = out; *t != '\0'; ++t) + if (*t == '\\' && isdigit (*++t)) + { + int dig = *t - '0'; + size += regs->end[dig] - regs->start[dig] - 2; + } /* Allocate space and do the substitutions. */ result = xnew (size + 1, char); - size = 0; - for (; *out; ++out) + for (i = 0; *out != '\0'; ++out) { - if (*out == '\\') + if (*out == '\\' && isdigit (*++out)) { - ++out; - if (isdigit (*out)) - { - /* Using "dig2" satisfies my debugger. Bleah. */ - int dig2 = *out - '0'; - strncpy (result + size, in + regs->start[dig2], - regs->end[dig2] - regs->start[dig2]); - size += regs->end[dig2] - regs->start[dig2]; - } - else - result[size++] = *out; + /* Using "dig2" satisfies my debugger. Bleah. */ + int dig2 = *out - '0'; + int diglen = regs->end[dig2] - regs->start[dig2]; + strncpy (result + i, in + regs->start[dig2], diglen); + i += diglen; } else - result[size++] = *out; + result[i++] = *out; } - result[size] = '\0'; + result[i] = '\0'; + if (DEBUG && i > size) + abort (); return result; } @@ -4087,7 +4130,16 @@ readline_internal (linebuffer, stream) if (p > buffer && p[-1] == '\r') { *--p = '\0'; +#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 { @@ -4149,7 +4201,7 @@ readline (linebuffer, stream) else { /* Make an unnamed tag. */ - pfnote (NULL, TRUE, + pfnote ((char *)NULL, TRUE, linebuffer->buffer, match, lineno, linecharno); } break; @@ -4305,19 +4357,7 @@ concat (s1, s2, s3) char * etags_getcwd () { -#ifdef DOS_NT - char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ - - getwd (path); - for (p = path; *p != '\0'; p++) - if (*p == '\\') - *p = '/'; - else - *p = lowcase (*p); - - return strdup (path); -#else /* not DOS_NT */ -#if HAVE_GETCWD +#ifdef HAVE_GETCWD int bufsize = 200; char *path = xnew (bufsize, char); @@ -4329,8 +4369,32 @@ etags_getcwd () path = xnew (bufsize, char); } +#if WINDOWSNT + { + /* Convert backslashes to slashes. */ + char *p; + for (p = path; *p != '\0'; p++) + if (*p == '\\') + *p = '/'; + } +#endif + return path; -#else /* not DOS_NT and not HAVE_GETCWD */ + +#else /* not HAVE_GETCWD */ +#ifdef MSDOS + char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ + + getwd (path); + + for (p = path; *p != '\0'; p++) + if (*p == '\\') + *p = '/'; + else + *p = lowcase (*p); + + return strdup (path); +#else /* not MSDOS */ struct linebuffer path; FILE *pipe; @@ -4341,11 +4405,11 @@ etags_getcwd () pclose (pipe); return path.buffer; +#endif /* not MSDOS */ #endif /* not HAVE_GETCWD */ -#endif /* not DOS_NT */ } -/* Return a newly allocated string containing the filename +/* Return a newly allocated string containing the file name of FILE relative to the absolute directory DIR (which should end with a slash). */ char * @@ -4353,37 +4417,37 @@ relative_filename (file, dir) char *file, *dir; { char *fp, *dp, *abs, *res; + int i; - /* Find the common root of file and dir. */ + /* Find the common root of file and dir (with a trailing slash). */ abs = absolute_filename (file, cwd); fp = abs; dp = dir; while (*fp++ == *dp++) continue; - do - { - fp--; - dp--; - } + fp--, dp--; /* back to the first differing char */ + do /* look at the equal chars until '/' */ + fp--, dp--; while (*fp != '/'); - /* Build a sequence of "../" strings for the resulting relative filename. */ - for (dp = etags_strchr (dp + 1, '/'), res = ""; - dp != NULL; - dp = etags_strchr (dp + 1, '/')) - { - res = concat (res, "../", ""); - } - - /* Add the filename relative to the common root of file and dir. */ - res = concat (res, fp + 1, ""); + /* Build a sequence of "../" strings for the resulting relative file name. */ + i = 0; + while ((dp = etags_strchr (dp + 1, '/')) != NULL) + i += 1; + res = xnew (3*i + strlen (fp + 1) + 1, char); + res[0] = '\0'; + while (i-- > 0) + strcat (res, "../"); + + /* Add the file name relative to the common root of file and dir. */ + strcat (res, fp + 1); free (abs); return res; } /* Return a newly allocated string containing the - absolute filename of FILE given CWD (which should + absolute file name of FILE given CWD (which should end with a slash). */ char * absolute_filename (file, cwd) @@ -4392,12 +4456,12 @@ absolute_filename (file, cwd) char *slashp, *cp, *res; if (absolutefn (file)) - res = concat (file, "", ""); + res = savestr (file); #ifdef DOS_NT - /* We don't support non-absolute filenames with a drive + /* We don't support non-absolute file names with a drive letter, like `d:NAME' (it's too much hassle). */ else if (file[1] == ':') - fatal ("%s: relative filenames with drive letters not supported", file); + fatal ("%s: relative file names with drive letters not supported", file); #endif else res = concat (cwd, file, ""); @@ -4415,24 +4479,16 @@ absolute_filename (file, cwd) do cp--; while (cp >= res && !absolutefn (cp)); - if (*cp == '/') - { - strcpy (cp, slashp + 3); - } + if (cp < res) + cp = slashp; /* the absolute name begins with "/.." */ #ifdef DOS_NT /* Under MSDOS and NT we get `d:/NAME' as absolute - filename, so the luser could say `d:/../NAME'. + file name, so the luser could say `d:/../NAME'. We silently treat this as `d:/NAME'. */ - else if (cp[1] == ':') - strcpy (cp + 3, slashp + 4); + else if (cp[0] != '/') + cp = slashp; #endif - else /* else (cp == res) */ - { - if (slashp[3] != '\0') - strcpy (cp, slashp + 4); - else - return "."; - } + strcpy (cp, slashp + 3); slashp = cp; continue; } @@ -4445,12 +4501,15 @@ absolute_filename (file, cwd) slashp = etags_strchr (slashp + 1, '/'); } - - return res; + + if (res[0] == '\0') + return savestr ("/"); + else + return res; } /* Return a newly allocated string containing the absolute - filename of dir where FILE resides given CWD (which should + file name of dir where FILE resides given CWD (which should end with a slash). */ char * absolute_dirname (file, cwd) @@ -4468,7 +4527,7 @@ absolute_dirname (file, cwd) slashp = etags_strrchr (file, '/'); if (slashp == NULL) - return cwd; + return savestr (cwd); save = slashp[1]; slashp[1] = '\0'; res = absolute_filename (file, cwd); @@ -4477,6 +4536,17 @@ absolute_dirname (file, cwd) return res; } +/* Increase the size of a linebuffer. */ +void +grow_linebuffer (bufp, toksize) + struct linebuffer *bufp; + int toksize; +{ + while (bufp->size < toksize) + bufp->size *= 2; + bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size); +} + /* Like malloc but get fatal error if memory is exhausted. */ long * xmalloc (size) @@ -4484,7 +4554,7 @@ xmalloc (size) { long *result = (long *) malloc (size); if (result == NULL) - fatal ("virtual memory exhausted", 0); + fatal ("virtual memory exhausted", (char *)NULL); return result; } @@ -4495,6 +4565,6 @@ xrealloc (ptr, size) { long *result = (long *) realloc (ptr, size); if (result == NULL) - fatal ("virtual memory exhausted"); + fatal ("virtual memory exhausted", (char *)NULL); return result; }