X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=lib-src%2Fetags.c;h=7ae810d96fc0443b562def274b45a2dfcf8fbb9e;hb=02f4d2761a98c5cb9d5b423d2361160a5d8c9ee4;hp=5f2223a5e1d86f9e928177b8c0a52fd219766d3f;hpb=afa9772e3fcbb4e80e3e4cfd1a40b4fccc6d08b8;p=chise%2Fxemacs-chise.git.1 diff --git a/lib-src/etags.c b/lib-src/etags.c index 5f2223a..7ae810d 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -1,5 +1,5 @@ -/* Tags file maker to go with GNU Emacs - Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98, 99 +/* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*- + Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98, 99, 2000, 2001 Free Software Foundation, Inc. and Ken Arnold This file is not considered part of GNU Emacs. @@ -24,24 +24,31 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * Fortran added by Jim Kleckner. * Ed Pelegri-Llopart added C typedefs. * Gnu Emacs TAGS format and modifications by RMS? - * Sam Kendall added C++. - * Francesco Potorti` reorganised C and C++ based on work by Joe Wells. - * Regexp tags by Tom Tromey. + * 1989 Sam Kendall added C++. + * 1993 Francesco Potortì reorganised C and C++ based on work by Joe Wells. + * 1994 Regexp tags by Tom Tromey. + * 2001 Nested classes by Francesco Potortì based on work by Mykola Dzyuba. * - * Francesco Potorti` (pot@gnu.org) is the current maintainer. - * Ansified by Martin Buchholz, 19991105. + * Francesco Potortì has maintained it since 1993. */ -char pot_etags_version[] = "@(#) pot revision number is 13.33"; +char pot_etags_version[] = "@(#) pot revision number is 14.15"; #define TRUE 1 #define FALSE 0 -#ifndef _GNU_SOURCE -# define _GNU_SOURCE /* enables some compiler checks on GNU */ +#ifdef DEBUG +# undef DEBUG +# define DEBUG TRUE +#else +# define DEBUG FALSE +# define NDEBUG /* disable assert */ #endif -#ifndef DEBUG -# define DEBUG FALSE + +#if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C)) +# define P_(proto) proto +#else +# define P_(proto) () #endif #ifdef HAVE_CONFIG_H @@ -53,7 +60,21 @@ char pot_etags_version[] = "@(#) pot revision number is 13.33"; # define LONG_OPTIONS /* accept long options */ #endif /* HAVE_CONFIG_H */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 /* enables some compiler checks on GNU */ +#endif + +/* WIN32_NATIVE is for Xemacs. + MSDOS, WINDOWSNT, DOS_NT are for Emacs. */ +#ifdef WIN32_NATIVE +# undef MSDOS +# undef WINDOWSNT +# define WINDOWSNT +#endif /* WIN32_NATIVE */ + #ifdef MSDOS +# undef MSDOS +# define MSDOS TRUE # include # include # include @@ -61,34 +82,37 @@ char pot_etags_version[] = "@(#) pot revision number is 13.33"; # define DOS_NT # include # endif +#else +# define MSDOS FALSE #endif /* MSDOS */ #ifdef WINDOWSNT # include # include # include +# include # include # define MAXPATHLEN _MAX_PATH -# ifdef HAVE_CONFIG_H -# undef HAVE_NTGUI -# else -# define DOS_NT -# endif /* not HAVE_CONFIG_H */ +# undef HAVE_NTGUI +# undef DOS_NT +# define DOS_NT # ifndef HAVE_GETCWD # define HAVE_GETCWD # endif /* undef HAVE_GETCWD */ -#endif /* WINDOWSNT */ - -#if !defined (WINDOWSNT) && defined (STDC_HEADERS) -#include -#include -#endif +#else /* !WINDOWSNT */ +# ifdef STDC_HEADERS +# include +# include +# else + extern char *getenv (); +# endif +#endif /* !WINDOWSNT */ #ifdef HAVE_UNISTD_H # include #else -# ifdef HAVE_GETCWD - extern char *getcwd (); +# if defined (HAVE_GETCWD) && !defined (WINDOWSNT) + extern char *getcwd (char *buf, size_t size); # endif #endif /* HAVE_UNISTD_H */ @@ -101,6 +125,12 @@ char pot_etags_version[] = "@(#) pot revision number is 13.33"; #include #include +#include +#ifdef NDEBUG +# undef assert /* some systems have a buggy assert.h */ +# define assert(x) ((void) 0) +#endif + #if !defined (S_ISREG) && defined (S_IFREG) # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif @@ -136,48 +166,47 @@ char pot_etags_version[] = "@(#) pot revision number is 13.33"; # define BAD 1 #endif -/* C extensions. */ -#define C_PLPL 0x00001 /* C++ */ -#define C_STAR 0x00003 /* C* */ -#define C_JAVA 0x00005 /* JAVA */ -#define YACC 0x10000 /* yacc file */ - -#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 ((char)c) +#define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t)) +#define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n)) #define CHARS 256 /* 2^sizeof(char) */ -#define CHAR(x) ((unsigned int)x & (CHARS - 1)) +#define CHAR(x) ((unsigned int)(x) & (CHARS - 1)) #define iswhite(c) (_wht[CHAR(c)]) /* c is white */ #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ +#define ISALNUM(c) isalnum (CHAR(c)) +#define ISALPHA(c) isalpha (CHAR(c)) +#define ISDIGIT(c) isdigit (CHAR(c)) +#define ISLOWER(c) islower (CHAR(c)) + +#define lowcase(c) tolower (CHAR(c)) +#define upcase(c) toupper (CHAR(c)) + /* * xnew, xrnew -- allocate, reallocate storage * * SYNOPSIS: Type *xnew (int n, Type); - * Type *xrnew (OldPointer, int n, Type); + * void xrnew (OldPointer, int n, Type); */ -#ifdef chkmalloc +#if DEBUG # include "chkmalloc.h" # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \ (n) * sizeof (Type))) -# define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \ - (op), (n) * sizeof (Type))) +# define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \ + (char *) (op), (n) * sizeof (Type))) #else # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) -# define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type))) +# define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \ + (char *) (op), (n) * sizeof (Type))) #endif typedef int bool; -typedef void Lang_function (); +typedef void Lang_function P_((FILE *)); typedef struct { @@ -189,12 +218,11 @@ typedef struct { char *name; Lang_function *function; + char **filenames; char **suffixes; char **interpreters; } language; -extern char *getenv (); - typedef struct node_st { /* sorting structure */ char *name; /* function or type name */ @@ -224,74 +252,82 @@ typedef struct /* Many compilers barf on this: Lang_function Ada_funcs; so let's write it this way */ -void Ada_funcs (FILE *inf); -void Asm_labels (FILE *inf); -void C_entries (int c_ext, FILE *inf); -void default_C_entries (FILE *inf); -void plain_C_entries (FILE *inf); -void Cjava_entries (FILE *inf); -void Cobol_paragraphs (FILE *inf); -void Cplusplus_entries (FILE *inf); -void Cstar_entries (FILE *inf); -void Erlang_functions (FILE *inf); -void Fortran_functions (FILE *inf); -void Yacc_entries (FILE *inf); -void Lisp_functions (FILE *inf); -void Pascal_functions (FILE *inf); -void Perl_functions (FILE *inf); -void Postscript_functions (FILE *inf); -void Prolog_functions (FILE *inf); -void Python_functions (FILE *inf); -void Scheme_functions (FILE *inf); -void TeX_functions (FILE *inf); -void just_read_file (FILE *inf); - -compressor *get_compressor_from_suffix (char *file, char **extptr); -language *get_language_from_name (char *name); -language *get_language_from_interpreter (char *interpreter); -language *get_language_from_suffix (char *file); -int total_size_of_entries (register node *np); -long readline (linebuffer *lbp, FILE *stream); -long readline_internal (linebuffer *lbp, register FILE *stream); -void get_tag (register char *bp); +static void Ada_funcs P_((FILE *)); +static void Asm_labels P_((FILE *)); +static void C_entries P_((int c_ext, FILE *)); +static void default_C_entries P_((FILE *)); +static void plain_C_entries P_((FILE *)); +static void Cjava_entries P_((FILE *)); +static void Cobol_paragraphs P_((FILE *)); +static void Cplusplus_entries P_((FILE *)); +static void Cstar_entries P_((FILE *)); +static void Erlang_functions P_((FILE *)); +static void Fortran_functions P_((FILE *)); +static void Yacc_entries P_((FILE *)); +static void Lisp_functions P_((FILE *)); +static void Makefile_targets P_((FILE *)); +static void Pascal_functions P_((FILE *)); +static void Perl_functions P_((FILE *)); +static void Postscript_functions P_((FILE *)); +static void Prolog_functions P_((FILE *)); +static void Python_functions P_((FILE *)); +static void Scheme_functions P_((FILE *)); +static void TeX_commands P_((FILE *)); +static void Texinfo_nodes P_((FILE *)); +static void just_read_file P_((FILE *)); + +static void print_language_names P_((void)); +static void print_version P_((void)); +static void print_help P_((void)); +int main P_((int, char **)); +static int number_len P_((long)); + +static compressor *get_compressor_from_suffix P_((char *, char **)); +static language *get_language_from_langname P_((char *)); +static language *get_language_from_interpreter P_((char *)); +static language *get_language_from_filename P_((char *)); +static int total_size_of_entries P_((node *)); +static long readline P_((linebuffer *, FILE *)); +static long readline_internal P_((linebuffer *, FILE *)); +static void get_tag P_((char *)); #ifdef ETAGS_REGEXPS -void analyse_regex (char *regex_arg, bool ignore_case); -void add_regex (char *regexp_pattern, bool ignore_case, language *lan); -void free_patterns (void); +static void analyse_regex P_((char *, bool)); +static void add_regex P_((char *, bool, language *)); +static void free_patterns P_((void)); #endif /* ETAGS_REGEXPS */ -void error (const char *s1, const char *s2); -void suggest_asking_for_help (void); -void fatal (char *s1, char *s2); -void pfatal (char *s1); -void add_node (node *np, node **cur_node_p); - -void init (void); -void initbuffer (linebuffer *lbp); -void find_entries (char *file, FILE *inf); -void free_tree (register node *np); -void pfnote (char *name, bool is_func, char *linestart, int linelen, int lno, long int cno); -void new_pfnote (char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long int cno); -void process_file (char *file); -void put_entries (register node *np); -void takeprec (void); - -char *concat (char *s1, char *s2, char *s3); -char *skip_spaces (char *cp); -char *skip_non_spaces (char *cp); -char *savenstr (char *cp, int len); -char *savestr (char *cp); -char *etags_strchr (char *sp, char c); -char *etags_strrchr (char *sp, char c); -char *etags_getcwd (void); -char *relative_filename (char *file, char *dir); -char *absolute_filename (char *file, char *dir); -char *absolute_dirname (char *file, char *dir); -bool filename_is_absolute (char *fn); -void canonicalize_filename (register char *fn); -void grow_linebuffer (linebuffer *lbp, int toksize); -long *xmalloc (unsigned int size); -long *xrealloc (char *ptr, unsigned int size); +static void error P_((const char *, const char *)); +static void suggest_asking_for_help P_((void)); +void fatal P_((char *, char *)); +static void pfatal P_((char *)); +static void add_node P_((node *, node **)); + +static void init P_((void)); +static void initbuffer P_((linebuffer *)); +static void find_entries P_((char *, FILE *)); +static void free_tree P_((node *)); +static void pfnote P_((char *, bool, char *, int, int, long)); +static void new_pfnote P_((char *, int, bool, char *, int, int, long)); +static void process_file P_((char *)); +static void put_entries P_((node *)); +static void takeprec P_((void)); + +static char *concat P_((char *, char *, char *)); +static char *skip_spaces P_((char *)); +static char *skip_non_spaces P_((char *)); +static char *savenstr P_((char *, int)); +static char *savestr P_((char *)); +static char *etags_strchr P_((const char *, int)); +static char *etags_strrchr P_((const char *, int)); +static char *etags_getcwd P_((void)); +static char *relative_filename P_((char *, char *)); +static char *absolute_filename P_((char *, char *)); +static char *absolute_dirname P_((char *, char *)); +static bool filename_is_absolute P_((char *f)); +static void canonicalize_filename P_((char *)); +static void linebuffer_setlen P_((linebuffer *, int)); +long *xmalloc P_((unsigned int)); +long *xrealloc P_((char *, unsigned int)); char searchar = '/'; /* use /.../ searches */ @@ -313,18 +349,12 @@ char *dbp; /* pointer to start of current tag */ node *head; /* the head of the binary tree of tags */ linebuffer lb; /* the current line */ -linebuffer token_name; /* used by C_entries as a temporary area */ -struct -{ - long linepos; - linebuffer lb; /* used by C_entries instead of lb */ -} lbs[2]; /* boolean "functions" (see init) */ bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; char /* white chars */ - *white = " \f\t\n\r", + *white = " \f\t\n\r\v", /* not in a name */ *nonam = " \f\t\n\r(=,[;", /* token ending chars */ @@ -337,7 +367,7 @@ char bool append_to_tagfile; /* -a: append to tags */ /* The following four default to TRUE for etags, but to FALSE for ctags. */ bool typedefs; /* -t: create tags for C and Ada typedefs */ -bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */ +bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ /* 0 struct/enum/union decls, and C++ */ /* member functions. */ bool constantypedefs; /* -d: create tags for C #define, enum */ @@ -447,12 +477,13 @@ char *Asm_suffixes [] = { "a", /* Unix assembler */ }; /* Note that .c and .h can be considered C++, if the --c++ flag was - given. That is why default_C_entries is called here. */ + given, or if the `class' keyowrd is met inside the file. + That is why default_C_entries is called for these. */ char *default_C_suffixes [] = { "c", "h", NULL }; char *Cplusplus_suffixes [] = - { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx", + { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx", "M", /* Objective C++ */ "pdb", /* Postscript with C syntax */ NULL }; @@ -473,7 +504,10 @@ char *Fortran_suffixes [] = { "F", "f", "f90", "for", NULL }; char *Lisp_suffixes [] = - { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL }; + { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL }; + +char *Makefile_filenames [] = + { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL}; char *Pascal_suffixes [] = { "p", "pas", NULL }; @@ -484,9 +518,9 @@ char *Perl_interpreters [] = { "perl", "@PERL@", NULL }; char *plain_C_suffixes [] = - { "pc", /* Pro*C file */ + { "lm", /* Objective lex file */ "m", /* Objective C file */ - "lm", /* Objective lex file */ + "pc", /* Pro*C file */ NULL }; char *Postscript_suffixes [] = @@ -500,13 +534,16 @@ char *Python_suffixes [] = /* Can't do the `SCM' or `scm' prefix with a version number. */ char *Scheme_suffixes [] = - { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL }; + { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL }; char *TeX_suffixes [] = - { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL }; + { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL }; + +char *Texinfo_suffixes [] = + { "texi", "texinfo", "txi", NULL }; char *Yacc_suffixes [] = - { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */ + { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */ /* * Table of languages. @@ -517,41 +554,47 @@ char *Yacc_suffixes [] = language lang_names [] = { - { "ada", Ada_funcs, Ada_suffixes, NULL }, - { "asm", Asm_labels, Asm_suffixes, NULL }, - { "c", default_C_entries, default_C_suffixes, NULL }, - { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, - { "c*", Cstar_entries, Cstar_suffixes, NULL }, - { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL }, - { "erlang", Erlang_functions, Erlang_suffixes, NULL }, - { "fortran", Fortran_functions, Fortran_suffixes, NULL }, - { "java", Cjava_entries, Cjava_suffixes, NULL }, - { "lisp", Lisp_functions, Lisp_suffixes, NULL }, - { "pascal", Pascal_functions, Pascal_suffixes, NULL }, - { "perl", Perl_functions, Perl_suffixes, Perl_interpreters }, - { "postscript", Postscript_functions, Postscript_suffixes, NULL }, - { "proc", plain_C_entries, plain_C_suffixes, NULL }, - { "prolog", Prolog_functions, Prolog_suffixes, NULL }, - { "python", Python_functions, Python_suffixes, NULL }, - { "scheme", Scheme_functions, Scheme_suffixes, NULL }, - { "tex", TeX_functions, TeX_suffixes, NULL }, - { "yacc", Yacc_entries, Yacc_suffixes, NULL }, + { "ada", Ada_funcs, NULL, Ada_suffixes, NULL }, + { "asm", Asm_labels, NULL, Asm_suffixes, NULL }, + { "c", default_C_entries, NULL, default_C_suffixes, NULL }, + { "c++", Cplusplus_entries, NULL, Cplusplus_suffixes, NULL }, + { "c*", Cstar_entries, NULL, Cstar_suffixes, NULL }, + { "cobol", Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, + { "erlang", Erlang_functions, NULL, Erlang_suffixes, NULL }, + { "fortran", Fortran_functions, NULL, Fortran_suffixes, NULL }, + { "java", Cjava_entries, NULL, Cjava_suffixes, NULL }, + { "lisp", Lisp_functions, NULL, Lisp_suffixes, NULL }, + { "makefile", Makefile_targets, Makefile_filenames, NULL, NULL }, + { "pascal", Pascal_functions, NULL, Pascal_suffixes, NULL }, + { "perl", Perl_functions, NULL, Perl_suffixes, Perl_interpreters }, + { "postscript", Postscript_functions, NULL, Postscript_suffixes, NULL }, + { "proc", plain_C_entries, NULL, plain_C_suffixes, NULL }, + { "prolog", Prolog_functions, NULL, Prolog_suffixes, NULL }, + { "python", Python_functions, NULL, Python_suffixes, NULL }, + { "scheme", Scheme_functions, NULL, Scheme_suffixes, NULL }, + { "tex", TeX_commands, NULL, TeX_suffixes, NULL }, + { "texinfo", Texinfo_nodes, NULL, Texinfo_suffixes, NULL }, + { "yacc", Yacc_entries, NULL, Yacc_suffixes, NULL }, { "auto", NULL }, /* default guessing scheme */ { "none", just_read_file }, /* regexp matching only */ { NULL, NULL } /* end of list */ }; + static void print_language_names () { language *lang; - char **ext; + char **name, **ext; puts ("\nThese are the currently supported languages, along with the\n\ -default file name suffixes:"); +default file names and dot suffixes:"); for (lang = lang_names; lang->name != NULL; lang++) { - printf ("\t%s\t", lang->name); + printf (" %-*s", 10, lang->name); + if (lang->filenames != NULL) + for (name = lang->filenames; *name != NULL; name++) + printf (" %s", *name); if (lang->suffixes != NULL) for (ext = lang->suffixes; *ext != NULL; ext++) printf (" .%s", *ext); @@ -563,22 +606,20 @@ 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\ Fortran is tried first; if no tags are found, C is tried next.\n\ +When parsing any C file, a \"class\" keyword switches to C++.\n\ Compressed files are supported using gzip and bzip2."); } -#ifdef XEMACS -# define EMACS_NAME "XEmacs" -#else +#ifndef EMACS_NAME # define EMACS_NAME "GNU Emacs" #endif - #ifndef VERSION -# define VERSION "20" +# define VERSION "21" #endif static void print_version () { - printf ("%s (" EMACS_NAME " %s)\n", (CTAGS) ? "ctags" : "etags", VERSION); + printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION); puts ("Copyright (C) 1999 Free Software Foundation, Inc. and Ken Arnold"); puts ("This program is distributed under the same terms as Emacs"); @@ -614,8 +655,13 @@ Relative ones are stored relative to the output file's directory."); Write the search commands for the tag entries using '?', the\n\ backward-search command instead of '/', the forward-search command."); + /* This option is mostly obsolete, because etags can now automatically + detect C++. Retained for backward compatibility and for debugging and + experimentation. In principle, we could want to tag as C++ even + before any "class" keyword. puts ("-C, --c++\n\ Treat files whose name suffix defaults to C language as C++ files."); + */ puts ("--declarations\n\ In C and derived languages, create tags for function declarations,"); @@ -766,7 +812,7 @@ typedef struct { #include #include #define OUTSIZE MAX_FILE_SPEC_LEN -short +static short fn_exp (out, in) vspec *out; char *in; @@ -811,7 +857,7 @@ fn_exp (out, in) v1.01 nmm 19-Aug-85 gfnames - return in successive calls the name of each file specified by the provided arg expanding wildcards. */ -char * +static char * gfnames (arg, p_error) char *arg; bool *p_error; @@ -899,13 +945,14 @@ main (argc, argv) /* * If etags, always find typedefs and structure tags. Why not? - * Also default is to find macro constants, enum constants and + * Also default to find macro constants, enum constants and * global variables. */ if (!CTAGS) { - typedefs = typedefs_and_cplusplus = constantypedefs = TRUE; + typedefs = typedefs_or_cplusplus = constantypedefs = TRUE; globals = TRUE; + declarations = FALSE; members = FALSE; } @@ -963,7 +1010,7 @@ main (argc, argv) break; case 'l': { - language *lang = get_language_from_name (optarg); + language *lang = get_language_from_langname (optarg); if (lang != NULL) { argbuffer[current_arg].lang = lang; @@ -1000,7 +1047,7 @@ main (argc, argv) typedefs = TRUE; break; case 'T': - typedefs = typedefs_and_cplusplus = TRUE; + typedefs = typedefs_or_cplusplus = TRUE; break; #if (!CTAGS) /* Etags options */ @@ -1051,9 +1098,6 @@ main (argc, argv) init (); /* set up boolean "functions" */ initbuffer (&lb); - initbuffer (&token_name); - initbuffer (&lbs[0].lb); - initbuffer (&lbs[1].lb); initbuffer (&filename_lb); if (!CTAGS) @@ -1185,9 +1229,9 @@ main (argc, argv) * return a pointer into FILE where the compressor-specific * extension begins. If no compressor is found, NULL is returned * and EXTPTR is not significant. - * Idea by Vladimir Alexiev + * Idea by Vladimir Alexiev (1998) */ -compressor * +static compressor * get_compressor_from_suffix (file, extptr) char *file; char **extptr; @@ -1212,9 +1256,8 @@ get_compressor_from_suffix (file, extptr) for (compr = compressors; compr->suffix != NULL; compr++) if (streq (compr->suffix, suffix)) return compr; -#ifndef MSDOS - break; -#endif + if (!MSDOS) + break; /* do it only once: not really a loop */ if (extptr != NULL) *extptr = ++suffix; } while (*suffix != '\0'); @@ -1226,8 +1269,8 @@ get_compressor_from_suffix (file, extptr) /* * Return a language given the name. */ -language * -get_language_from_name (name) +static language * +get_language_from_langname (name) char *name; { language *lang; @@ -1249,7 +1292,7 @@ get_language_from_name (name) /* * Return a language given the interpreter name. */ -language * +static language * get_language_from_interpreter (interpreter) char *interpreter; { @@ -1272,13 +1315,21 @@ get_language_from_interpreter (interpreter) /* * Return a language given the file name. */ -language * -get_language_from_suffix (file) +static language * +get_language_from_filename (file) char *file; { language *lang; - char **ext, *suffix; + char **name, **ext, *suffix; + /* Try whole file name first. */ + for (lang = lang_names; lang->name != NULL; lang++) + if (lang->filenames != NULL) + for (name = lang->filenames; *name != NULL; name++) + if (streq (*name, file)) + return lang; + + /* If not found, try suffix after last dot. */ suffix = etags_strrchr (file, '.'); if (suffix == NULL) return NULL; @@ -1296,7 +1347,7 @@ get_language_from_suffix (file) /* * This routine is called on each file argument. */ -void +static void process_file (file) char *file; { @@ -1360,21 +1411,22 @@ process_file (file) compressed_name = concat (file, ".", compr->suffix); if (stat (compressed_name, &stat_buf) != 0) { -#ifdef MSDOS - char *suf = compressed_name + strlen (file); - size_t suflen = strlen (compr->suffix) + 1; - for ( ; suf[1]; suf++, suflen--) + if (MSDOS) { - memmove (suf, suf + 1, suflen); - if (stat (compressed_name, &stat_buf) == 0) + char *suf = compressed_name + strlen (file); + size_t suflen = strlen (compr->suffix) + 1; + for ( ; suf[1]; suf++, suflen--) { - real_name = compressed_name; - break; + memmove (suf, suf + 1, suflen); + if (stat (compressed_name, &stat_buf) == 0) + { + real_name = compressed_name; + break; + } } - } - if (real_name != NULL) - break; -#endif + if (real_name != NULL) + break; + } /* MSDOS */ free (compressed_name); compressed_name = NULL; } @@ -1400,7 +1452,7 @@ process_file (file) if (real_name == compressed_name) { char *cmd = concat (compr->command, " ", real_name); - inf = popen (cmd, "r"); + inf = (FILE *) popen (cmd, "r"); free (cmd); } else @@ -1454,7 +1506,7 @@ process_file (file) * subscripted by the chars in "white" are set to TRUE. Thus "_wht" * of a char is TRUE if it is the string "white", else FALSE. */ -void +static void init () { register char *sp; @@ -1464,13 +1516,12 @@ init () iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE; for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE; for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE; - for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE; - for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE; - for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE; - iswhite('\0') = iswhite('\n'); notinname('\0') = notinname('\n'); + for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE; begtoken('\0') = begtoken('\n'); + for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE; intoken('\0') = intoken('\n'); + for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE; endtoken('\0') = endtoken('\n'); } @@ -1480,7 +1531,7 @@ init () */ node *last_node = NULL; -void +static void find_entries (file, inf) char *file; FILE *inf; @@ -1506,7 +1557,7 @@ find_entries (file, inf) } /* Try to guess the language given the file name. */ - lang = get_language_from_suffix (file); + lang = get_language_from_filename (file); if (lang != NULL && lang->function != NULL) { curlang = lang; @@ -1551,7 +1602,7 @@ find_entries (file, inf) /* Try Fortran. */ old_last_node = last_node; - curlang = get_language_from_name ("fortran"); + curlang = get_language_from_langname ("fortran"); Fortran_functions (inf); /* No Fortran entries found. Try C. */ @@ -1560,14 +1611,15 @@ find_entries (file, inf) /* We do not tag if rewind fails. Only the file name will be recorded in the tags file. */ rewind (inf); - curlang = get_language_from_name (cplusplus ? "c++" : "c"); + curlang = get_language_from_langname (cplusplus ? "c++" : "c"); default_C_entries (inf); } return; } + /* Record a tag. */ -void +static void pfnote (name, is_func, linestart, linelen, lno, cno) char *name; /* tag name, or NULL if unnamed */ bool is_func; /* tag is a function */ @@ -1618,10 +1670,9 @@ pfnote (name, is_func, linestart, linelen, lno, cno) add_node (np, &head); } -/* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997] - * From: Sam Kendall - * Subject: Proposal for firming up the TAGS format specification - * To: F.Potorti@cnuce.cnr.it +/* + * TAGS format specification + * Idea by Sam Kendall (1997) * * pfnote should emit the optimized form [unnamed tag] only if: * 1. name does not contain any of the characters " \t\r\n(),;"; @@ -1637,7 +1688,7 @@ pfnote (name, is_func, linestart, linelen, lno, cno) * `nonam'. */ #define traditional_tag_style TRUE -void +static void new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) char *name; /* tag name, or NULL if unnamed */ int namelen; /* tag length */ @@ -1679,7 +1730,7 @@ new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) * free_tree () * recurse on left children, iterate on right children. */ -void +static void free_tree (np) register node *np; { @@ -1704,7 +1755,7 @@ free_tree (np) * add_node is the only function allowed to add nodes, so it can * maintain state. */ -void +static void add_node (np, cur_node_p) node *np, **cur_node_p; { @@ -1761,8 +1812,9 @@ add_node (np, cur_node_p) add_node (np, dif < 0 ? &cur_node->left : &cur_node->right); } } + -void +static void put_entries (np) register node *np; { @@ -1846,7 +1898,7 @@ number_len (num) * is irrelevant with the new tags.el, but is still supplied for * backward compatibility. */ -int +static int total_size_of_entries (np) register node *np; { @@ -1869,7 +1921,17 @@ total_size_of_entries (np) return total; } + +/* C extensions. */ +#define C_EXT 0x00fff /* C extensions */ +#define C_PLAIN 0x00000 /* C */ +#define C_PLPL 0x00001 /* C++ */ +#define C_STAR 0x00003 /* C* */ +#define C_JAVA 0x00005 /* JAVA */ +#define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */ +#define YACC 0x10000 /* yacc file */ + /* * The C symbol tables. */ @@ -1881,11 +1943,17 @@ enum sym_type st_C_ignore, st_C_javastruct, st_C_operator, + st_C_class, st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec }; +static unsigned int hash P_((const char *, unsigned int)); +static struct C_stab_entry * in_word_set P_((const char *, unsigned int)); +static enum sym_type C_symtype P_((char *, int, int)); + /* Feed stuff between (but not including) %[ and %] lines to: gperf -c -k 1,3 -o -p -r -t + then put a `static' keyword in front of the in_word_set function. %[ struct C_stab_entry { char *name; int c_ext; enum sym_type type; } %% @@ -1904,7 +1972,7 @@ friend, C_PLPL, st_C_ignore extends, C_JAVA, st_C_javastruct implements, C_JAVA, st_C_javastruct interface, C_JAVA, st_C_struct -class, C_PLPL, st_C_struct +class, 0, st_C_class namespace, C_PLPL, st_C_struct domain, C_STAR, st_C_struct union, 0, st_C_struct @@ -1941,7 +2009,8 @@ PSEUDO, 0, st_C_gnumacro #EXFUN, 0, st_C_gnumacro #DEFVAR_, 0, st_C_gnumacro %] -and replace lines between %< and %> with its output. */ +and replace lines between %< and %> with its output, +then make in_word_set static. */ /*%<*/ /* C code produced by gperf version 2.7.1 (19981006 egcs) */ /* Command-line: gperf -c -k 1,3 -o -p -r -t */ @@ -1951,8 +2020,8 @@ struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 15 #define MIN_HASH_VALUE 13 -#define MAX_HASH_VALUE 123 -/* maximum key range = 111, duplicates = 0 */ +#define MAX_HASH_VALUE 121 +/* maximum key range = 109, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -1964,32 +2033,32 @@ hash (str, len) { static unsigned char asso_values[] = { - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 3, 124, 124, 124, 43, 6, - 11, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 11, 124, 124, 58, 7, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 57, 7, 42, - 4, 14, 52, 0, 124, 53, 124, 124, 29, 11, - 6, 35, 32, 124, 29, 34, 59, 58, 51, 24, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124 + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 57, 122, 122, 122, 55, 6, + 60, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 51, 122, 122, 10, 2, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 2, 52, 59, + 49, 38, 56, 41, 122, 22, 122, 122, 9, 32, + 33, 60, 26, 122, 1, 28, 46, 59, 44, 51, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122 }; register int hval = len; @@ -2018,77 +2087,76 @@ in_word_set (str, len) { {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {"@end", 0, st_C_objend}, - {""}, {""}, {""}, {""}, {"ENTRY", 0, st_C_gnumacro}, - {"@interface", 0, st_C_objprot}, - {""}, - {"domain", C_STAR, st_C_struct}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {"PSEUDO", 0, st_C_gnumacro}, - {""}, {""}, - {"namespace", C_PLPL, st_C_struct}, + {"if", 0, st_C_ignore}, {""}, {""}, - {"@implementation",0, st_C_objimpl}, + {"SYSCALL", 0, st_C_gnumacro}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {"struct", 0, st_C_struct}, + {"static", 0, st_C_typespec}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"long", 0, st_C_typespec}, - {"signed", 0, st_C_typespec}, - {"@protocol", 0, st_C_objprot}, - {""}, {""}, {""}, {""}, - {"bool", C_PLPL, st_C_typespec}, - {""}, {""}, {""}, {""}, {""}, {""}, - {"const", 0, st_C_typespec}, - {"explicit", C_PLPL, st_C_typespec}, - {"if", 0, st_C_ignore}, - {""}, - {"operator", C_PLPL, st_C_operator}, - {""}, - {"DEFUN", 0, st_C_gnumacro}, - {""}, {""}, - {"define", 0, st_C_define}, {""}, {""}, {""}, {""}, {""}, - {"double", 0, st_C_typespec}, - {"struct", 0, st_C_struct}, - {""}, {""}, {""}, {""}, - {"short", 0, st_C_typespec}, + {"auto", 0, st_C_typespec}, + {"return", 0, st_C_ignore}, + {"import", C_JAVA, st_C_ignore}, {""}, - {"enum", 0, st_C_enum}, - {"mutable", C_PLPL, st_C_typespec}, + {"switch", 0, st_C_ignore}, {""}, - {"extern", 0, st_C_extern}, - {"extends", C_JAVA, st_C_javastruct}, - {"package", C_JAVA, st_C_ignore}, - {"while", 0, st_C_ignore}, + {"implements", C_JAVA, st_C_javastruct}, {""}, {"for", 0, st_C_ignore}, - {""}, {""}, {""}, {"volatile", 0, st_C_typespec}, + {""}, + {"PSEUDO", 0, st_C_gnumacro}, + {""}, + {"char", 0, st_C_typespec}, + {"class", 0, st_C_class}, + {"@protocol", 0, st_C_objprot}, {""}, {""}, - {"import", C_JAVA, st_C_ignore}, - {"float", 0, st_C_typespec}, - {"switch", 0, st_C_ignore}, - {"return", 0, st_C_ignore}, - {"implements", C_JAVA, st_C_javastruct}, + {"void", 0, st_C_typespec}, + {"int", 0, st_C_typespec}, + {"explicit", C_PLPL, st_C_typespec}, {""}, - {"static", 0, st_C_typespec}, + {"namespace", C_PLPL, st_C_struct}, + {"signed", 0, st_C_typespec}, + {""}, + {"interface", C_JAVA, st_C_struct}, + {"while", 0, st_C_ignore}, {"typedef", 0, st_C_typedef}, {"typename", C_PLPL, st_C_typespec}, - {"unsigned", 0, st_C_typespec}, - {""}, {""}, - {"char", 0, st_C_typespec}, - {"class", C_PLPL, st_C_struct}, {""}, {""}, {""}, - {"void", 0, st_C_typespec}, - {""}, {""}, {"friend", C_PLPL, st_C_ignore}, - {""}, {""}, {""}, - {"int", 0, st_C_typespec}, + {"mutable", C_PLPL, st_C_typespec}, {"union", 0, st_C_struct}, - {""}, {""}, {""}, - {"auto", 0, st_C_typespec}, - {"interface", C_JAVA, st_C_struct}, + {"domain", C_STAR, st_C_struct}, + {""}, {""}, + {"extern", 0, st_C_extern}, + {"extends", C_JAVA, st_C_javastruct}, + {"package", C_JAVA, st_C_ignore}, + {"short", 0, st_C_typespec}, + {"@end", 0, st_C_objend}, + {"unsigned", 0, st_C_typespec}, {""}, - {"SYSCALL", 0, st_C_gnumacro} + {"const", 0, st_C_typespec}, + {""}, {""}, + {"@interface", 0, st_C_objprot}, + {"enum", 0, st_C_enum}, + {""}, {""}, + {"@implementation",0, st_C_objimpl}, + {""}, + {"operator", C_PLPL, st_C_operator}, + {""}, {""}, {""}, {""}, + {"define", 0, st_C_define}, + {""}, {""}, + {"double", 0, st_C_typespec}, + {""}, + {"bool", C_PLPL, st_C_typespec}, + {""}, {""}, {""}, + {"DEFUN", 0, st_C_gnumacro}, + {"float", 0, st_C_typespec} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -2119,14 +2187,17 @@ C_symtype (str, len, c_ext) return st_none; return se->type; } + - /* - * C functions and variables are recognized using a simple - * finite automaton. fvdef is its state variable. - */ +/* + * C functions and variables are recognized using a simple + * finite automaton. fvdef is its state variable. + */ enum { fvnone, /* nothing seen */ + fdefunkey, /* Emacs DEFUN keyword seen */ + fdefunname, /* Emacs DEFUN name seen */ foperator, /* func: operator keyword seen (cplpl) */ fvnameseen, /* function or variable name seen */ fstartlist, /* func: just after open parenthesis */ @@ -2138,10 +2209,10 @@ enum bool fvextern; /* func or var: extern keyword seen; */ - /* - * typedefs are recognized using a simple finite automaton. - * typdef is its state variable. - */ +/* + * typedefs are recognized using a simple finite automaton. + * typdef is its state variable. + */ enum { tnone, /* nothing seen */ @@ -2152,30 +2223,22 @@ enum tignore /* junk after typedef tag */ } typdef; - - /* - * struct-like structures (enum, struct and union) are recognized - * using another simple finite automaton. `structdef' is its state - * variable. - */ +/* + * struct-like structures (enum, struct and union) are recognized + * using another simple finite automaton. `structdef' is its state + * variable. + */ enum { - snone, /* nothing seen yet */ + snone, /* nothing seen yet, + or in struct body if cblev > 0 */ 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*/ + sintemplate, /* inside template (ignore) */ + scolonseen /* colon seen after struct-like tag */ } structdef; /* - * When structdef is stagseen, scolonseen, or sinbody, structtag is the - * struct tag, and structtype is the type of the preceding struct-like - * keyword. - */ -char *structtag = ""; -enum sym_type structtype; - -/* * When objdef is different from onone, objtag is the name of the class. */ char *objtag = ""; @@ -2193,7 +2256,7 @@ enum /* * State machine for Objective C protocols and implementations. - * Tom R.Hageman + * Idea by Tom R.Hageman (1995) */ enum { @@ -2216,34 +2279,115 @@ enum * Use this structure to keep info about the token read, and how it * should be tagged. Used by the make_C_tag function to build a tag. */ -typedef struct +struct tok { bool valid; - char *str; bool named; - int linelen; + int offset; + int length; int lineno; long linepos; - char *buffer; -} token; - -token tok; /* latest token read */ + char *line; +} token; /* latest token read */ +linebuffer token_name; /* its name */ /* - * Set this to TRUE, and the next token considered is called a function. - * Used only for GNU emacs's function-defining macros. + * Variables and functions for dealing with nested structures. + * Idea by Mykola Dzyuba (2001) */ -bool next_token_is_func; +static void pushclass_above P_((int, char *, int)); +static void popclass_above P_((int)); +static void write_classname P_((linebuffer *, char *qualifier)); + +struct { + char **cname; /* nested class names */ + int *cblev; /* nested class curly brace level */ + int nl; /* class nesting level (elements used) */ + int size; /* length of the array */ +} cstack; /* stack for nested declaration tags */ +/* Current struct nesting depth (namespace, class, struct, union, enum). */ +#define nestlev (cstack.nl) +/* After struct keyword or in struct body, not inside an nested function. */ +#define instruct (structdef == snone && nestlev > 0 \ + && cblev == cstack.cblev[nestlev-1] + 1) -/* - * TRUE in the rules part of a yacc file, FALSE outside (parse as C). - */ -bool yacc_rules; +static void +pushclass_above (cblev, str, len) + int cblev; + char *str; + int len; +{ + int nl; -/* - * methodlen is the length of the method name stored in token_name. - */ -int methodlen; + popclass_above (cblev); + nl = cstack.nl; + if (nl >= cstack.size) + { + int size = cstack.size *= 2; + xrnew (cstack.cname, size, char *); + xrnew (cstack.cblev, size, int); + } + assert (nl == 0 || cstack.cblev[nl-1] < cblev); + cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len); + cstack.cblev[nl] = cblev; + cstack.nl = nl + 1; +} + +static void +popclass_above (cblev) + int cblev; +{ + int nl; + + for (nl = cstack.nl - 1; + nl >= 0 && cstack.cblev[nl] >= cblev; + nl--) + { + if (cstack.cname[nl] != NULL) + free (cstack.cname[nl]); + cstack.nl = nl; + } +} + +static void +write_classname (cn, qualifier) + linebuffer *cn; + char *qualifier; +{ + int i, len; + int qlen = strlen (qualifier); + + if (cstack.nl == 0 || cstack.cname[0] == NULL) + { + len = 0; + cn->len = 0; + cn->buffer[0] = '\0'; + } + else + { + len = strlen (cstack.cname[0]); + linebuffer_setlen (cn, len); + strcpy (cn->buffer, cstack.cname[0]); + } + for (i = 1; i < cstack.nl; i++) + { + char *s; + int slen; + + s = cstack.cname[i]; + if (s == NULL) + continue; + slen = strlen (s); + len += slen + qlen; + linebuffer_setlen (cn, len); + strncat (cn->buffer, qualifier, qlen); + strncat (cn->buffer, s, slen); + } +} + + +static bool consider_token P_((char *, int, int, int *, int, int, bool *)); +static void make_C_tag P_((bool)); /* * consider_token () @@ -2252,7 +2396,7 @@ int methodlen; * is a struct/union/enum tag, or #define, or an enum constant. * * *IS_FUNC gets TRUE iff the token is a function or #define macro - * with args. C_EXT is which language we are looking at. + * with args. C_EXTP points to which language we are looking at. * * Globals * fvdef IN OUT @@ -2260,20 +2404,27 @@ int methodlen; * definedef IN OUT * typdef IN OUT * objdef IN OUT - * next_token_is_func IN OUT */ static bool -consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) +consider_token (str, len, c, c_extp, cblev, parlev, is_func_or_var) register char *str; /* IN: token pointer */ register int len; /* IN: token length */ - register char c; /* IN: first char after the token */ - int c_ext; /* IN: C extensions mask */ + register int c; /* IN: first char after the token */ + int *c_extp; /* IN, OUT: C extensions mask */ int cblev; /* IN: curly brace level */ int parlev; /* IN: parenthesis level */ bool *is_func_or_var; /* OUT: function or variable found */ { - enum sym_type toktype = C_symtype (str, len, c_ext); + /* When structdef is stagseen, scolonseen, or snone with cblev > 0, + structtype is the type of the preceding struct-like keyword, and + structcblev is the curly brace level where it has been seen. */ + static enum sym_type structtype; + static int structcblev; + static enum sym_type toktype; + + + toktype = C_symtype (str, len, *c_extp); /* * Advance the definedef state machine. @@ -2282,6 +2433,11 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) { case dnone: /* We're not on a preprocessor line. */ + if (toktype == st_C_gnumacro) + { + fvdef = fdefunkey; + return FALSE; + } break; case dsharpseen: if (toktype == st_C_define) @@ -2330,17 +2486,25 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) { case st_none: case st_C_typespec: + case st_C_class: case st_C_struct: case st_C_enum: typdef = ttypeseen; break; } - /* Do not return here, so the structdef stuff has a chance. */ + break; + case ttypeseen: + if (structdef == snone && fvdef == fvnone) + { + fvdef = fvnameseen; + return TRUE; + } break; case tend: switch (toktype) { case st_C_typespec: + case st_C_class: case st_C_struct: case st_C_enum: return FALSE; @@ -2349,11 +2513,6 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) } /* - * This structdef business is currently only invoked when cblev==0. - * It should be recursively invoked whatever the curly brace level, - * and a stack of states kept, to allow for definitions of structs - * within structs. - * * 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. @@ -2364,25 +2523,29 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) if (structdef == stagseen) structdef = scolonseen; return FALSE; + case st_C_class: + if (cblev == 0 + && (*c_extp & C_AUTO) /* automatic detection of C++ language */ + && definedef == dnone && structdef == snone + && typdef == tnone && fvdef == fvnone) + *c_extp = (*c_extp | C_PLPL) & ~C_AUTO; + /* FALLTHRU */ case st_C_struct: case st_C_enum: - if (typdef == tkeyseen - || (typedefs_and_cplusplus && cblev == 0 && structdef == snone)) + if (parlev == 0 + && fvdef != vignore + && (typdef == tkeyseen + || (typedefs_or_cplusplus && structdef == snone))) { structdef = skeyseen; structtype = toktype; + structcblev = cblev; } return FALSE; } if (structdef == skeyseen) { - /* Save the tag for struct/union/class, for functions and variables - that may be defined inside. */ - if (structtype == st_C_struct) - structtag = savenstr (str, len); - else - structtag = ""; structdef = stagseen; return TRUE; } @@ -2390,34 +2553,6 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) if (typdef != tnone) definedef = dnone; - /* Detect GNU macros. - - Writers of emacs code are recommended to put the - first two args of a DEFUN on the same line. - - 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. */ - if (definedef == dnone && toktype == st_C_gnumacro) - { - next_token_is_func = TRUE; - return FALSE; - } - if (next_token_is_func) - { - next_token_is_func = FALSE; - fvdef = fignore; - *is_func_or_var = TRUE; - return TRUE; - } - /* Detect Objective C constructs. */ switch (objdef) { @@ -2453,11 +2588,9 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) if (parlev == 0) { objdef = omethodtag; - methodlen = len; - grow_linebuffer (&token_name, methodlen + 1); + linebuffer_setlen (&token_name, len); strncpy (token_name.buffer, str, len); - token_name.buffer[methodlen] = '\0'; - token_name.len = methodlen; + token_name.buffer[len] = '\0'; return TRUE; } return FALSE; @@ -2469,10 +2602,8 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) if (parlev == 0) { objdef = omethodtag; - methodlen += len; - grow_linebuffer (&token_name, methodlen + 1); + linebuffer_setlen (&token_name, token_name.len + len); strncat (token_name.buffer, str, len); - token_name.len = methodlen; return TRUE; } return FALSE; @@ -2509,16 +2640,33 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) *is_func_or_var = TRUE; return TRUE; case st_none: - if ((c_ext & C_PLPL) && strneq (str+len-10, "::operator", 10)) + if (constantypedefs + && structdef == snone + && structtype == st_C_enum && cblev > structcblev) + return TRUE; /* enum constant */ + switch (fvdef) { - fvdef = foperator; + case fdefunkey: + if (cblev > 0) + break; + fvdef = fdefunname; /* GNU macro */ *is_func_or_var = TRUE; return TRUE; - } - if (constantypedefs && structdef == sinbody && structtype == st_C_enum) - return TRUE; - if (fvdef == fvnone) - { + case fvnone: + if ((strneq (str, "asm", 3) && endtoken (str[3])) + || (strneq (str, "__asm__", 7) && endtoken (str[7]))) + { + fvdef = vignore; + return FALSE; + } + if ((*c_extp & C_PLPL) && strneq (str+len-10, "::operator", 10)) + { + fvdef = foperator; + *is_func_or_var = TRUE; + return TRUE; + } + if (cblev > 0 && !instruct) + break; fvdef = fvnameseen; /* function or variable */ *is_func_or_var = TRUE; return TRUE; @@ -2529,20 +2677,24 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) return FALSE; } + /* - * C_entries () - * This routine finds functions, variables, typedefs, - * #define's, enum constants and struct/union/enum definitions in - * C syntax and adds them to the list. + * C_entries often keeps pointers to tokens or lines which are older than + * the line currently read. By keeping two line buffers, and switching + * them at end of line, it is possible to use those pointers. */ +struct +{ + long linepos; + linebuffer lb; +} lbs[2]; + #define current_lb_is_new (newndx == curndx) #define switch_line_buffers() (curndx = 1 - curndx) #define curlb (lbs[curndx].lb) -#define othlb (lbs[1-curndx].lb) #define newlb (lbs[newndx].lb) #define curlinepos (lbs[curndx].linepos) -#define othlinepos (lbs[1-curndx].linepos) #define newlinepos (lbs[newndx].linepos) #define CNL_SAVE_DEFINEDEF() \ @@ -2559,10 +2711,10 @@ do { \ #define CNL() \ do { \ CNL_SAVE_DEFINEDEF(); \ - if (savetok.valid) \ + if (savetoken.valid) \ { \ - tok = savetok; \ - savetok.valid = FALSE; \ + token = savetoken; \ + savetoken.valid = FALSE; \ } \ definedef = dnone; \ } while (0) @@ -2572,9 +2724,9 @@ static void make_C_tag (isfun) bool isfun; { - /* This function should never be called when tok.valid is FALSE, but + /* This function should never be called when token.valid is FALSE, but we must protect against invalid input or internal errors. */ - if (tok.valid) + if (DEBUG || token.valid) { if (traditional_tag_style) { @@ -2582,22 +2734,33 @@ make_C_tag (isfun) which uses the new method for naming tags (see new_pfnote). */ char *name = NULL; - if (CTAGS || tok.named) + if (CTAGS || token.named) name = savestr (token_name.buffer); - pfnote (name, isfun, - tok.buffer, tok.linelen, tok.lineno, tok.linepos); + if (DEBUG && !token.valid) + { + if (token.named) + name = concat (name, "##invalid##", ""); + else + name = savestr ("##invalid##"); + } + pfnote (name, isfun, token.line, + token.offset+token.length+1, token.lineno, token.linepos); } else - new_pfnote (token_name.buffer, token_name.len, isfun, - tok.buffer, tok.linelen, tok.lineno, tok.linepos); - tok.valid = FALSE; + new_pfnote (token_name.buffer, token_name.len, isfun, token.line, + token.offset+token.length+1, token.lineno, token.linepos); + token.valid = FALSE; } - else if (DEBUG) - abort (); } -void +/* + * C_entries () + * This routine finds functions, variables, typedefs, + * #define's, enum constants and struct/union/enum definitions in + * C syntax and adds them to the list. + */ +static void C_entries (c_ext, inf) int c_ext; /* extension of C */ FILE *inf; /* input file */ @@ -2611,11 +2774,24 @@ C_entries (c_ext, inf) int qlen; /* length of qualifier */ int cblev; /* current curly brace level */ int parlev; /* current parenthesis level */ + int typdefcblev; /* cblev where a typedef struct body begun */ bool incomm, inquote, inchar, quotednl, midtoken; - bool purec, cplpl, cjava; - token savetok; /* token saved during preprocessor handling */ + bool cplpl, cjava; + bool yacc_rules; /* in the rules part of a yacc file */ + struct tok savetoken; /* token saved during preprocessor handling */ + initbuffer (&token_name); + initbuffer (&lbs[0].lb); + initbuffer (&lbs[1].lb); + if (cstack.size == 0) + { + cstack.size = (DEBUG) ? 1 : 4; + cstack.nl = 0; + cstack.cname = xnew (cstack.size, char *); + cstack.cblev = xnew (cstack.size, int); + } + tokoff = toklen = 0; /* keep compiler quiet */ curndx = newndx = 0; lineno = 0; @@ -2625,12 +2801,11 @@ C_entries (c_ext, inf) fvdef = fvnone; fvextern = FALSE; typdef = tnone; structdef = snone; definedef = dnone; objdef = onone; - next_token_is_func = yacc_rules = FALSE; + yacc_rules = FALSE; midtoken = inquote = inchar = incomm = quotednl = FALSE; - tok.valid = savetok.valid = FALSE; + token.valid = savetoken.valid = FALSE; cblev = 0; parlev = 0; - purec = !(c_ext & ~YACC); /* no extensions (apart from possibly yacc) */ cplpl = (c_ext & C_PLPL) == C_PLPL; cjava = (c_ext & C_JAVA) == C_JAVA; if (cjava) @@ -2638,6 +2813,7 @@ C_entries (c_ext, inf) else { qualifier = "::"; qlen = 2; } + while (!feof (inf)) { c = *lp++; @@ -2708,8 +2884,15 @@ C_entries (c_ext, inf) { case '"': inquote = TRUE; - if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) + switch (fvdef) { + case fdefunkey: + case fstartlist: + case finlist: + case fignore: + case vignore: + break; + default: fvextern = FALSE; fvdef = fvnone; } @@ -2739,11 +2922,10 @@ C_entries (c_ext, inf) case '%': if ((c_ext & YACC) && *lp == '%') { - /* entering or exiting rules section in yacc file */ + /* Entering or exiting rules section in yacc file. */ lp++; definedef = dnone; fvdef = fvnone; fvextern = FALSE; typdef = tnone; structdef = snone; - next_token_is_func = FALSE; midtoken = inquote = inchar = incomm = quotednl = FALSE; cblev = 0; yacc_rules = !yacc_rules; @@ -2779,21 +2961,18 @@ C_entries (c_ext, inf) } /* switch (c) */ - /* Consider token only if some complicated conditions are satisfied. */ - if ((definedef != dnone - || (cblev == 0 && structdef != scolonseen) - || (cblev == 1 && cplpl && structdef == sinbody) - || (structdef == sinbody && purec)) - && typdef != tignore + /* Consider token only if some involved conditions are satisfied. */ + if (typdef != tignore && definedef != dignorerest - && fvdef != finlist) + && fvdef != finlist + && structdef != sintemplate + && (definedef != dnone + || structdef != scolonseen)) { if (midtoken) { if (endtoken (c)) { - bool funorvar = FALSE; - if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1])) { /* @@ -2804,13 +2983,15 @@ C_entries (c_ext, inf) lp += 2; toklen += 2; c = lp[-1]; - goto intok; + goto still_in_token; } else { + bool funorvar = FALSE; + if (yacc_rules || consider_token (newlb.buffer + tokoff, toklen, c, - c_ext, cblev, parlev, &funorvar)) + &c_ext, cblev, parlev, &funorvar)) { if (fvdef == foperator) { @@ -2819,87 +3000,112 @@ C_entries (c_ext, inf) if (*lp != '\0') lp += 1; while (*lp != '\0' - && !isspace (*lp) && *lp != '(') + && !iswhite (*lp) && *lp != '(') lp += 1; c = *lp++; toklen += lp - oldlp; } - tok.named = FALSE; - if (!purec - && funorvar - && definedef == dnone - && structdef == sinbody) - /* function or var defined in C++ class body */ + token.named = FALSE; + if ((c_ext & C_EXT) /* not pure C */ + && nestlev > 0 && definedef == dnone) + /* in struct body */ { - int len = strlen (structtag) + qlen + toklen; - grow_linebuffer (&token_name, len + 1); - strcpy (token_name.buffer, structtag); + write_classname (&token_name, qualifier); + linebuffer_setlen (&token_name, + token_name.len+qlen+toklen); strcat (token_name.buffer, qualifier); strncat (token_name.buffer, newlb.buffer + tokoff, toklen); - token_name.len = len; - tok.named = TRUE; + token.named = TRUE; } else if (objdef == ocatseen) /* Objective C category */ { int len = strlen (objtag) + 2 + toklen; - grow_linebuffer (&token_name, len + 1); + linebuffer_setlen (&token_name, len); strcpy (token_name.buffer, objtag); strcat (token_name.buffer, "("); strncat (token_name.buffer, newlb.buffer + tokoff, toklen); strcat (token_name.buffer, ")"); - token_name.len = len; - tok.named = TRUE; + token.named = TRUE; } else if (objdef == omethodtag || objdef == omethodparm) /* Objective C method */ { - tok.named = TRUE; + token.named = TRUE; + } + else if (fvdef == fdefunname) + /* GNU DEFUN and similar macros */ + { + bool defun = (newlb.buffer[tokoff] == 'F'); + int off = tokoff; + int len = toklen; + + /* Rewrite the tag so that emacs lisp DEFUNs + can be found by their elisp name */ + if (defun) + { + off += 1; + len -= 1; + } + len = toklen; + linebuffer_setlen (&token_name, len); + strncpy (token_name.buffer, + newlb.buffer + off, len); + token_name.buffer[len] = '\0'; + if (defun) + while (--len >= 0) + if (token_name.buffer[len] == '_') + token_name.buffer[len] = '-'; + token.named = defun; } else { - grow_linebuffer (&token_name, toklen + 1); + linebuffer_setlen (&token_name, toklen); strncpy (token_name.buffer, newlb.buffer + tokoff, toklen); token_name.buffer[toklen] = '\0'; - token_name.len = toklen; /* Name macros and members. */ - tok.named = (structdef == stagseen - || typdef == ttypeseen - || typdef == tend - || (funorvar - && definedef == dignorerest) - || (funorvar - && definedef == dnone - && structdef == sinbody)); + token.named = (structdef == stagseen + || typdef == ttypeseen + || typdef == tend + || (funorvar + && definedef == dignorerest) + || (funorvar + && definedef == dnone + && structdef == snone + && cblev > 0)); } - tok.lineno = lineno; - tok.linelen = tokoff + toklen + 1; - tok.buffer = newlb.buffer; - tok.linepos = newlinepos; - tok.valid = TRUE; + token.lineno = lineno; + token.offset = tokoff; + token.length = toklen; + token.line = newlb.buffer; + token.linepos = newlinepos; + token.valid = TRUE; if (definedef == dnone && (fvdef == fvnameseen || fvdef == foperator || structdef == stagseen || typdef == tend + || typdef == ttypeseen || objdef != onone)) { if (current_lb_is_new) switch_line_buffers (); } - else + else if (definedef != dnone + || fvdef == fdefunname + || instruct) make_C_tag (funorvar); } midtoken = FALSE; } } /* if (endtoken (c)) */ else if (intoken (c)) - intok: + still_in_token: { toklen++; continue; @@ -2924,10 +3130,13 @@ C_entries (c_ext, inf) break; } if (structdef == stagseen && !cjava) - structdef = snone; + { + popclass_above (cblev); + structdef = snone; + } break; case dsharpseen: - savetok = tok; + savetoken = token; } if (!yacc_rules || lp == newlb.buffer + 1) { @@ -2945,6 +3154,11 @@ C_entries (c_ext, inf) switch (c) { case ':': + if (yacc_rules && token.offset == 0 && token.valid) + { + make_C_tag (FALSE); /* a yacc function */ + break; + } if (definedef != dnone) break; switch (objdef) @@ -2956,65 +3170,62 @@ C_entries (c_ext, inf) case omethodtag: case omethodparm: objdef = omethodcolon; - methodlen += 1; - grow_linebuffer (&token_name, methodlen + 1); + linebuffer_setlen (&token_name, token_name.len + 1); strcat (token_name.buffer, ":"); - token_name.len = methodlen; break; } if (structdef == stagseen) structdef = scolonseen; - else - switch (fvdef) - { - case fvnameseen: - if (yacc_rules) - { - make_C_tag (FALSE); /* a yacc function */ - fvdef = fignore; - } - break; - case fstartlist: - fvextern = FALSE; - fvdef = fvnone; - break; - } break; case ';': if (definedef != dnone) break; - if (cblev == 0) - switch (typdef) - { - case tend: - make_C_tag (FALSE); /* a typedef */ - /* FALLTHRU */ - default: - typdef = tnone; - } - switch (fvdef) + switch (typdef) { - case fignore: - break; - case fvnameseen: - if ((members && cblev == 1) - || (globals && cblev == 0 && (!fvextern || declarations))) - make_C_tag (FALSE); /* a variable */ - fvextern = FALSE; + case tend: + case ttypeseen: + make_C_tag (FALSE); /* a typedef */ + typdef = tnone; fvdef = fvnone; - tok.valid = FALSE; break; - case flistseen: - if (declarations && (cblev == 0 || cblev == 1)) - make_C_tag (TRUE); /* a function declaration */ + case tnone: + case tinbody: + case tignore: + switch (fvdef) + { + case fignore: + if (typdef == tignore) + fvdef = fvnone; + break; + case fvnameseen: + if ((globals && cblev == 0 && (!fvextern || declarations)) + || (members && instruct)) + make_C_tag (FALSE); /* a variable */ + fvextern = FALSE; + fvdef = fvnone; + token.valid = FALSE; + break; + case flistseen: + if ((declarations && typdef == tnone && !instruct) + || (members && typdef != tignore && instruct)) + make_C_tag (TRUE); /* a function declaration */ + /* FALLTHRU */ + default: + fvextern = FALSE; + fvdef = fvnone; + if (declarations + && structdef == stagseen && (c_ext & C_PLPL)) + make_C_tag (FALSE); /* forward declaration */ + else + /* The following instruction invalidates the token. + Probably the token should be invalidated in all other + cases where some state machine is reset prematurely. */ + token.valid = FALSE; + } /* switch (fvdef) */ /* FALLTHRU */ default: - fvextern = FALSE; - fvdef = fvnone; - /* The following instruction invalidates the token. - Probably the token should be invalidated in all - other cases where some state machine is reset. */ - tok.valid = FALSE; + if (!instruct) + typdef = tnone; } if (structdef == stagseen) structdef = snone; @@ -3032,15 +3243,31 @@ C_entries (c_ext, inf) } switch (fvdef) { + case fdefunkey: case foperator: + case fstartlist: case finlist: case fignore: case vignore: break; - case fvnameseen: - if ((members && cblev == 1) - || (globals && cblev == 0 && (!fvextern || declarations))) - make_C_tag (FALSE); /* a variable */ + case fdefunname: + fvdef = fignore; + break; + case fvnameseen: /* a variable */ + if ((globals && cblev == 0 && (!fvextern || declarations)) + || (members && instruct)) + make_C_tag (FALSE); + break; + case flistseen: /* a function */ + if ((declarations && typdef == tnone && !instruct) + || (members && typdef != tignore && instruct)) + { + make_C_tag (TRUE); /* a function declaration */ + fvdef = fvnameseen; + } + else if (!declarations) + fvdef = fvnone; + token.valid = FALSE; break; default: fvdef = fvnone; @@ -3051,29 +3278,35 @@ C_entries (c_ext, inf) case '[': if (definedef != dnone) break; - if (cblev == 0 && typdef == tend) + if (structdef == stagseen) + structdef = snone; + switch (typdef) { + case ttypeseen: + case tend: typdef = tignore; make_C_tag (FALSE); /* a typedef */ break; - } - switch (fvdef) - { - case foperator: - case finlist: - case fignore: - case vignore: + case tnone: + case tinbody: + switch (fvdef) + { + case foperator: + case finlist: + case fignore: + case vignore: + break; + case fvnameseen: + if ((members && cblev == 1) + || (globals && cblev == 0 + && (!fvextern || declarations))) + make_C_tag (FALSE); /* a variable */ + /* FALLTHRU */ + default: + fvdef = fvnone; + } break; - case fvnameseen: - if ((members && cblev == 1) - || (globals && cblev == 0 && (!fvextern || declarations))) - make_C_tag (FALSE); /* a variable */ - /* FALLTHRU */ - default: - fvdef = fvnone; } - if (structdef == stagseen) - structdef = snone; break; case '(': if (definedef != dnone) @@ -3084,14 +3317,15 @@ C_entries (c_ext, inf) { case fvnameseen: if (typdef == ttypeseen - && tok.valid && *lp != '*' - && structdef != sinbody) + && !instruct) { /* This handles constructs like: typedef void OperatorFun (int fun); */ make_C_tag (FALSE); typdef = tignore; + fvdef = fignore; + break; } /* FALLTHRU */ case foperator: @@ -3120,7 +3354,9 @@ C_entries (c_ext, inf) fvdef = flistseen; break; } - if (cblev == 0 && (typdef == tend)) + if (!instruct + && (typdef == tend + || typdef == ttypeseen)) { typdef = tignore; make_C_tag (FALSE); /* a typedef */ @@ -3133,23 +3369,14 @@ C_entries (c_ext, inf) if (definedef != dnone) break; if (typdef == ttypeseen) - typdef = tinbody; - switch (structdef) { - case skeyseen: /* unnamed struct */ - structdef = sinbody; - structtag = "_anonymous_"; - break; - case stagseen: - case scolonseen: /* named struct */ - structdef = sinbody; - make_C_tag (FALSE); /* a struct */ - break; + typdefcblev = cblev; + typdef = tinbody; } switch (fvdef) { case flistseen: - make_C_tag (TRUE); /* a function */ + make_C_tag (TRUE); /* a function */ /* FALLTHRU */ case fignore: fvdef = fvnone; @@ -3168,10 +3395,24 @@ C_entries (c_ext, inf) break; default: /* Neutralize `extern "C" {' grot. */ - if (cblev == 0 && structdef == snone && typdef == tnone) + if (cblev == 0 && structdef == snone && nestlev == 0 + && typdef == tnone) cblev = -1; } } + switch (structdef) + { + case skeyseen: /* unnamed struct */ + pushclass_above (cblev, NULL, 0); + structdef = snone; + break; + case stagseen: /* named struct or enum */ + case scolonseen: /* a class */ + pushclass_above (cblev, token.line+token.offset, token.length); + structdef = snone; + make_C_tag (FALSE); /* a struct or enum */ + break; + } cblev++; break; case '*': @@ -3190,20 +3431,12 @@ C_entries (c_ext, inf) } else if (cblev > 0) cblev--; - if (cblev == 0) + popclass_above (cblev); + structdef = snone; + if (typdef == tinbody && cblev <= typdefcblev) { - if (typdef == tinbody) - typdef = tend; - /* Memory leakage here: the string pointed by structtag is - never released, because I fear to miss something and - break things while freeing the area. The amount of - memory leaked here is the sum of the lengths of the - struct tags. - if (structdef == sinbody) - free (structtag); */ - - structdef = snone; - structtag = ""; + assert (cblev == typdefcblev); + typdef = tend; } break; case '=': @@ -3225,6 +3458,20 @@ C_entries (c_ext, inf) fvdef = vignore; } break; + case '<': + if (cplpl && structdef == stagseen) + { + structdef = sintemplate; + break; + } + goto resetfvdef; + case '>': + if (structdef == sintemplate) + { + structdef = stagseen; + break; + } + goto resetfvdef; case '+': case '-': if (objdef == oinbody && cblev == 0) @@ -3233,8 +3480,9 @@ C_entries (c_ext, inf) break; } /* FALLTHRU */ + resetfvdef: case '#': case '~': case '&': case '%': case '/': case '|': - case '^': case '!': case '<': case '>': case '.': case '?': case ']': + case '^': case '!': case '.': case '?': case ']': if (definedef != dnone) break; /* These surely cannot follow a function tag in C. */ @@ -3264,21 +3512,25 @@ C_entries (c_ext, inf) } /* switch (c) */ } /* while not eof */ + + free (token_name.buffer); + free (lbs[0].lb.buffer); + free (lbs[1].lb.buffer); } /* * Process either a C++ file or a C file depending on the setting * of a global flag. */ -void +static void default_C_entries (inf) FILE *inf; { - C_entries (cplusplus ? C_PLPL : 0, inf); + C_entries (cplusplus ? C_PLPL : C_AUTO, inf); } -/* Always do plain ANSI C. */ -void +/* Always do plain C. */ +static void plain_C_entries (inf) FILE *inf; { @@ -3286,7 +3538,7 @@ plain_C_entries (inf) } /* Always do C++. */ -void +static void Cplusplus_entries (inf) FILE *inf; { @@ -3294,7 +3546,7 @@ Cplusplus_entries (inf) } /* Always do Java. */ -void +static void Cjava_entries (inf) FILE *inf; { @@ -3302,7 +3554,7 @@ Cjava_entries (inf) } /* Always do C*. */ -void +static void Cstar_entries (inf) FILE *inf; { @@ -3310,12 +3562,13 @@ Cstar_entries (inf) } /* Always do Yacc. */ -void +static void Yacc_entries (inf) FILE *inf; { C_entries (YACC, inf); } + /* A useful macro. */ #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \ @@ -3333,7 +3586,7 @@ Yacc_entries (inf) * Read a file, but do no processing. This is used to do regexp * matching on files that have no language defined. */ -void +static void just_read_file (inf) FILE *inf; { @@ -3342,9 +3595,14 @@ just_read_file (inf) LOOP_ON_INPUT_LINES (inf, lb, dummy) continue; } + /* Fortran parsing */ +static bool tail P_((char *)); +static void takeprec P_((void)); +static void getit P_((FILE *)); + static bool tail (cp) char *cp; @@ -3361,7 +3619,7 @@ tail (cp) return FALSE; } -void +static void takeprec () { dbp = skip_spaces (dbp); @@ -3374,14 +3632,14 @@ takeprec () dbp += 3; return; } - if (!isdigit (*dbp)) + if (!ISDIGIT (*dbp)) { --dbp; /* force failure */ return; } do dbp++; - while (isdigit (*dbp)); + while (ISDIGIT (*dbp)); } static void @@ -3402,7 +3660,7 @@ getit (inf) dbp += 6; dbp = skip_spaces (dbp); } - if (!isalpha (*dbp) && *dbp != '_' && *dbp != '$') + if (!ISALPHA (*dbp) && *dbp != '_' && *dbp != '$') return; for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++) continue; @@ -3411,7 +3669,7 @@ getit (inf) } -void +static void Fortran_functions (inf) FILE *inf; { @@ -3483,11 +3741,15 @@ Fortran_functions (inf) } } } + /* - * Philippe Waroquiers , 1998-04-24 * Ada parsing + * Philippe Waroquiers (1998) */ + +static void adagetit P_((FILE *, char *)); + /* Once we are positioned after an "interesting" keyword, let's get the real tag value necessary. */ static void @@ -3540,7 +3802,7 @@ adagetit (inf, name_qualifier) dbp = skip_spaces (dbp); for (cp = dbp; (*cp != '\0' - && (isalpha (*cp) || isdigit (*cp) || *cp == '_' || *cp == '.')); + && (ISALPHA (*cp) || ISDIGIT (*cp) || *cp == '_' || *cp == '.')); cp++) continue; if (cp == dbp) @@ -3557,7 +3819,7 @@ adagetit (inf, name_qualifier) } } -void +static void Ada_funcs (inf) FILE *inf; { @@ -3648,13 +3910,14 @@ Ada_funcs (inf) } /* advance char */ } /* advance line */ } + /* * Bob Weiner, Motorola Inc., 4/3/94 * Unix and microcontroller assembly tag handling * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]' */ -void +static void Asm_labels (inf) FILE *inf; { @@ -3664,13 +3927,13 @@ Asm_labels (inf) { /* If first char is alphabetic or one of [_.$], test for colon following identifier. */ - if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$') + if (ISALPHA (*cp) || *cp == '_' || *cp == '.' || *cp == '$') { /* Read past label. */ cp++; - while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$') + while (ISALNUM (*cp) || *cp == '_' || *cp == '.' || *cp == '$') cp++; - if (*cp == ':' || isspace (*cp)) + if (*cp == ':' || iswhite (*cp)) { /* Found end of label, so copy it and add it to the table. */ pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE, @@ -3679,14 +3942,16 @@ Asm_labels (inf) } } } + /* - * Perl support by Bart Robinson - * enhanced by Michael Ernst + * Perl support * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/ * Perl variable names: /^(my|local).../ + * Bart Robinson (1995) + * Michael Ernst (1997) */ -void +static void Perl_functions (inf) FILE *inf; { @@ -3696,14 +3961,14 @@ Perl_functions (inf) { if (*cp++ == 's' && *cp++ == 'u' - && *cp++ == 'b' && isspace (*cp++)) + && *cp++ == 'b' && iswhite (*cp++)) { cp = skip_spaces (cp); if (*cp != '\0') { char *sp = cp; while (*cp != '\0' - && !isspace (*cp) && *cp != '{' && *cp != '(') + && !iswhite (*cp) && *cp != '{' && *cp != '(') cp++; pfnote (savenstr (sp, cp-sp), TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); @@ -3719,7 +3984,7 @@ Perl_functions (inf) && *cp++ == 'c' && *cp++ == 'a' && *cp++ == 'l')) - && (*cp == '(' || isspace (*cp))) + && (*cp == '(' || iswhite (*cp))) { /* After "my" or "local", but before any following paren or space. */ char *varname = NULL; @@ -3728,7 +3993,7 @@ Perl_functions (inf) if (*cp == '$' || *cp == '@' || *cp == '%') { char* varstart = ++cp; - while (isalnum (*cp) || *cp == '_') + while (ISALNUM (*cp) || *cp == '_') cp++; varname = savenstr (varstart, cp-varstart); } @@ -3747,12 +4012,14 @@ Perl_functions (inf) } } } + /* - * Python support by Eric S. Raymond + * Python support * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/ + * Eric S. Raymond (1997) */ -void +static void Python_functions (inf) FILE *inf; { @@ -3762,10 +4029,10 @@ Python_functions (inf) { if (*cp++ == 'd' && *cp++ == 'e' - && *cp++ == 'f' && isspace (*cp++)) + && *cp++ == 'f' && iswhite (*cp++)) { cp = skip_spaces (cp); - while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':') + while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') cp++; pfnote (NULL, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); @@ -3776,23 +4043,24 @@ Python_functions (inf) && *cp++ == 'l' && *cp++ == 'a' && *cp++ == 's' - && *cp++ == 's' && isspace (*cp++)) + && *cp++ == 's' && iswhite (*cp++)) { cp = skip_spaces (cp); - while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':') + while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') cp++; pfnote (NULL, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); } } } + /* Idea by Corny de Souza * Cobol tag functions * We could look for anything that could be a paragraph name. * i.e. anything that starts in column 8 is one word and ends in a full stop. */ -void +static void Cobol_paragraphs (inf) FILE *inf; { @@ -3805,16 +4073,40 @@ Cobol_paragraphs (inf) bp += 8; /* If eoln, compiler option or comment ignore whole line. */ - if (bp[-1] != ' ' || !isalnum (bp[0])) + if (bp[-1] != ' ' || !ISALNUM (bp[0])) continue; - for (ep = bp; isalnum (*ep) || *ep == '-'; ep++) + for (ep = bp; ISALNUM (*ep) || *ep == '-'; ep++) continue; if (*ep++ == '.') pfnote (savenstr (bp, ep-bp), TRUE, lb.buffer, ep - lb.buffer + 1, lineno, linecharno); } } + + +/* + * Makefile support + * Idea by Assar Westerlund (2001) + */ +static void +Makefile_targets (inf) + FILE *inf; +{ + register char *bp; + + LOOP_ON_INPUT_LINES (inf, lb, bp) + { + if (*bp == '\t' || *bp == '#') + continue; + while (*bp != '\0' && *bp != '=' && *bp != ':') + bp++; + if (*bp == ':') + pfnote (savenstr (lb.buffer, bp - lb.buffer), TRUE, + lb.buffer, bp - lb.buffer + 1, lineno, linecharno); + } +} + /* Added by Mosur Mohan, 4/22/88 */ /* Pascal parsing */ @@ -3825,7 +4117,7 @@ Cobol_paragraphs (inf) * "forward" immediately following the procedure statement; if found, * the tag is skipped. */ -void +static void Pascal_functions (inf) FILE *inf; { @@ -3961,7 +4253,7 @@ Pascal_functions (inf) continue; /* save all values for later tagging */ - grow_linebuffer (&tline, lb.len + 1); + linebuffer_setlen (&tline, lb.len); strcpy (tline.buffer, lb.buffer); save_lineno = lineno; save_lcno = linecharno; @@ -3997,11 +4289,17 @@ Pascal_functions (inf) free (tline.buffer); } + /* - * lisp tag functions + * Lisp tag functions * look for (def or (DEF, quote or QUOTE */ + +static int L_isdef P_((char *)); +static int L_isquote P_((char *)); +static void L_getit P_((void)); + static int L_isdef (strp) register char *strp; @@ -4020,7 +4318,7 @@ L_isquote (strp) && (*++strp == 'o' || *strp == 'O') && (*++strp == 't' || *strp == 'T') && (*++strp == 'e' || *strp == 'E') - && isspace (*++strp)); + && iswhite (*++strp)); } static void @@ -4040,7 +4338,7 @@ L_getit () } for (cp = dbp /*+1*/; - *cp != '\0' && *cp != '(' && !isspace(*cp) && *cp != ')'; + *cp != '\0' && *cp != '(' && !iswhite(*cp) && *cp != ')'; cp++) continue; if (cp == dbp) @@ -4050,7 +4348,7 @@ L_getit () lb.buffer, cp - lb.buffer + 1, lineno, linecharno); } -void +static void Lisp_functions (inf) FILE *inf; { @@ -4069,7 +4367,7 @@ Lisp_functions (inf) /* Check for (foo::defmumble name-defined ... */ do dbp++; - while (*dbp != '\0' && !isspace (*dbp) + while (*dbp != '\0' && !iswhite (*dbp) && *dbp != ':' && *dbp != '(' && *dbp != ')'); if (*dbp == ':') { @@ -4088,15 +4386,16 @@ Lisp_functions (inf) } } } + /* * Postscript tag functions * Just look for lines where the first character is '/' - * Richard Mlynarik * Also look at "defineps" for PSWrap - * suggested by Masatake YAMATO + * Richard Mlynarik (1997) + * Ideas by Masatake Yamato (1999) */ -void +static void Postscript_functions (inf) FILE *inf; { @@ -4131,7 +4430,7 @@ Postscript_functions (inf) * look for (set! xyzzy */ -void +static void Scheme_functions (inf) FILE *inf; { @@ -4146,7 +4445,7 @@ Scheme_functions (inf) { bp = skip_non_spaces (bp); /* Skip over open parens and white space */ - while (isspace (*bp) || *bp == '(') + while (iswhite (*bp) || *bp == '(') bp++; get_tag (bp); } @@ -4155,7 +4454,7 @@ Scheme_functions (inf) && (bp[2] == 'E' || bp[2] == 'e') && (bp[3] == 'T' || bp[3] == 't') && (bp[4] == '!' || bp[4] == '!') - && (isspace (bp[5]))) + && (iswhite (bp[5]))) { bp = skip_non_spaces (bp); bp = skip_spaces (bp); @@ -4163,6 +4462,7 @@ Scheme_functions (inf) } } } + /* Find tags in TeX and LaTeX input files. */ @@ -4184,9 +4484,9 @@ char *TEX_defenv = "\ :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\ :part:appendix:entry:index"; -void TEX_mode (FILE *inf); -struct TEX_tabent *TEX_decode_env (char *evarname, char *defenv); -int TEX_Token (char *cp); +static void TEX_mode P_((FILE *)); +static struct TEX_tabent *TEX_decode_env P_((char *, char *)); +static int TEX_Token P_((char *)); char TEX_esc = '\\'; char TEX_opgrp = '{'; @@ -4195,8 +4495,8 @@ char TEX_clgrp = '}'; /* * TeX/LaTeX scanning loop. */ -void -TeX_functions (inf) +static void +TeX_commands (inf) FILE *inf; { char *cp, *lasthit; @@ -4242,7 +4542,7 @@ TeX_functions (inf) /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping chars accordingly. */ -void +static void TEX_mode (inf) FILE *inf; { @@ -4277,7 +4577,7 @@ TEX_mode (inf) /* Read environment and prepend it to the default string. Build token table. */ -struct TEX_tabent * +static struct TEX_tabent * TEX_decode_env (evarname, defenv) char *evarname; char *defenv; @@ -4334,7 +4634,7 @@ TEX_decode_env (evarname, defenv) Otherwise return -1. Keep the capital `T' in `token' for dumb truncating compilers (this distinguishes it from `TEX_toktab' */ -int +static int TEX_Token (cp) char *cp; { @@ -4345,6 +4645,31 @@ TEX_Token (cp) return i; return -1; } + + +/* Texinfo support. Dave Love, Mar. 2000. */ +static void +Texinfo_nodes (inf) + FILE * inf; +{ + char *cp, *start; + LOOP_ON_INPUT_LINES (inf, lb, cp) + { + if ((*cp++ == '@' + && *cp++ == 'n' + && *cp++ == 'o' + && *cp++ == 'd' + && *cp++ == 'e' && iswhite (*cp++))) + { + start = cp = skip_spaces(cp); + while (*cp != '\0' && *cp != ',') + cp++; + pfnote (savenstr (start, cp - start), TRUE, + lb.buffer, cp - lb.buffer + 1, lineno, linecharno); + } + } +} + /* * Prolog support (rewritten) by Anders Lindgren, Mar. 96 @@ -4352,11 +4677,11 @@ TEX_Token (cp) * Assumes that the predicate starts at column 0. * Only the first clause of a predicate is added. */ -int prolog_pred (char *s, char *last); -void prolog_skip_comment (linebuffer *plb, FILE *inf); -int prolog_atom (char *s, int pos); +static int prolog_pred P_((char *, char *)); +static void prolog_skip_comment P_((linebuffer *, FILE *)); +static int prolog_atom P_((char *, int)); -void +static void Prolog_functions (inf) FILE *inf; { @@ -4372,7 +4697,7 @@ Prolog_functions (inf) { if (cp[0] == '\0') /* Empty line */ continue; - else if (isspace (cp[0])) /* Not a predicate */ + else if (iswhite (cp[0])) /* Not a predicate */ continue; else if (cp[0] == '/' && cp[1] == '*') /* comment. */ prolog_skip_comment (&lb, inf); @@ -4383,7 +4708,7 @@ Prolog_functions (inf) if (last == NULL) last = xnew(len + 1, char); else if (len + 1 > allocated) - last = xrnew (last, len + 1, char); + xrnew (last, len + 1, char); allocated = len + 1; strncpy (last, cp, len); last[len] = '\0'; @@ -4392,7 +4717,7 @@ Prolog_functions (inf) } -void +static void prolog_skip_comment (plb, inf) linebuffer *plb; FILE *inf; @@ -4420,7 +4745,7 @@ prolog_skip_comment (plb, inf) * Return the size of the name of the predicate, or 0 if no header * was found. */ -int +static int prolog_pred (s, last) char *s; char *last; /* Name of last clause. */ @@ -4461,7 +4786,7 @@ prolog_pred (s, last) * - A quoted arbitrary string. Single quotes can escape themselves. * Backslash quotes everything. */ -int +static int prolog_atom (s, pos) char *s; int pos; @@ -4470,11 +4795,11 @@ prolog_atom (s, pos) origpos = pos; - if (islower(s[pos]) || (s[pos] == '_')) + if (ISLOWER(s[pos]) || (s[pos] == '_')) { /* The atom is unquoted. */ pos++; - while (isalnum(s[pos]) || (s[pos] == '_')) + while (ISALNUM(s[pos]) || (s[pos] == '_')) { pos++; } @@ -4510,6 +4835,7 @@ prolog_atom (s, pos) else return -1; } + /* * Support for Erlang -- Anders Lindgren, Feb 1996. @@ -4518,11 +4844,11 @@ prolog_atom (s, pos) * * Assumes that Erlang functions start at column 0. */ -int erlang_func (char *s, char *last); -void erlang_attribute (char *s); -int erlang_atom (char *s, int pos); +static int erlang_func P_((char *, char *)); +static void erlang_attribute P_((char *)); +static int erlang_atom P_((char *, int)); -void +static void Erlang_functions (inf) FILE *inf; { @@ -4538,7 +4864,7 @@ Erlang_functions (inf) { if (cp[0] == '\0') /* Empty line */ continue; - else if (isspace (cp[0])) /* Not function nor attribute */ + else if (iswhite (cp[0])) /* Not function nor attribute */ continue; else if (cp[0] == '%') /* comment */ continue; @@ -4558,7 +4884,7 @@ Erlang_functions (inf) if (last == NULL) last = xnew (len + 1, char); else if (len + 1 > allocated) - last = xrnew (last, len + 1, char); + xrnew (last, len + 1, char); allocated = len + 1; strncpy (last, cp, len); last[len] = '\0'; @@ -4577,7 +4903,7 @@ Erlang_functions (inf) * Return the size of the name of the function, or 0 if no function * was found. */ -int +static int erlang_func (s, last) char *s; char *last; /* Name of last clause. */ @@ -4615,7 +4941,7 @@ erlang_func (s, last) * -define(Foo(M, N), M+N). * -record(graph, {vtab = notable, cyclic = true}). */ -void +static void erlang_attribute (s) char *s; { @@ -4642,7 +4968,7 @@ erlang_attribute (s) * Consume an Erlang atom (or variable). * Return the number of bytes consumed, or -1 if there was an error. */ -int +static int erlang_atom (s, pos) char *s; int pos; @@ -4651,11 +4977,11 @@ erlang_atom (s, pos) origpos = pos; - if (isalpha (s[pos]) || s[pos] == '_') + if (ISALPHA (s[pos]) || s[pos] == '_') { /* The atom is unquoted. */ pos++; - while (isalnum (s[pos]) || s[pos] == '_') + while (ISALNUM (s[pos]) || s[pos] == '_') pos++; return pos - origpos; } @@ -4687,9 +5013,15 @@ erlang_atom (s, pos) else return -1; } + #ifdef ETAGS_REGEXPS +static char *scan_separators P_((char *)); +static void analyse_regex P_((char *, bool)); +static void add_regex P_((char *, bool, language *)); +static char *substitute P_((char *, char *, struct re_registers *)); + /* Take a string like "/blah/" and turn it into "blah", making sure that the first and last characters are the same, and handling quoted separator characters. Actually, stops on the occurrence of @@ -4735,7 +5067,7 @@ scan_separators (name) /* Look at the argument of --regex or --no-regex and do the right thing. Same for each line of a regexp file. */ -void +static void analyse_regex (regex_arg, ignore_case) char *regex_arg; bool ignore_case; @@ -4789,7 +5121,7 @@ analyse_regex (regex_arg, ignore_case) return; } *cp = '\0'; - lang = get_language_from_name (lang_name); + lang = get_language_from_langname (lang_name); if (lang == NULL) return; add_regex (cp + 1, ignore_case, lang); @@ -4805,7 +5137,7 @@ analyse_regex (regex_arg, ignore_case) /* Turn a name, which is an ed-style (but Emacs syntax) regular expression, into a real regular expression by compiling it. */ -void +static void add_regex (regexp_pattern, ignore_case, lang) char *regexp_pattern; bool ignore_case; @@ -4875,7 +5207,7 @@ substitute (in, out, regs) for (t = etags_strchr (out, '\\'); t != NULL; t = etags_strchr (t + 2, '\\')) - if (isdigit (t[1])) + if (ISDIGIT (t[1])) { dig = t[1] - '0'; diglen = regs->end[dig] - regs->start[dig]; @@ -4888,9 +5220,8 @@ substitute (in, out, regs) result = xnew (size + 1, char); for (t = result; *out != '\0'; out++) - if (*out == '\\' && isdigit (*++out)) + if (*out == '\\' && ISDIGIT (*++out)) { - /* Using "dig2" satisfies my debugger. Bleah. */ dig = *out - '0'; diglen = regs->end[dig] - regs->start[dig]; strncpy (t, in + regs->start[dig], diglen); @@ -4900,14 +5231,13 @@ substitute (in, out, regs) *t++ = *out; *t = '\0'; - if (DEBUG && (t > result + size || t - result != (int)strlen (result))) - abort (); + assert (t <= result + size && t - result == (int)strlen (result)); return result; } /* Deallocate all patterns. */ -void +static void free_patterns () { pattern *pp; @@ -4921,8 +5251,10 @@ free_patterns () } return; } +#endif /* ETAGS_REGEXPS */ + -void +static void get_tag (bp) register char *bp; { @@ -4932,21 +5264,22 @@ get_tag (bp) return; /* Go till you get to white space or a syntactic break */ for (cp = bp + 1; - *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp); + *cp != '\0' && *cp != '(' && *cp != ')' && !iswhite (*cp); cp++) continue; pfnote (savenstr (bp, cp-bp), TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); } -#endif /* ETAGS_REGEXPS */ /* Initialize a linebuffer for use */ -void +static void initbuffer (lbp) linebuffer *lbp; { - lbp->size = 200; - lbp->buffer = xnew (200, char); + lbp->size = (DEBUG) ? 3 : 200; + lbp->buffer = xnew (lbp->size, char); + lbp->buffer[0] = '\0'; + lbp->len = 0; } /* @@ -4959,7 +5292,7 @@ initbuffer (lbp) * platforms (for text files, it translates CR-NL to NL as it reads in the * file). */ -long +static long readline_internal (lbp, stream) linebuffer *lbp; register FILE *stream; @@ -4978,7 +5311,7 @@ readline_internal (lbp, stream) { /* We're at the end of linebuffer: expand it. */ lbp->size *= 2; - buffer = xrnew (buffer, lbp->size, char); + xrnew (buffer, lbp->size, char); p += buffer - lbp->buffer; pend = buffer + lbp->size; lbp->buffer = buffer; @@ -5023,7 +5356,7 @@ readline_internal (lbp, stream) * Like readline_internal, above, but in addition try to match the * input line against relevant regular expressions. */ -long +static long readline (lbp, stream) linebuffer *lbp; FILE *stream; @@ -5079,12 +5412,13 @@ readline (lbp, stream) return result; } + /* * Return a pointer to a space of size strlen(cp)+1 allocated * with xnew where the string CP has been copied. */ -char * +static char * savestr (cp) char *cp; { @@ -5095,7 +5429,7 @@ savestr (cp) * Return a pointer to a space of size LEN+1 allocated with xnew where * the string CP has been copied for at most the first LEN characters. */ -char * +static char * savenstr (cp, len) char *cp; int len; @@ -5112,13 +5446,14 @@ savenstr (cp, len) * Return the ptr in sp at which the character c last * appears; NULL if not found * - * Identical to System V strrchr, included for portability. + * Identical to POSIX strrchr, included for portability. */ -char * +static char * etags_strrchr (sp, c) - register char *sp, c; + register const char *sp; + register int c; { - register char *r; + register const char *r; r = NULL; do @@ -5126,7 +5461,7 @@ etags_strrchr (sp, c) if (*sp == c) r = sp; } while (*sp++); - return r; + return (char *)r; } @@ -5134,36 +5469,37 @@ etags_strrchr (sp, c) * Return the ptr in sp at which the character c first * appears; NULL if not found * - * Identical to System V strchr, included for portability. + * Identical to POSIX strchr, included for portability. */ -char * +static char * etags_strchr (sp, c) - register char *sp, c; + register const char *sp; + register int c; { do { if (*sp == c) - return sp; + return (char *)sp; } while (*sp++); return NULL; } /* Skip spaces, return new pointer. */ -char * +static char * skip_spaces (cp) char *cp; { - while (isspace (*cp)) /* isspace('\0')==FALSE */ + while (iswhite (*cp)) cp++; return cp; } /* Skip non spaces, return new pointer. */ -char * +static char * skip_non_spaces (cp) char *cp; { - while (!iswhite (*cp)) /* iswhite('\0')==TRUE */ + while (*cp != '\0' && !iswhite (*cp)) cp++; return cp; } @@ -5177,7 +5513,7 @@ fatal (s1, s2) exit (BAD); } -void +static void pfatal (s1) char *s1; { @@ -5185,7 +5521,7 @@ pfatal (s1) exit (BAD); } -void +static void suggest_asking_for_help () { fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n", @@ -5200,7 +5536,7 @@ suggest_asking_for_help () } /* Print error message. `s1' is printf control string, `s2' is arg for it. */ -void +static void error (s1, s2) const char *s1, *s2; { @@ -5211,7 +5547,7 @@ error (s1, s2) /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ -char * +static char * concat (s1, s2, s3) char *s1, *s2, *s3; { @@ -5225,10 +5561,11 @@ concat (s1, s2, s3) return result; } + /* Does the same work as the system V getcwd, but does not need to guess the buffer size in advance. */ -char * +static char * etags_getcwd () { #ifdef HAVE_GETCWD @@ -5248,7 +5585,8 @@ etags_getcwd () return path; #else /* not HAVE_GETCWD */ -#ifdef MSDOS +#if MSDOS + char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ getwd (path); @@ -5277,7 +5615,7 @@ etags_getcwd () /* Return a newly allocated string containing the file name of FILE relative to the absolute directory DIR (which should end with a slash). */ -char * +static char * relative_filename (file, dir) char *file, *dir; { @@ -5317,7 +5655,7 @@ relative_filename (file, dir) /* Return a newly allocated string containing the absolute file name of FILE given DIR (which should end with a slash). */ -char * +static char * absolute_filename (file, dir) char *file, *dir; { @@ -5379,7 +5717,7 @@ absolute_filename (file, dir) /* Return a newly allocated string containing the absolute file name of dir where FILE resides given DIR (which should end with a slash). */ -char * +static char * absolute_dirname (file, dir) char *file, *dir; { @@ -5400,26 +5738,26 @@ absolute_dirname (file, dir) /* Whether the argument string is an absolute file name. The argument string must have been canonicalized with canonicalize_filename. */ -bool +static bool filename_is_absolute (fn) char *fn; { return (fn[0] == '/' #ifdef DOS_NT - || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/') + || (ISALPHA(fn[0]) && fn[1] == ':' && fn[2] == '/') #endif ); } /* Translate backslashes into slashes. Works in place. */ -void +static void canonicalize_filename (fn) register char *fn; { #ifdef DOS_NT /* Canonicalize drive letter case. */ - if (islower (fn[0])) - fn[0] = toupper (fn[0]); + if (fn[0] != '\0' && fn[1] == ':' && ISLOWER (fn[0])) + fn[0] = upcase (fn[0]); /* Convert backslashes to slashes. */ for (; *fn != '\0'; fn++) if (*fn == '\\') @@ -5430,15 +5768,18 @@ canonicalize_filename (fn) #endif } -/* Increase the size of a linebuffer. */ -void -grow_linebuffer (lbp, toksize) +/* Set the minimum size of a string contained in a linebuffer. */ +static void +linebuffer_setlen (lbp, toksize) linebuffer *lbp; int toksize; { - while (lbp->size < toksize) - lbp->size *= 2; - lbp->buffer = xrnew (lbp->buffer, lbp->size, char); + while (lbp->size <= toksize) + { + lbp->size *= 2; + xrnew (lbp->buffer, lbp->size, char); + } + lbp->len = toksize; } /* Like malloc but get fatal error if memory is exhausted. */