diff options
| author | Francesco Potortì | 1999-11-01 02:48:57 +0000 |
|---|---|---|
| committer | Francesco Potortì | 1999-11-01 02:48:57 +0000 |
| commit | 93b7ac65fc0e920bf11262f6b3eba4ae65c7a114 (patch) | |
| tree | db580d73a45abb863610aa6c3d0117a6d24abd2e /lib-src | |
| parent | 1c4784614ed4beda8e488308709c5486ea5740d8 (diff) | |
| download | emacs-93b7ac65fc0e920bf11262f6b3eba4ae65c7a114.tar.gz emacs-93b7ac65fc0e920bf11262f6b3eba4ae65c7a114.zip | |
Checked in at last a lot of improvementes and bug fixes. The oldest dating
back to 1997-06-04. Please look at Changelog for details. Main changes
are:
- lots of code cleanups and optimizations
- --globals is used not only for C-like languages
- new option --ignore-case-regex
- understands "operator" in C++
- support DOS file names by handling e.g. foo.cgz as if it were foo.c.gz.
- Fortran: no tags for "procedure"
- new option --declarations
- regular expressions can be read from a file
- regular expressions can be bound to a given language
- Ada and Python languages added
- my and local variables recognised in Perl
- "(defstruct (foo", "(defun (operator" and similar Lisp constructs
- interface in Java
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/etags.c | 2404 |
1 files changed, 1492 insertions, 912 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c index 83a9f65f6ca..165c298f0da 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c | |||
| @@ -31,11 +31,12 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| 31 | * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer. | 31 | * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | char pot_etags_version[] = "@(#) pot revision number is 12.11"; | 34 | char pot_etags_version[] = "@(#) pot revision number is 13.31"; |
| 35 | 35 | ||
| 36 | #define TRUE 1 | 36 | #define TRUE 1 |
| 37 | #define FALSE 0 | 37 | #define FALSE 0 |
| 38 | 38 | ||
| 39 | #define _GNU_SOURCE /* enables some compiler checks on GNU */ | ||
| 39 | #ifndef DEBUG | 40 | #ifndef DEBUG |
| 40 | # define DEBUG FALSE | 41 | # define DEBUG FALSE |
| 41 | #endif | 42 | #endif |
| @@ -45,14 +46,18 @@ char pot_etags_version[] = "@(#) pot revision number is 12.11"; | |||
| 45 | /* On some systems, Emacs defines static as nothing for the sake | 46 | /* On some systems, Emacs defines static as nothing for the sake |
| 46 | of unexec. We don't want that here since we don't use unexec. */ | 47 | of unexec. We don't want that here since we don't use unexec. */ |
| 47 | # undef static | 48 | # undef static |
| 48 | # define ETAGS_REGEXPS | 49 | # define ETAGS_REGEXPS /* use the regexp features */ |
| 49 | # define LONG_OPTIONS | 50 | # define LONG_OPTIONS /* accept long options */ |
| 50 | #endif | 51 | #endif /* HAVE_CONFIG_H */ |
| 51 | 52 | ||
| 52 | #ifdef MSDOS | 53 | #ifdef MSDOS |
| 53 | # include <string.h> | ||
| 54 | # include <fcntl.h> | 54 | # include <fcntl.h> |
| 55 | # include <sys/param.h> | 55 | # include <sys/param.h> |
| 56 | # include <io.h> | ||
| 57 | # ifndef HAVE_CONFIG_H | ||
| 58 | # define DOS_NT | ||
| 59 | # include <sys/config.h> | ||
| 60 | # endif | ||
| 56 | #endif /* MSDOS */ | 61 | #endif /* MSDOS */ |
| 57 | 62 | ||
| 58 | #ifdef WINDOWSNT | 63 | #ifdef WINDOWSNT |
| @@ -61,27 +66,38 @@ char pot_etags_version[] = "@(#) pot revision number is 12.11"; | |||
| 61 | # include <string.h> | 66 | # include <string.h> |
| 62 | # include <io.h> | 67 | # include <io.h> |
| 63 | # define MAXPATHLEN _MAX_PATH | 68 | # define MAXPATHLEN _MAX_PATH |
| 64 | #endif | 69 | # ifdef HAVE_CONFIG_H |
| 65 | 70 | # undef HAVE_NTGUI | |
| 66 | #if !defined (MSDOS) && !defined (WINDOWSNT) && defined (STDC_HEADERS) | 71 | # else |
| 72 | # define DOS_NT | ||
| 73 | # endif /* not HAVE_CONFIG_H */ | ||
| 74 | # ifndef HAVE_GETCWD | ||
| 75 | # define HAVE_GETCWD | ||
| 76 | # endif /* undef HAVE_GETCWD */ | ||
| 77 | #endif /* WINDOWSNT */ | ||
| 78 | |||
| 79 | #if !defined (WINDOWSNT) && defined (STDC_HEADERS) | ||
| 67 | #include <stdlib.h> | 80 | #include <stdlib.h> |
| 68 | #include <string.h> | 81 | #include <string.h> |
| 69 | #endif | 82 | #endif |
| 70 | 83 | ||
| 84 | #ifdef HAVE_UNISTD_H | ||
| 85 | # include <unistd.h> | ||
| 86 | #else | ||
| 87 | # ifdef HAVE_GETCWD | ||
| 88 | extern char *getcwd (); | ||
| 89 | # endif | ||
| 90 | #endif /* HAVE_UNISTD_H */ | ||
| 91 | |||
| 71 | #include <stdio.h> | 92 | #include <stdio.h> |
| 72 | #include <ctype.h> | 93 | #include <ctype.h> |
| 73 | #include <errno.h> | 94 | #include <errno.h> |
| 74 | #ifndef errno | 95 | #ifndef errno |
| 75 | extern int errno; | 96 | extern int errno; |
| 76 | #endif | 97 | #endif |
| 77 | #include <sys/types.h> | 98 | #include <sys/types.h> |
| 78 | #include <sys/stat.h> | 99 | #include <sys/stat.h> |
| 79 | 100 | ||
| 80 | /* This is to declare getcwd. */ | ||
| 81 | #ifdef HAVE_UNISTD_H | ||
| 82 | #include <unistd.h> | ||
| 83 | #endif | ||
| 84 | |||
| 85 | #if !defined (S_ISREG) && defined (S_IFREG) | 101 | #if !defined (S_ISREG) && defined (S_IFREG) |
| 86 | # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) | 102 | # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
| 87 | #endif | 103 | #endif |
| @@ -131,62 +147,55 @@ extern int errno; | |||
| 131 | #define lowcase(c) tolower ((char)c) | 147 | #define lowcase(c) tolower ((char)c) |
| 132 | 148 | ||
| 133 | #define CHARS 256 /* 2^sizeof(char) */ | 149 | #define CHARS 256 /* 2^sizeof(char) */ |
| 134 | #define CHAR(x) ((int)x & (CHARS - 1)) | 150 | #define CHAR(x) ((unsigned int)x & (CHARS - 1)) |
| 135 | #define iswhite(c) (_wht[CHAR(c)]) /* c is white */ | 151 | #define iswhite(c) (_wht[CHAR(c)]) /* c is white */ |
| 136 | #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ | 152 | #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ |
| 137 | #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ | 153 | #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ |
| 138 | #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ | 154 | #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ |
| 139 | #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ | 155 | #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ |
| 140 | 156 | ||
| 141 | #ifdef DOS_NT | ||
| 142 | # define absolutefn(fn) (fn[0] == '/' \ | ||
| 143 | || (fn[1] == ':' && fn[2] == '/')) | ||
| 144 | #else | ||
| 145 | # define absolutefn(fn) (fn[0] == '/') | ||
| 146 | #endif | ||
| 147 | |||
| 148 | 157 | ||
| 149 | /* | 158 | /* |
| 150 | * xnew -- allocate storage | 159 | * xnew, xrnew -- allocate, reallocate storage |
| 151 | * | 160 | * |
| 152 | * SYNOPSIS: Type *xnew (int n, Type); | 161 | * SYNOPSIS: Type *xnew (int n, Type); |
| 162 | * Type *xrnew (OldPointer, int n, Type); | ||
| 153 | */ | 163 | */ |
| 154 | #ifdef chkmalloc | 164 | #ifdef chkmalloc |
| 155 | # include "chkmalloc.h" | 165 | # include "chkmalloc.h" |
| 156 | # define xnew(n,Type) ((Type *) trace_xmalloc (__FILE__, __LINE__, \ | 166 | # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \ |
| 157 | (n) * sizeof (Type))) | 167 | (n) * sizeof (Type))) |
| 168 | # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \ | ||
| 169 | (op), (n) * sizeof (Type))) | ||
| 158 | #else | 170 | #else |
| 159 | # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) | 171 | # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) |
| 172 | # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type))) | ||
| 160 | #endif | 173 | #endif |
| 161 | 174 | ||
| 162 | typedef int bool; | 175 | typedef int bool; |
| 163 | 176 | ||
| 164 | typedef struct nd_st | 177 | typedef void Lang_function (); |
| 165 | { /* sorting structure */ | ||
| 166 | char *name; /* function or type name */ | ||
| 167 | char *file; /* file name */ | ||
| 168 | bool is_func; /* use pattern or line no */ | ||
| 169 | bool been_warned; /* set if noticed dup */ | ||
| 170 | int lno; /* line number tag is on */ | ||
| 171 | long cno; /* character number line starts on */ | ||
| 172 | char *pat; /* search pattern */ | ||
| 173 | struct nd_st *left, *right; /* left and right sons */ | ||
| 174 | } NODE; | ||
| 175 | 178 | ||
| 176 | extern char *getenv (); | 179 | typedef struct |
| 180 | { | ||
| 181 | char *suffix; | ||
| 182 | char *command; /* Takes one arg and decompresses to stdout */ | ||
| 183 | } compressor; | ||
| 177 | 184 | ||
| 178 | char *concat (); | 185 | typedef struct |
| 179 | char *savenstr (), *savestr (); | 186 | { |
| 180 | char *etags_strchr (), *etags_strrchr (); | 187 | char *name; |
| 181 | char *etags_getcwd (); | 188 | Lang_function *function; |
| 182 | char *relative_filename (), *absolute_filename (), *absolute_dirname (); | 189 | char **suffixes; |
| 183 | void grow_linebuffer (); | 190 | char **interpreters; |
| 184 | long *xmalloc (), *xrealloc (); | 191 | } language; |
| 192 | |||
| 193 | extern char *getenv (); | ||
| 185 | 194 | ||
| 186 | typedef void Lang_function (); | ||
| 187 | /* Many compilers barf on this: | 195 | /* Many compilers barf on this: |
| 188 | Lang_function Asm_labels; | 196 | Lang_function Ada_funcs; |
| 189 | so let's write it this way */ | 197 | so let's write it this way */ |
| 198 | void Ada_funcs (); | ||
| 190 | void Asm_labels (); | 199 | void Asm_labels (); |
| 191 | void C_entries (); | 200 | void C_entries (); |
| 192 | void default_C_entries (); | 201 | void default_C_entries (); |
| @@ -203,81 +212,111 @@ void Pascal_functions (); | |||
| 203 | void Perl_functions (); | 212 | void Perl_functions (); |
| 204 | void Postscript_functions (); | 213 | void Postscript_functions (); |
| 205 | void Prolog_functions (); | 214 | void Prolog_functions (); |
| 215 | void Python_functions (); | ||
| 206 | void Scheme_functions (); | 216 | void Scheme_functions (); |
| 207 | void TeX_functions (); | 217 | void TeX_functions (); |
| 208 | void just_read_file (); | 218 | void just_read_file (); |
| 209 | 219 | ||
| 210 | Lang_function *get_language_from_name (); | 220 | compressor *get_compressor_from_suffix (); |
| 211 | Lang_function *get_language_from_interpreter (); | 221 | language *get_language_from_name (); |
| 212 | Lang_function *get_language_from_suffix (); | 222 | language *get_language_from_interpreter (); |
| 223 | language *get_language_from_suffix (); | ||
| 213 | int total_size_of_entries (); | 224 | int total_size_of_entries (); |
| 214 | long readline (); | 225 | long readline (), readline_internal (); |
| 215 | long readline_internal (); | 226 | void get_tag (); |
| 227 | |||
| 216 | #ifdef ETAGS_REGEXPS | 228 | #ifdef ETAGS_REGEXPS |
| 217 | void analyse_regex (); | 229 | void analyse_regex (); |
| 218 | void add_regex (); | 230 | void add_regex (); |
| 231 | void free_patterns (); | ||
| 219 | #endif /* ETAGS_REGEXPS */ | 232 | #endif /* ETAGS_REGEXPS */ |
| 220 | void add_node (); | ||
| 221 | void error (); | 233 | void error (); |
| 222 | void suggest_asking_for_help (); | 234 | void suggest_asking_for_help (); |
| 223 | void fatal (), pfatal (); | 235 | void fatal (), pfatal (); |
| 224 | void find_entries (); | 236 | void add_node (); |
| 225 | void free_tree (); | 237 | |
| 226 | void getit (); | ||
| 227 | void init (); | 238 | void init (); |
| 228 | void initbuffer (); | 239 | void initbuffer (); |
| 240 | void find_entries (); | ||
| 241 | void free_tree (); | ||
| 229 | void pfnote (), new_pfnote (); | 242 | void pfnote (), new_pfnote (); |
| 230 | void process_file (); | 243 | void process_file (); |
| 231 | void put_entries (); | 244 | void put_entries (); |
| 232 | void takeprec (); | 245 | void takeprec (); |
| 233 | 246 | ||
| 247 | char *concat (); | ||
| 248 | char *skip_spaces (), *skip_non_spaces (); | ||
| 249 | char *savenstr (), *savestr (); | ||
| 250 | char *etags_strchr (), *etags_strrchr (); | ||
| 251 | char *etags_getcwd (); | ||
| 252 | char *relative_filename (), *absolute_filename (), *absolute_dirname (); | ||
| 253 | bool filename_is_absolute (); | ||
| 254 | void canonicalize_filename (); | ||
| 255 | void grow_linebuffer (); | ||
| 256 | long *xmalloc (), *xrealloc (); | ||
| 257 | |||
| 234 | 258 | ||
| 235 | char searchar = '/'; /* use /.../ searches */ | 259 | char searchar = '/'; /* use /.../ searches */ |
| 236 | 260 | ||
| 237 | int lineno; /* line number of current line */ | ||
| 238 | long charno; /* current character number */ | ||
| 239 | long linecharno; /* charno of start of line */ | ||
| 240 | |||
| 241 | char *curfile; /* current input file name */ | ||
| 242 | char *tagfile; /* output file */ | 261 | char *tagfile; /* output file */ |
| 243 | char *progname; /* name this program was invoked with */ | 262 | char *progname; /* name this program was invoked with */ |
| 244 | char *cwd; /* current working directory */ | 263 | char *cwd; /* current working directory */ |
| 245 | char *tagfiledir; /* directory of tagfile */ | 264 | char *tagfiledir; /* directory of tagfile */ |
| 246 | |||
| 247 | FILE *tagf; /* ioptr for tags file */ | 265 | FILE *tagf; /* ioptr for tags file */ |
| 248 | NODE *head; /* the head of the binary tree of tags */ | 266 | |
| 267 | char *curfile; /* current input file name */ | ||
| 268 | language *curlang; /* current language */ | ||
| 269 | |||
| 270 | int lineno; /* line number of current line */ | ||
| 271 | long charno; /* current character number */ | ||
| 272 | long linecharno; /* charno of start of current line */ | ||
| 273 | char *dbp; /* pointer to start of current tag */ | ||
| 274 | |||
| 275 | typedef struct node_st | ||
| 276 | { /* sorting structure */ | ||
| 277 | char *name; /* function or type name */ | ||
| 278 | char *file; /* file name */ | ||
| 279 | bool is_func; /* use pattern or line no */ | ||
| 280 | bool been_warned; /* set if noticed dup */ | ||
| 281 | int lno; /* line number tag is on */ | ||
| 282 | long cno; /* character number line starts on */ | ||
| 283 | char *pat; /* search pattern */ | ||
| 284 | struct node_st *left, *right; /* left and right sons */ | ||
| 285 | } node; | ||
| 286 | |||
| 287 | node *head; /* the head of the binary tree of tags */ | ||
| 249 | 288 | ||
| 250 | /* | 289 | /* |
| 251 | * A `struct linebuffer' is a structure which holds a line of text. | 290 | * A `linebuffer' is a structure which holds a line of text. |
| 252 | * `readline' reads a line from a stream into a linebuffer and works | 291 | * `readline_internal' reads a line from a stream into a linebuffer |
| 253 | * regardless of the length of the line. | 292 | * and works regardless of the length of the line. |
| 254 | * SIZE is the size of BUFFER, LEN is the length of the string in | 293 | * SIZE is the size of BUFFER, LEN is the length of the string in |
| 255 | * BUFFER after readline reads it. | 294 | * BUFFER after readline reads it. |
| 256 | */ | 295 | */ |
| 257 | struct linebuffer | 296 | typedef struct |
| 258 | { | 297 | { |
| 259 | long size; | 298 | long size; |
| 260 | int len; | 299 | int len; |
| 261 | char *buffer; | 300 | char *buffer; |
| 262 | }; | 301 | } linebuffer; |
| 263 | 302 | ||
| 264 | struct linebuffer lb; /* the current line */ | 303 | linebuffer lb; /* the current line */ |
| 265 | struct linebuffer token_name; /* used by C_entries as a temporary area */ | 304 | linebuffer token_name; /* used by C_entries as a temporary area */ |
| 266 | struct | 305 | struct |
| 267 | { | 306 | { |
| 268 | long linepos; | 307 | long linepos; |
| 269 | struct linebuffer lb; /* used by C_entries instead of lb */ | 308 | linebuffer lb; /* used by C_entries instead of lb */ |
| 270 | } lbs[2]; | 309 | } lbs[2]; |
| 271 | 310 | ||
| 272 | /* boolean "functions" (see init) */ | 311 | /* boolean "functions" (see init) */ |
| 273 | bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; | 312 | bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; |
| 274 | char | 313 | char |
| 275 | /* white chars */ | 314 | /* white chars */ |
| 276 | *white = " \f\t\n\013", | 315 | *white = " \f\t\n\r", |
| 277 | /* not in a name */ | 316 | /* not in a name */ |
| 278 | *nonam =" \f\t\n\013(=,[;", | 317 | *nonam = " \f\t\n\r(=,[;", |
| 279 | /* token ending chars */ | 318 | /* token ending chars */ |
| 280 | *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", | 319 | *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?", |
| 281 | /* token starting chars */ | 320 | /* token starting chars */ |
| 282 | *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@", | 321 | *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@", |
| 283 | /* valid in-token chars */ | 322 | /* valid in-token chars */ |
| @@ -285,14 +324,15 @@ char | |||
| 285 | 324 | ||
| 286 | bool append_to_tagfile; /* -a: append to tags */ | 325 | bool append_to_tagfile; /* -a: append to tags */ |
| 287 | /* The following four default to TRUE for etags, but to FALSE for ctags. */ | 326 | /* The following four default to TRUE for etags, but to FALSE for ctags. */ |
| 288 | bool typedefs; /* -t: create tags for C typedefs */ | 327 | bool typedefs; /* -t: create tags for C and Ada typedefs */ |
| 289 | bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */ | 328 | bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */ |
| 290 | /* 0 struct/enum/union decls, and C++ */ | 329 | /* 0 struct/enum/union decls, and C++ */ |
| 291 | /* member functions. */ | 330 | /* member functions. */ |
| 292 | bool constantypedefs; /* -d: create tags for C #define, enum */ | 331 | bool constantypedefs; /* -d: create tags for C #define, enum */ |
| 293 | /* constants and variables. */ | 332 | /* constants and variables. */ |
| 294 | /* -D: opposite of -d. Default under ctags. */ | 333 | /* -D: opposite of -d. Default under ctags. */ |
| 295 | bool globals; /* create tags for C global variables */ | 334 | bool declarations; /* --declarations: tag them and extern in C&Co*/ |
| 335 | bool globals; /* create tags for global variables */ | ||
| 296 | bool members; /* create tags for C member variables */ | 336 | bool members; /* create tags for C member variables */ |
| 297 | bool update; /* -u: update tags */ | 337 | bool update; /* -u: update tags */ |
| 298 | bool vgrind_style; /* -v: create vgrind style index output */ | 338 | bool vgrind_style; /* -v: create vgrind style index output */ |
| @@ -300,64 +340,87 @@ bool no_warnings; /* -w: suppress warnings */ | |||
| 300 | bool cxref_style; /* -x: create cxref style output */ | 340 | bool cxref_style; /* -x: create cxref style output */ |
| 301 | bool cplusplus; /* .[hc] means C++, not C */ | 341 | bool cplusplus; /* .[hc] means C++, not C */ |
| 302 | bool noindentypedefs; /* -I: ignore indentation in C */ | 342 | bool noindentypedefs; /* -I: ignore indentation in C */ |
| 343 | bool packages_only; /* --packages-only: in Ada, only tag packages*/ | ||
| 303 | 344 | ||
| 304 | #ifdef LONG_OPTIONS | 345 | #ifdef LONG_OPTIONS |
| 305 | struct option longopts[] = | 346 | struct option longopts[] = |
| 306 | { | 347 | { |
| 307 | { "append", no_argument, NULL, 'a' }, | 348 | { "packages-only", no_argument, &packages_only, TRUE }, |
| 308 | { "backward-search", no_argument, NULL, 'B' }, | 349 | { "append", no_argument, NULL, 'a' }, |
| 309 | { "c++", no_argument, NULL, 'C' }, | 350 | { "backward-search", no_argument, NULL, 'B' }, |
| 310 | { "cxref", no_argument, NULL, 'x' }, | 351 | { "c++", no_argument, NULL, 'C' }, |
| 311 | { "defines", no_argument, NULL, 'd' }, | 352 | { "cxref", no_argument, NULL, 'x' }, |
| 312 | { "no-defines", no_argument, NULL, 'D' }, | 353 | { "defines", no_argument, NULL, 'd' }, |
| 313 | { "globals", no_argument, &globals, TRUE }, | 354 | { "declarations", no_argument, &declarations, TRUE }, |
| 314 | { "no-globals", no_argument, &globals, FALSE }, | 355 | { "no-defines", no_argument, NULL, 'D' }, |
| 315 | { "help", no_argument, NULL, 'h' }, | 356 | { "globals", no_argument, &globals, TRUE }, |
| 316 | { "help", no_argument, NULL, 'H' }, | 357 | { "no-globals", no_argument, &globals, FALSE }, |
| 317 | { "ignore-indentation", no_argument, NULL, 'I' }, | 358 | { "help", no_argument, NULL, 'h' }, |
| 318 | { "include", required_argument, NULL, 'i' }, | 359 | { "help", no_argument, NULL, 'H' }, |
| 319 | { "language", required_argument, NULL, 'l' }, | 360 | { "ignore-indentation", no_argument, NULL, 'I' }, |
| 320 | { "members", no_argument, &members, TRUE }, | 361 | { "include", required_argument, NULL, 'i' }, |
| 321 | { "no-members", no_argument, &members, FALSE }, | 362 | { "language", required_argument, NULL, 'l' }, |
| 322 | { "no-warn", no_argument, NULL, 'w' }, | 363 | { "members", no_argument, &members, TRUE }, |
| 323 | { "output", required_argument, NULL, 'o' }, | 364 | { "no-members", no_argument, &members, FALSE }, |
| 324 | #ifdef ETAGS_REGEXPS | 365 | { "no-warn", no_argument, NULL, 'w' }, |
| 325 | { "regex", required_argument, NULL, 'r' }, | 366 | { "output", required_argument, NULL, 'o' }, |
| 326 | { "no-regex", no_argument, NULL, 'R' }, | 367 | #ifdef ETAGS_REGEXPS |
| 327 | #endif /* ETAGS_REGEXPS */ | 368 | { "regex", required_argument, NULL, 'r' }, |
| 328 | { "typedefs", no_argument, NULL, 't' }, | 369 | { "no-regex", no_argument, NULL, 'R' }, |
| 329 | { "typedefs-and-c++", no_argument, NULL, 'T' }, | 370 | { "ignore-case-regex", required_argument, NULL, 'c' }, |
| 330 | { "update", no_argument, NULL, 'u' }, | 371 | #endif /* ETAGS_REGEXPS */ |
| 331 | { "version", no_argument, NULL, 'V' }, | 372 | { "typedefs", no_argument, NULL, 't' }, |
| 332 | { "vgrind", no_argument, NULL, 'v' }, | 373 | { "typedefs-and-c++", no_argument, NULL, 'T' }, |
| 333 | { 0 } | 374 | { "update", no_argument, NULL, 'u' }, |
| 375 | { "version", no_argument, NULL, 'V' }, | ||
| 376 | { "vgrind", no_argument, NULL, 'v' }, | ||
| 377 | { NULL } | ||
| 334 | }; | 378 | }; |
| 335 | #endif /* LONG_OPTIONS */ | 379 | #endif /* LONG_OPTIONS */ |
| 336 | 380 | ||
| 337 | #ifdef ETAGS_REGEXPS | 381 | #ifdef ETAGS_REGEXPS |
| 338 | /* Structure defining a regular expression. Elements are | 382 | /* Structure defining a regular expression. Elements are |
| 339 | the compiled pattern, and the name string. */ | 383 | the compiled pattern, and the name string. */ |
| 340 | struct pattern | 384 | typedef struct pattern |
| 341 | { | 385 | { |
| 386 | struct pattern *p_next; | ||
| 387 | language *language; | ||
| 388 | char *regex; | ||
| 342 | struct re_pattern_buffer *pattern; | 389 | struct re_pattern_buffer *pattern; |
| 343 | struct re_registers regs; | 390 | struct re_registers regs; |
| 344 | char *name_pattern; | 391 | char *name_pattern; |
| 345 | bool error_signaled; | 392 | bool error_signaled; |
| 346 | }; | 393 | } pattern; |
| 347 | 394 | ||
| 348 | /* Number of regexps found. */ | 395 | /* List of all regexps. */ |
| 349 | int num_patterns = 0; | 396 | pattern *p_head = NULL; |
| 350 | 397 | ||
| 351 | /* Array of all regexps. */ | 398 | /* How many characters in the character set. (From regex.c.) */ |
| 352 | struct pattern *patterns = NULL; | 399 | #define CHAR_SET_SIZE 256 |
| 400 | /* Translation table for case-insensitive matching. */ | ||
| 401 | char lc_trans[CHAR_SET_SIZE]; | ||
| 353 | #endif /* ETAGS_REGEXPS */ | 402 | #endif /* ETAGS_REGEXPS */ |
| 354 | 403 | ||
| 404 | compressor compressors[] = | ||
| 405 | { | ||
| 406 | { "z", "gzip -d -c"}, | ||
| 407 | { "Z", "gzip -d -c"}, | ||
| 408 | { "gz", "gzip -d -c"}, | ||
| 409 | { "GZ", "gzip -d -c"}, | ||
| 410 | { "bz2", "bzip2 -d -c" }, | ||
| 411 | { NULL } | ||
| 412 | }; | ||
| 413 | |||
| 355 | /* | 414 | /* |
| 356 | * Language stuff. | 415 | * Language stuff. |
| 357 | */ | 416 | */ |
| 358 | 417 | ||
| 359 | /* Non-NULL if language fixed. */ | 418 | /* Non-NULL if language fixed. */ |
| 360 | Lang_function *lang_func = NULL; | 419 | language *forced_lang = NULL; |
| 420 | |||
| 421 | /* Ada code */ | ||
| 422 | char *Ada_suffixes [] = | ||
| 423 | { "ads", "adb", "ada", NULL }; | ||
| 361 | 424 | ||
| 362 | /* Assembly code */ | 425 | /* Assembly code */ |
| 363 | char *Asm_suffixes [] = { "a", /* Unix assembler */ | 426 | char *Asm_suffixes [] = { "a", /* Unix assembler */ |
| @@ -415,14 +478,17 @@ char *plain_C_suffixes [] = | |||
| 415 | NULL }; | 478 | NULL }; |
| 416 | 479 | ||
| 417 | char *Postscript_suffixes [] = | 480 | char *Postscript_suffixes [] = |
| 418 | { "ps", NULL }; | 481 | { "ps", "psw", NULL }; /* .psw is for PSWrap */ |
| 419 | 482 | ||
| 420 | char *Prolog_suffixes [] = | 483 | char *Prolog_suffixes [] = |
| 421 | { "prolog", NULL }; | 484 | { "prolog", NULL }; |
| 422 | 485 | ||
| 486 | char *Python_suffixes [] = | ||
| 487 | { "py", NULL }; | ||
| 488 | |||
| 423 | /* Can't do the `SCM' or `scm' prefix with a version number. */ | 489 | /* Can't do the `SCM' or `scm' prefix with a version number. */ |
| 424 | char *Scheme_suffixes [] = | 490 | char *Scheme_suffixes [] = |
| 425 | { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "t", NULL }; | 491 | { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL }; |
| 426 | 492 | ||
| 427 | char *TeX_suffixes [] = | 493 | char *TeX_suffixes [] = |
| 428 | { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL }; | 494 | { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL }; |
| @@ -430,20 +496,16 @@ char *TeX_suffixes [] = | |||
| 430 | char *Yacc_suffixes [] = | 496 | char *Yacc_suffixes [] = |
| 431 | { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */ | 497 | { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */ |
| 432 | 498 | ||
| 433 | /* Table of language names and corresponding functions, file suffixes | 499 | /* |
| 434 | and interpreter names. | 500 | * Table of languages. |
| 435 | It is ok for a given function to be listed under more than one | 501 | * |
| 436 | name. I just didn't. */ | 502 | * It is ok for a given function to be listed under more than one |
| 437 | struct lang_entry | 503 | * name. I just didn't. |
| 438 | { | 504 | */ |
| 439 | char *name; | ||
| 440 | Lang_function *function; | ||
| 441 | char **suffixes; | ||
| 442 | char **interpreters; | ||
| 443 | }; | ||
| 444 | 505 | ||
| 445 | struct lang_entry lang_names [] = | 506 | language lang_names [] = |
| 446 | { | 507 | { |
| 508 | { "ada", Ada_funcs, Ada_suffixes, NULL }, | ||
| 447 | { "asm", Asm_labels, Asm_suffixes, NULL }, | 509 | { "asm", Asm_labels, Asm_suffixes, NULL }, |
| 448 | { "c", default_C_entries, default_C_suffixes, NULL }, | 510 | { "c", default_C_entries, default_C_suffixes, NULL }, |
| 449 | { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, | 511 | { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, |
| @@ -458,6 +520,7 @@ struct lang_entry lang_names [] = | |||
| 458 | { "postscript", Postscript_functions, Postscript_suffixes, NULL }, | 520 | { "postscript", Postscript_functions, Postscript_suffixes, NULL }, |
| 459 | { "proc", plain_C_entries, plain_C_suffixes, NULL }, | 521 | { "proc", plain_C_entries, plain_C_suffixes, NULL }, |
| 460 | { "prolog", Prolog_functions, Prolog_suffixes, NULL }, | 522 | { "prolog", Prolog_functions, Prolog_suffixes, NULL }, |
| 523 | { "python", Python_functions, Python_suffixes, NULL }, | ||
| 461 | { "scheme", Scheme_functions, Scheme_suffixes, NULL }, | 524 | { "scheme", Scheme_functions, Scheme_suffixes, NULL }, |
| 462 | { "tex", TeX_functions, TeX_suffixes, NULL }, | 525 | { "tex", TeX_functions, TeX_suffixes, NULL }, |
| 463 | { "yacc", Yacc_entries, Yacc_suffixes, NULL }, | 526 | { "yacc", Yacc_entries, Yacc_suffixes, NULL }, |
| @@ -465,12 +528,11 @@ struct lang_entry lang_names [] = | |||
| 465 | { "none", just_read_file }, /* regexp matching only */ | 528 | { "none", just_read_file }, /* regexp matching only */ |
| 466 | { NULL, NULL } /* end of list */ | 529 | { NULL, NULL } /* end of list */ |
| 467 | }; | 530 | }; |
| 468 | |||
| 469 | 531 | ||
| 470 | void | 532 | void |
| 471 | print_language_names () | 533 | print_language_names () |
| 472 | { | 534 | { |
| 473 | struct lang_entry *lang; | 535 | language *lang; |
| 474 | char **ext; | 536 | char **ext; |
| 475 | 537 | ||
| 476 | puts ("\nThese are the currently supported languages, along with the\n\ | 538 | puts ("\nThese are the currently supported languages, along with the\n\ |
| @@ -488,11 +550,12 @@ name suffix, and `none' means only do regexp processing on files.\n\ | |||
| 488 | If no language is specified and no matching suffix is found,\n\ | 550 | If no language is specified and no matching suffix is found,\n\ |
| 489 | the first line of the file is read for a sharp-bang (#!) sequence\n\ | 551 | the first line of the file is read for a sharp-bang (#!) sequence\n\ |
| 490 | followed by the name of an interpreter. If no such sequence is found,\n\ | 552 | followed by the name of an interpreter. If no such sequence is found,\n\ |
| 491 | Fortran is tried first; if no tags are found, C is tried next."); | 553 | Fortran is tried first; if no tags are found, C is tried next.\n\ |
| 554 | Compressed files are supported using gzip and bzip2."); | ||
| 492 | } | 555 | } |
| 493 | 556 | ||
| 494 | #ifndef VERSION | 557 | #ifndef VERSION |
| 495 | # define VERSION "19" | 558 | # define VERSION "20" |
| 496 | #endif | 559 | #endif |
| 497 | void | 560 | void |
| 498 | print_version () | 561 | print_version () |
| @@ -516,15 +579,18 @@ These are the options accepted by %s.\n", progname, progname); | |||
| 516 | puts ("Long option names do not work with this executable, as it is not\n\ | 579 | puts ("Long option names do not work with this executable, as it is not\n\ |
| 517 | linked with GNU getopt."); | 580 | linked with GNU getopt."); |
| 518 | #endif /* LONG_OPTIONS */ | 581 | #endif /* LONG_OPTIONS */ |
| 519 | puts ("A - as file name means read names from stdin."); | 582 | puts ("A - as file name means read names from stdin (one per line)."); |
| 520 | if (!CTAGS) | 583 | if (!CTAGS) |
| 521 | printf (" Absolute names are stored in the output file as they\n\ | 584 | printf (" Absolute names are stored in the output file as they are.\n\ |
| 522 | are. Relative ones are stored relative to the output file's directory."); | 585 | Relative ones are stored relative to the output file's directory."); |
| 523 | puts ("\n"); | 586 | puts ("\n"); |
| 524 | 587 | ||
| 525 | puts ("-a, --append\n\ | 588 | puts ("-a, --append\n\ |
| 526 | Append tag entries to existing tags file."); | 589 | Append tag entries to existing tags file."); |
| 527 | 590 | ||
| 591 | puts ("--packages-only\n\ | ||
| 592 | For Ada files, only generate tags for packages ."); | ||
| 593 | |||
| 528 | if (CTAGS) | 594 | if (CTAGS) |
| 529 | puts ("-B, --backward-search\n\ | 595 | puts ("-B, --backward-search\n\ |
| 530 | Write the search commands for the tag entries using '?', the\n\ | 596 | Write the search commands for the tag entries using '?', the\n\ |
| @@ -533,6 +599,14 @@ are. Relative ones are stored relative to the output file's directory."); | |||
| 533 | puts ("-C, --c++\n\ | 599 | puts ("-C, --c++\n\ |
| 534 | Treat files whose name suffix defaults to C language as C++ files."); | 600 | Treat files whose name suffix defaults to C language as C++ files."); |
| 535 | 601 | ||
| 602 | puts ("--declarations\n\ | ||
| 603 | In C and derived languages, create tags for function declarations,"); | ||
| 604 | if (CTAGS) | ||
| 605 | puts ("\tand create tags for extern variables if --globals is used."); | ||
| 606 | else | ||
| 607 | puts | ||
| 608 | ("\tand create tags for extern variables unless --no-globals is used."); | ||
| 609 | |||
| 536 | if (CTAGS) | 610 | if (CTAGS) |
| 537 | puts ("-d, --defines\n\ | 611 | puts ("-d, --defines\n\ |
| 538 | Create tag entries for C #define constants and enum constants, too."); | 612 | Create tag entries for C #define constants and enum constants, too."); |
| @@ -554,22 +628,25 @@ are. Relative ones are stored relative to the output file's directory."); | |||
| 554 | 628 | ||
| 555 | if (CTAGS) | 629 | if (CTAGS) |
| 556 | puts ("--globals\n\ | 630 | puts ("--globals\n\ |
| 557 | Create tag entries for global variables in C and derived languages."); | 631 | Create tag entries for global variables in some languages."); |
| 558 | else | 632 | else |
| 559 | puts ("--no-globals\n\ | 633 | puts ("--no-globals\n\ |
| 560 | Do not create tag entries for global variables in C and\n\ | 634 | Do not create tag entries for global variables in some\n\ |
| 561 | derived languages. This makes the tags file smaller."); | 635 | languages. This makes the tags file smaller."); |
| 562 | puts ("--members\n\ | 636 | puts ("--members\n\ |
| 563 | Create tag entries for member variables in C and derived languages."); | 637 | Create tag entries for member variables in C and derived languages."); |
| 564 | 638 | ||
| 565 | #ifdef ETAGS_REGEXPS | 639 | #ifdef ETAGS_REGEXPS |
| 566 | puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\ | 640 | puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\ |
| 567 | Make a tag for each line matching pattern REGEXP in the\n\ | 641 | Make a tag for each line matching pattern REGEXP in the following\n\ |
| 568 | following files. regexfile is a file containing one REGEXP\n\ | 642 | files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\ |
| 569 | per line. REGEXP is anchored (as if preceded by ^).\n\ | 643 | regexfile is a file containing one REGEXP per line.\n\ |
| 570 | The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\ | 644 | REGEXP is anchored (as if preceded by ^).\n\ |
| 571 | named tags can be created with:\n\ | 645 | The form /REGEXP/NAME/ creates a named tag.\n\ |
| 646 | For example Tcl named tags can be created with:\n\ | ||
| 572 | --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/."); | 647 | --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/."); |
| 648 | puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\ | ||
| 649 | Like -r, --regex but ignore case when matching expressions."); | ||
| 573 | puts ("-R, --no-regex\n\ | 650 | puts ("-R, --no-regex\n\ |
| 574 | Don't create tags from regexps for the following files."); | 651 | Don't create tags from regexps for the following files."); |
| 575 | #endif /* ETAGS_REGEXPS */ | 652 | #endif /* ETAGS_REGEXPS */ |
| @@ -584,7 +661,7 @@ are. Relative ones are stored relative to the output file's directory."); | |||
| 584 | if (CTAGS) | 661 | if (CTAGS) |
| 585 | { | 662 | { |
| 586 | puts ("-t, --typedefs\n\ | 663 | puts ("-t, --typedefs\n\ |
| 587 | Generate tag entries for C typedefs."); | 664 | Generate tag entries for C and Ada typedefs."); |
| 588 | puts ("-T, --typedefs-and-c++\n\ | 665 | puts ("-T, --typedefs-and-c++\n\ |
| 589 | Generate tag entries for C typedefs, C struct/enum/union tags,\n\ | 666 | Generate tag entries for C typedefs, C struct/enum/union tags,\n\ |
| 590 | and C++ member functions."); | 667 | and C++ member functions."); |
| @@ -627,7 +704,8 @@ enum argument_type | |||
| 627 | { | 704 | { |
| 628 | at_language, | 705 | at_language, |
| 629 | at_regexp, | 706 | at_regexp, |
| 630 | at_filename | 707 | at_filename, |
| 708 | at_icregexp | ||
| 631 | }; | 709 | }; |
| 632 | 710 | ||
| 633 | /* This structure helps us allow mixing of --lang and file names. */ | 711 | /* This structure helps us allow mixing of --lang and file names. */ |
| @@ -635,7 +713,7 @@ typedef struct | |||
| 635 | { | 713 | { |
| 636 | enum argument_type arg_type; | 714 | enum argument_type arg_type; |
| 637 | char *what; | 715 | char *what; |
| 638 | Lang_function *function; | 716 | language *lang; /* language of the regexp */ |
| 639 | } argument; | 717 | } argument; |
| 640 | 718 | ||
| 641 | #ifdef VMS /* VMS specific functions */ | 719 | #ifdef VMS /* VMS specific functions */ |
| @@ -774,7 +852,7 @@ main (argc, argv) | |||
| 774 | char *this_file; | 852 | char *this_file; |
| 775 | argument *argbuffer; | 853 | argument *argbuffer; |
| 776 | int current_arg, file_count; | 854 | int current_arg, file_count; |
| 777 | struct linebuffer filename_lb; | 855 | linebuffer filename_lb; |
| 778 | #ifdef VMS | 856 | #ifdef VMS |
| 779 | bool got_err; | 857 | bool got_err; |
| 780 | #endif | 858 | #endif |
| @@ -795,13 +873,16 @@ main (argc, argv) | |||
| 795 | 873 | ||
| 796 | #ifdef ETAGS_REGEXPS | 874 | #ifdef ETAGS_REGEXPS |
| 797 | /* Set syntax for regular expression routines. */ | 875 | /* Set syntax for regular expression routines. */ |
| 798 | re_set_syntax (RE_SYNTAX_EMACS); | 876 | re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS); |
| 877 | /* Translation table for case-insensitive search. */ | ||
| 878 | for (i = 0; i < CHAR_SET_SIZE; i++) | ||
| 879 | lc_trans[i] = lowcase (i); | ||
| 799 | #endif /* ETAGS_REGEXPS */ | 880 | #endif /* ETAGS_REGEXPS */ |
| 800 | 881 | ||
| 801 | /* | 882 | /* |
| 802 | * If etags, always find typedefs and structure tags. Why not? | 883 | * If etags, always find typedefs and structure tags. Why not? |
| 803 | * Also default is to find macro constants, enum constants and | 884 | * Also default is to find macro constants, enum constants and |
| 804 | * global variables. | 885 | * global variables. |
| 805 | */ | 886 | */ |
| 806 | if (!CTAGS) | 887 | if (!CTAGS) |
| 807 | { | 888 | { |
| @@ -816,7 +897,7 @@ main (argc, argv) | |||
| 816 | char *optstring; | 897 | char *optstring; |
| 817 | 898 | ||
| 818 | #ifdef ETAGS_REGEXPS | 899 | #ifdef ETAGS_REGEXPS |
| 819 | optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH"; | 900 | optstring = "-aCdDf:Il:o:r:c:RStTi:BuvxwVhH"; |
| 820 | #else | 901 | #else |
| 821 | optstring = "-aCdDf:Il:o:StTi:BuvxwVhH"; | 902 | optstring = "-aCdDf:Il:o:StTi:BuvxwVhH"; |
| 822 | #endif /* ETAGS_REGEXPS */ | 903 | #endif /* ETAGS_REGEXPS */ |
| @@ -863,9 +944,15 @@ main (argc, argv) | |||
| 863 | noindentypedefs = TRUE; | 944 | noindentypedefs = TRUE; |
| 864 | break; | 945 | break; |
| 865 | case 'l': | 946 | case 'l': |
| 866 | argbuffer[current_arg].function = get_language_from_name (optarg); | 947 | { |
| 867 | argbuffer[current_arg].arg_type = at_language; | 948 | language *lang = get_language_from_name (optarg); |
| 868 | ++current_arg; | 949 | if (lang != NULL) |
| 950 | { | ||
| 951 | argbuffer[current_arg].lang = lang; | ||
| 952 | argbuffer[current_arg].arg_type = at_language; | ||
| 953 | ++current_arg; | ||
| 954 | } | ||
| 955 | } | ||
| 869 | break; | 956 | break; |
| 870 | #ifdef ETAGS_REGEXPS | 957 | #ifdef ETAGS_REGEXPS |
| 871 | case 'r': | 958 | case 'r': |
| @@ -878,6 +965,11 @@ main (argc, argv) | |||
| 878 | argbuffer[current_arg].what = NULL; | 965 | argbuffer[current_arg].what = NULL; |
| 879 | ++current_arg; | 966 | ++current_arg; |
| 880 | break; | 967 | break; |
| 968 | case 'c': | ||
| 969 | argbuffer[current_arg].arg_type = at_icregexp; | ||
| 970 | argbuffer[current_arg].what = optarg; | ||
| 971 | ++current_arg; | ||
| 972 | break; | ||
| 881 | #endif /* ETAGS_REGEXPS */ | 973 | #endif /* ETAGS_REGEXPS */ |
| 882 | case 'V': | 974 | case 'V': |
| 883 | print_version (); | 975 | print_version (); |
| @@ -972,11 +1064,14 @@ main (argc, argv) | |||
| 972 | switch (argbuffer[i].arg_type) | 1064 | switch (argbuffer[i].arg_type) |
| 973 | { | 1065 | { |
| 974 | case at_language: | 1066 | case at_language: |
| 975 | lang_func = argbuffer[i].function; | 1067 | forced_lang = argbuffer[i].lang; |
| 976 | break; | 1068 | break; |
| 977 | #ifdef ETAGS_REGEXPS | 1069 | #ifdef ETAGS_REGEXPS |
| 978 | case at_regexp: | 1070 | case at_regexp: |
| 979 | analyse_regex (argbuffer[i].what); | 1071 | analyse_regex (argbuffer[i].what, FALSE); |
| 1072 | break; | ||
| 1073 | case at_icregexp: | ||
| 1074 | analyse_regex (argbuffer[i].what, TRUE); | ||
| 980 | break; | 1075 | break; |
| 981 | #endif | 1076 | #endif |
| 982 | case at_filename: | 1077 | case at_filename: |
| @@ -996,7 +1091,7 @@ main (argc, argv) | |||
| 996 | this_file = argbuffer[i].what; | 1091 | this_file = argbuffer[i].what; |
| 997 | #endif | 1092 | #endif |
| 998 | /* Input file named "-" means read file names from stdin | 1093 | /* Input file named "-" means read file names from stdin |
| 999 | and use them. */ | 1094 | (one per line) and use them. */ |
| 1000 | if (streq (this_file, "-")) | 1095 | if (streq (this_file, "-")) |
| 1001 | while (readline_internal (&filename_lb, stdin) > 0) | 1096 | while (readline_internal (&filename_lb, stdin) > 0) |
| 1002 | process_file (filename_lb.buffer); | 1097 | process_file (filename_lb.buffer); |
| @@ -1009,6 +1104,10 @@ main (argc, argv) | |||
| 1009 | } | 1104 | } |
| 1010 | } | 1105 | } |
| 1011 | 1106 | ||
| 1107 | #ifdef ETAGS_REGEXPS | ||
| 1108 | free_patterns (); | ||
| 1109 | #endif /* ETAGS_REGEXPS */ | ||
| 1110 | |||
| 1012 | if (!CTAGS) | 1111 | if (!CTAGS) |
| 1013 | { | 1112 | { |
| 1014 | while (nincluded_files-- > 0) | 1113 | while (nincluded_files-- > 0) |
| @@ -1023,6 +1122,8 @@ main (argc, argv) | |||
| 1023 | if (cxref_style) | 1122 | if (cxref_style) |
| 1024 | { | 1123 | { |
| 1025 | put_entries (head); | 1124 | put_entries (head); |
| 1125 | free_tree (head); | ||
| 1126 | head = NULL; | ||
| 1026 | exit (GOOD); | 1127 | exit (GOOD); |
| 1027 | } | 1128 | } |
| 1028 | 1129 | ||
| @@ -1046,6 +1147,8 @@ main (argc, argv) | |||
| 1046 | if (tagf == NULL) | 1147 | if (tagf == NULL) |
| 1047 | pfatal (tagfile); | 1148 | pfatal (tagfile); |
| 1048 | put_entries (head); | 1149 | put_entries (head); |
| 1150 | free_tree (head); | ||
| 1151 | head = NULL; | ||
| 1049 | fclose (tagf); | 1152 | fclose (tagf); |
| 1050 | 1153 | ||
| 1051 | if (update) | 1154 | if (update) |
| @@ -1058,41 +1161,81 @@ main (argc, argv) | |||
| 1058 | } | 1161 | } |
| 1059 | 1162 | ||
| 1060 | 1163 | ||
| 1164 | |||
| 1165 | /* | ||
| 1166 | * Return a compressor given the file name. If EXTPTR is non-zero, | ||
| 1167 | * return a pointer into FILE where the compressor-specific | ||
| 1168 | * extension begins. If no compressor is found, NULL is returned | ||
| 1169 | * and EXTPTR is not significant. | ||
| 1170 | * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> | ||
| 1171 | */ | ||
| 1172 | compressor * | ||
| 1173 | get_compressor_from_suffix (file, extptr) | ||
| 1174 | char *file; | ||
| 1175 | char **extptr; | ||
| 1176 | { | ||
| 1177 | compressor *compr; | ||
| 1178 | char *slash, *suffix; | ||
| 1179 | |||
| 1180 | /* This relies on FN to be after canonicalize_filename, | ||
| 1181 | so we don't need to consider backslashes on DOS_NT. */ | ||
| 1182 | slash = etags_strrchr (file, '/'); | ||
| 1183 | suffix = etags_strrchr (file, '.'); | ||
| 1184 | if (suffix == NULL || suffix < slash) | ||
| 1185 | return NULL; | ||
| 1186 | if (extptr != NULL) | ||
| 1187 | *extptr = suffix; | ||
| 1188 | suffix += 1; | ||
| 1189 | /* Let those poor souls who live with DOS 8+3 file name limits get | ||
| 1190 | some solace by treating foo.cgz as if it were foo.c.gz, etc. | ||
| 1191 | Only the first do loop is run if not MSDOS */ | ||
| 1192 | do | ||
| 1193 | { | ||
| 1194 | for (compr = compressors; compr->suffix != NULL; compr++) | ||
| 1195 | if (streq (compr->suffix, suffix)) | ||
| 1196 | return compr; | ||
| 1197 | #ifndef MSDOS | ||
| 1198 | break; | ||
| 1199 | #endif | ||
| 1200 | if (extptr != NULL) | ||
| 1201 | *extptr = ++suffix; | ||
| 1202 | } while (*suffix != '\0'); | ||
| 1203 | return NULL; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | |||
| 1207 | |||
| 1061 | /* | 1208 | /* |
| 1062 | * Return a Lang_function given the name. | 1209 | * Return a language given the name. |
| 1063 | */ | 1210 | */ |
| 1064 | Lang_function * | 1211 | language * |
| 1065 | get_language_from_name (name) | 1212 | get_language_from_name (name) |
| 1066 | char *name; | 1213 | char *name; |
| 1067 | { | 1214 | { |
| 1068 | struct lang_entry *lang; | 1215 | language *lang; |
| 1069 | 1216 | ||
| 1070 | if (name != NULL) | 1217 | if (name == NULL) |
| 1071 | for (lang = lang_names; lang->name != NULL; lang++) | 1218 | error ("empty language name", (char *)NULL); |
| 1072 | { | 1219 | else |
| 1220 | { | ||
| 1221 | for (lang = lang_names; lang->name != NULL; lang++) | ||
| 1073 | if (streq (name, lang->name)) | 1222 | if (streq (name, lang->name)) |
| 1074 | return lang->function; | 1223 | return lang; |
| 1075 | } | 1224 | error ("unknown language \"%s\"", name); |
| 1076 | 1225 | } | |
| 1077 | error ("language \"%s\" not recognized.", optarg); | ||
| 1078 | suggest_asking_for_help (); | ||
| 1079 | 1226 | ||
| 1080 | /* This point should never be reached. The function should either | 1227 | return NULL; |
| 1081 | return a function pointer or never return. Note that a NULL | ||
| 1082 | pointer cannot be considered as an error, as it means that the | ||
| 1083 | language has not been explicitely imposed by the user ("auto"). */ | ||
| 1084 | return NULL; /* avoid warnings from compiler */ | ||
| 1085 | } | 1228 | } |
| 1086 | 1229 | ||
| 1087 | 1230 | ||
| 1088 | /* | 1231 | /* |
| 1089 | * Return a Lang_function given the interpreter name. | 1232 | * Return a language given the interpreter name. |
| 1090 | */ | 1233 | */ |
| 1091 | Lang_function * | 1234 | language * |
| 1092 | get_language_from_interpreter (interpreter) | 1235 | get_language_from_interpreter (interpreter) |
| 1093 | char *interpreter; | 1236 | char *interpreter; |
| 1094 | { | 1237 | { |
| 1095 | struct lang_entry *lang; | 1238 | language *lang; |
| 1096 | char **iname; | 1239 | char **iname; |
| 1097 | 1240 | ||
| 1098 | if (interpreter == NULL) | 1241 | if (interpreter == NULL) |
| @@ -1101,7 +1244,7 @@ get_language_from_interpreter (interpreter) | |||
| 1101 | if (lang->interpreters != NULL) | 1244 | if (lang->interpreters != NULL) |
| 1102 | for (iname = lang->interpreters; *iname != NULL; iname++) | 1245 | for (iname = lang->interpreters; *iname != NULL; iname++) |
| 1103 | if (streq (*iname, interpreter)) | 1246 | if (streq (*iname, interpreter)) |
| 1104 | return lang->function; | 1247 | return lang; |
| 1105 | 1248 | ||
| 1106 | return NULL; | 1249 | return NULL; |
| 1107 | } | 1250 | } |
| @@ -1109,27 +1252,29 @@ get_language_from_interpreter (interpreter) | |||
| 1109 | 1252 | ||
| 1110 | 1253 | ||
| 1111 | /* | 1254 | /* |
| 1112 | * Return a Lang_function given the file suffix. | 1255 | * Return a language given the file name. |
| 1113 | */ | 1256 | */ |
| 1114 | Lang_function * | 1257 | language * |
| 1115 | get_language_from_suffix (suffix) | 1258 | get_language_from_suffix (file) |
| 1116 | char *suffix; | 1259 | char *file; |
| 1117 | { | 1260 | { |
| 1118 | struct lang_entry *lang; | 1261 | language *lang; |
| 1119 | char **ext; | 1262 | char **ext, *suffix; |
| 1120 | 1263 | ||
| 1264 | suffix = etags_strrchr (file, '.'); | ||
| 1121 | if (suffix == NULL) | 1265 | if (suffix == NULL) |
| 1122 | return NULL; | 1266 | return NULL; |
| 1267 | suffix += 1; | ||
| 1123 | for (lang = lang_names; lang->name != NULL; lang++) | 1268 | for (lang = lang_names; lang->name != NULL; lang++) |
| 1124 | if (lang->suffixes != NULL) | 1269 | if (lang->suffixes != NULL) |
| 1125 | for (ext = lang->suffixes; *ext != NULL; ext++) | 1270 | for (ext = lang->suffixes; *ext != NULL; ext++) |
| 1126 | if (streq (*ext, suffix)) | 1271 | if (streq (*ext, suffix)) |
| 1127 | return lang->function; | 1272 | return lang; |
| 1128 | |||
| 1129 | return NULL; | 1273 | return NULL; |
| 1130 | } | 1274 | } |
| 1131 | 1275 | ||
| 1132 | 1276 | ||
| 1277 | |||
| 1133 | /* | 1278 | /* |
| 1134 | * This routine is called on each file argument. | 1279 | * This routine is called on each file argument. |
| 1135 | */ | 1280 | */ |
| @@ -1139,47 +1284,136 @@ process_file (file) | |||
| 1139 | { | 1284 | { |
| 1140 | struct stat stat_buf; | 1285 | struct stat stat_buf; |
| 1141 | FILE *inf; | 1286 | FILE *inf; |
| 1142 | #ifdef DOS_NT | 1287 | compressor *compr; |
| 1143 | char *p; | 1288 | char *compressed_name, *uncompressed_name; |
| 1289 | char *ext, *real_name; | ||
| 1144 | 1290 | ||
| 1145 | for (p = file; *p != '\0'; p++) | ||
| 1146 | if (*p == '\\') | ||
| 1147 | *p = '/'; | ||
| 1148 | #endif | ||
| 1149 | 1291 | ||
| 1150 | if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode)) | 1292 | canonicalize_filename (file); |
| 1151 | { | ||
| 1152 | error ("skipping %s: it is not a regular file.", file); | ||
| 1153 | return; | ||
| 1154 | } | ||
| 1155 | if (streq (file, tagfile) && !streq (tagfile, "-")) | 1293 | if (streq (file, tagfile) && !streq (tagfile, "-")) |
| 1156 | { | 1294 | { |
| 1157 | error ("skipping inclusion of %s in self.", file); | 1295 | error ("skipping inclusion of %s in self.", file); |
| 1158 | return; | 1296 | return; |
| 1159 | } | 1297 | } |
| 1160 | inf = fopen (file, "r"); | 1298 | if ((compr = get_compressor_from_suffix (file, &ext)) == NULL) |
| 1299 | { | ||
| 1300 | compressed_name = NULL; | ||
| 1301 | real_name = uncompressed_name = savestr (file); | ||
| 1302 | } | ||
| 1303 | else | ||
| 1304 | { | ||
| 1305 | real_name = compressed_name = savestr (file); | ||
| 1306 | uncompressed_name = savenstr (file, ext - file); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | /* If the canonicalised uncompressed name has already be dealt with, | ||
| 1310 | skip it silently, else add it to the list. */ | ||
| 1311 | { | ||
| 1312 | typedef struct processed_file | ||
| 1313 | { | ||
| 1314 | char *filename; | ||
| 1315 | struct processed_file *next; | ||
| 1316 | } processed_file; | ||
| 1317 | static processed_file *pf_head = NULL; | ||
| 1318 | register processed_file *fnp; | ||
| 1319 | |||
| 1320 | for (fnp = pf_head; fnp != NULL; fnp = fnp->next) | ||
| 1321 | if (streq (uncompressed_name, fnp->filename)) | ||
| 1322 | goto exit; | ||
| 1323 | fnp = pf_head; | ||
| 1324 | pf_head = xnew (1, struct processed_file); | ||
| 1325 | pf_head->filename = savestr (uncompressed_name); | ||
| 1326 | pf_head->next = fnp; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | if (stat (real_name, &stat_buf) != 0) | ||
| 1330 | { | ||
| 1331 | /* Reset real_name and try with a different name. */ | ||
| 1332 | real_name = NULL; | ||
| 1333 | if (compressed_name != NULL) /* try with the given suffix */ | ||
| 1334 | { | ||
| 1335 | if (stat (uncompressed_name, &stat_buf) == 0) | ||
| 1336 | real_name = uncompressed_name; | ||
| 1337 | } | ||
| 1338 | else /* try all possible suffixes */ | ||
| 1339 | { | ||
| 1340 | for (compr = compressors; compr->suffix != NULL; compr++) | ||
| 1341 | { | ||
| 1342 | compressed_name = concat (file, ".", compr->suffix); | ||
| 1343 | if (stat (compressed_name, &stat_buf) != 0) | ||
| 1344 | { | ||
| 1345 | #ifdef MSDOS | ||
| 1346 | char *suf = compressed_name + strlen (file); | ||
| 1347 | size_t suflen = strlen (compr->suffix) + 1; | ||
| 1348 | for ( ; suf[1]; suf++, suflen--) | ||
| 1349 | { | ||
| 1350 | memmove (suf, suf + 1, suflen); | ||
| 1351 | if (stat (compressed_name, &stat_buf) == 0) | ||
| 1352 | { | ||
| 1353 | real_name = compressed_name; | ||
| 1354 | break; | ||
| 1355 | } | ||
| 1356 | } | ||
| 1357 | if (real_name != NULL) | ||
| 1358 | break; | ||
| 1359 | #endif | ||
| 1360 | free (compressed_name); | ||
| 1361 | compressed_name = NULL; | ||
| 1362 | } | ||
| 1363 | else | ||
| 1364 | { | ||
| 1365 | real_name = compressed_name; | ||
| 1366 | break; | ||
| 1367 | } | ||
| 1368 | } | ||
| 1369 | } | ||
| 1370 | if (real_name == NULL) | ||
| 1371 | { | ||
| 1372 | perror (file); | ||
| 1373 | goto exit; | ||
| 1374 | } | ||
| 1375 | } /* try with a different name */ | ||
| 1376 | |||
| 1377 | if (!S_ISREG (stat_buf.st_mode)) | ||
| 1378 | { | ||
| 1379 | error ("skipping %s: it is not a regular file.", real_name); | ||
| 1380 | goto exit; | ||
| 1381 | } | ||
| 1382 | if (real_name == compressed_name) | ||
| 1383 | { | ||
| 1384 | char *cmd = concat (compr->command, " ", real_name); | ||
| 1385 | inf = popen (cmd, "r"); | ||
| 1386 | free (cmd); | ||
| 1387 | } | ||
| 1388 | else | ||
| 1389 | inf = fopen (real_name, "r"); | ||
| 1161 | if (inf == NULL) | 1390 | if (inf == NULL) |
| 1162 | { | 1391 | { |
| 1163 | perror (file); | 1392 | perror (real_name); |
| 1164 | return; | 1393 | goto exit; |
| 1165 | } | 1394 | } |
| 1166 | 1395 | ||
| 1167 | find_entries (file, inf); | 1396 | find_entries (uncompressed_name, inf); |
| 1397 | |||
| 1398 | if (real_name == compressed_name) | ||
| 1399 | pclose (inf); | ||
| 1400 | else | ||
| 1401 | fclose (inf); | ||
| 1168 | 1402 | ||
| 1169 | if (!CTAGS) | 1403 | if (!CTAGS) |
| 1170 | { | 1404 | { |
| 1171 | char *filename; | 1405 | char *filename; |
| 1172 | 1406 | ||
| 1173 | if (absolutefn (file)) | 1407 | if (filename_is_absolute (uncompressed_name)) |
| 1174 | { | 1408 | { |
| 1175 | /* file is an absolute file name. Canonicalise it. */ | 1409 | /* file is an absolute file name. Canonicalise it. */ |
| 1176 | filename = absolute_filename (file, cwd); | 1410 | filename = absolute_filename (uncompressed_name, cwd); |
| 1177 | } | 1411 | } |
| 1178 | else | 1412 | else |
| 1179 | { | 1413 | { |
| 1180 | /* file is a file name relative to cwd. Make it relative | 1414 | /* file is a file name relative to cwd. Make it relative |
| 1181 | to the directory of the tags file. */ | 1415 | to the directory of the tags file. */ |
| 1182 | filename = relative_filename (file, tagfiledir); | 1416 | filename = relative_filename (uncompressed_name, tagfiledir); |
| 1183 | } | 1417 | } |
| 1184 | fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head)); | 1418 | fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head)); |
| 1185 | free (filename); | 1419 | free (filename); |
| @@ -1187,11 +1421,16 @@ process_file (file) | |||
| 1187 | free_tree (head); | 1421 | free_tree (head); |
| 1188 | head = NULL; | 1422 | head = NULL; |
| 1189 | } | 1423 | } |
| 1424 | |||
| 1425 | exit: | ||
| 1426 | if (compressed_name) free(compressed_name); | ||
| 1427 | if (uncompressed_name) free(uncompressed_name); | ||
| 1428 | return; | ||
| 1190 | } | 1429 | } |
| 1191 | 1430 | ||
| 1192 | /* | 1431 | /* |
| 1193 | * This routine sets up the boolean pseudo-functions which work | 1432 | * This routine sets up the boolean pseudo-functions which work |
| 1194 | * by setting boolean flags dependent upon the corresponding character | 1433 | * by setting boolean flags dependent upon the corresponding character. |
| 1195 | * Every char which is NOT in that string is not a white char. Therefore, | 1434 | * Every char which is NOT in that string is not a white char. Therefore, |
| 1196 | * all of the array "_wht" is set to FALSE, and then the elements | 1435 | * all of the array "_wht" is set to FALSE, and then the elements |
| 1197 | * subscripted by the chars in "white" are set to TRUE. Thus "_wht" | 1436 | * subscripted by the chars in "white" are set to TRUE. Thus "_wht" |
| @@ -1204,58 +1443,61 @@ init () | |||
| 1204 | register int i; | 1443 | register int i; |
| 1205 | 1444 | ||
| 1206 | for (i = 0; i < CHARS; i++) | 1445 | for (i = 0; i < CHARS; i++) |
| 1207 | _wht[i] = _nin[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; | 1446 | iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE; |
| 1208 | for (sp = white; *sp; sp++) _wht[*sp] = TRUE; _wht[0] = _wht['\n']; | 1447 | for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE; |
| 1209 | for (sp = nonam; *sp; sp++) _nin[*sp] = TRUE; _nin[0] = _nin['\n']; | 1448 | for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE; |
| 1210 | for (sp = endtk; *sp; sp++) _etk[*sp] = TRUE; _etk[0] = _etk['\n']; | 1449 | for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE; |
| 1211 | for (sp = midtk; *sp; sp++) _itk[*sp] = TRUE; _btk[0] = _btk['\n']; | 1450 | for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE; |
| 1212 | for (sp = begtk; *sp; sp++) _btk[*sp] = TRUE; _itk[0] = _itk['\n']; | 1451 | for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE; |
| 1452 | iswhite('\0') = iswhite('\n'); | ||
| 1453 | notinname('\0') = notinname('\n'); | ||
| 1454 | begtoken('\0') = begtoken('\n'); | ||
| 1455 | intoken('\0') = intoken('\n'); | ||
| 1456 | endtoken('\0') = endtoken('\n'); | ||
| 1213 | } | 1457 | } |
| 1214 | 1458 | ||
| 1215 | /* | 1459 | /* |
| 1216 | * This routine opens the specified file and calls the function | 1460 | * This routine opens the specified file and calls the function |
| 1217 | * which finds the function and type definitions. | 1461 | * which finds the function and type definitions. |
| 1218 | */ | 1462 | */ |
| 1463 | node *last_node = NULL; | ||
| 1464 | |||
| 1219 | void | 1465 | void |
| 1220 | find_entries (file, inf) | 1466 | find_entries (file, inf) |
| 1221 | char *file; | 1467 | char *file; |
| 1222 | FILE *inf; | 1468 | FILE *inf; |
| 1223 | { | 1469 | { |
| 1224 | char *cp; | 1470 | char *cp; |
| 1225 | Lang_function *function; | 1471 | language *lang; |
| 1226 | NODE *old_last_node; | 1472 | node *old_last_node; |
| 1227 | extern NODE *last_node; | 1473 | |
| 1228 | 1474 | /* Memory leakage here: the string pointed by curfile is | |
| 1229 | 1475 | never released, because curfile is copied into np->file | |
| 1230 | /* Memory leakage here: the memory block pointed by curfile is never | 1476 | for each node, to be used in CTAGS mode. The amount of |
| 1231 | released. The amount of memory leaked here is the sum of the | 1477 | memory leaked here is the sum of the lengths of the |
| 1232 | lengths of the input file names. */ | 1478 | file names. */ |
| 1233 | curfile = savestr (file); | 1479 | curfile = savestr (file); |
| 1234 | 1480 | ||
| 1235 | /* If user specified a language, use it. */ | 1481 | /* If user specified a language, use it. */ |
| 1236 | function = lang_func; | 1482 | lang = forced_lang; |
| 1237 | if (function != NULL) | 1483 | if (lang != NULL && lang->function != NULL) |
| 1238 | { | 1484 | { |
| 1239 | function (inf); | 1485 | curlang = lang; |
| 1240 | fclose (inf); | 1486 | lang->function (inf); |
| 1241 | return; | 1487 | return; |
| 1242 | } | 1488 | } |
| 1243 | 1489 | ||
| 1244 | cp = etags_strrchr (file, '.'); | 1490 | /* Try to guess the language given the file name. */ |
| 1245 | if (cp != NULL) | 1491 | lang = get_language_from_suffix (file); |
| 1492 | if (lang != NULL && lang->function != NULL) | ||
| 1246 | { | 1493 | { |
| 1247 | cp += 1; | 1494 | curlang = lang; |
| 1248 | function = get_language_from_suffix (cp); | 1495 | lang->function (inf); |
| 1249 | if (function != NULL) | 1496 | return; |
| 1250 | { | ||
| 1251 | function (inf); | ||
| 1252 | fclose (inf); | ||
| 1253 | return; | ||
| 1254 | } | ||
| 1255 | } | 1497 | } |
| 1256 | 1498 | ||
| 1257 | /* Look for sharp-bang as the first two characters. */ | 1499 | /* Look for sharp-bang as the first two characters. */ |
| 1258 | if (readline_internal (&lb, inf) | 1500 | if (readline_internal (&lb, inf) > 0 |
| 1259 | && lb.len >= 2 | 1501 | && lb.len >= 2 |
| 1260 | && lb.buffer[0] == '#' | 1502 | && lb.buffer[0] == '#' |
| 1261 | && lb.buffer[1] == '!') | 1503 | && lb.buffer[1] == '!') |
| @@ -1269,36 +1511,40 @@ find_entries (file, inf) | |||
| 1269 | if (lp != NULL) | 1511 | if (lp != NULL) |
| 1270 | lp += 1; | 1512 | lp += 1; |
| 1271 | else | 1513 | else |
| 1272 | for (lp = lb.buffer+2; *lp != '\0' && isspace (*lp); lp++) | 1514 | lp = skip_spaces (lb.buffer + 2); |
| 1273 | continue; | 1515 | cp = skip_non_spaces (lp); |
| 1274 | for (cp = lp; *cp != '\0' && !isspace (*cp); cp++) | ||
| 1275 | continue; | ||
| 1276 | *cp = '\0'; | 1516 | *cp = '\0'; |
| 1277 | 1517 | ||
| 1278 | if (strlen (lp) > 0) | 1518 | if (strlen (lp) > 0) |
| 1279 | { | 1519 | { |
| 1280 | function = get_language_from_interpreter (lp); | 1520 | lang = get_language_from_interpreter (lp); |
| 1281 | if (function != NULL) | 1521 | if (lang != NULL && lang->function != NULL) |
| 1282 | { | 1522 | { |
| 1283 | function (inf); | 1523 | curlang = lang; |
| 1284 | fclose (inf); | 1524 | lang->function (inf); |
| 1285 | return; | 1525 | return; |
| 1286 | } | 1526 | } |
| 1287 | } | 1527 | } |
| 1288 | } | 1528 | } |
| 1529 | /* We rewind here, even if inf may be a pipe. We fail if the | ||
| 1530 | length of the first line is longer than the pipe block size, | ||
| 1531 | which is unlikely. */ | ||
| 1289 | rewind (inf); | 1532 | rewind (inf); |
| 1290 | 1533 | ||
| 1291 | /* Try Fortran. */ | 1534 | /* Try Fortran. */ |
| 1292 | old_last_node = last_node; | 1535 | old_last_node = last_node; |
| 1536 | curlang = get_language_from_name ("fortran"); | ||
| 1293 | Fortran_functions (inf); | 1537 | Fortran_functions (inf); |
| 1294 | 1538 | ||
| 1295 | /* No Fortran entries found. Try C. */ | 1539 | /* No Fortran entries found. Try C. */ |
| 1296 | if (old_last_node == last_node) | 1540 | if (old_last_node == last_node) |
| 1297 | { | 1541 | { |
| 1542 | /* We do not tag if rewind fails. | ||
| 1543 | Only the file name will be recorded in the tags file. */ | ||
| 1298 | rewind (inf); | 1544 | rewind (inf); |
| 1545 | curlang = get_language_from_name (cplusplus ? "c++" : "c"); | ||
| 1299 | default_C_entries (inf); | 1546 | default_C_entries (inf); |
| 1300 | } | 1547 | } |
| 1301 | fclose (inf); | ||
| 1302 | return; | 1548 | return; |
| 1303 | } | 1549 | } |
| 1304 | 1550 | ||
| @@ -1312,21 +1558,21 @@ pfnote (name, is_func, linestart, linelen, lno, cno) | |||
| 1312 | int lno; /* line number */ | 1558 | int lno; /* line number */ |
| 1313 | long cno; /* character number */ | 1559 | long cno; /* character number */ |
| 1314 | { | 1560 | { |
| 1315 | register NODE *np; | 1561 | register node *np; |
| 1316 | 1562 | ||
| 1317 | if (CTAGS && name == NULL) | 1563 | if (CTAGS && name == NULL) |
| 1318 | return; | 1564 | return; |
| 1319 | 1565 | ||
| 1320 | np = xnew (1, NODE); | 1566 | np = xnew (1, node); |
| 1321 | 1567 | ||
| 1322 | /* If ctags mode, change name "main" to M<thisfilename>. */ | 1568 | /* If ctags mode, change name "main" to M<thisfilename>. */ |
| 1323 | if (CTAGS && !cxref_style && streq (name, "main")) | 1569 | if (CTAGS && !cxref_style && streq (name, "main")) |
| 1324 | { | 1570 | { |
| 1325 | register char *fp = etags_strrchr (curfile, '/'); | 1571 | register char *fp = etags_strrchr (curfile, '/'); |
| 1326 | np->name = concat ("M", fp == 0 ? curfile : fp + 1, ""); | 1572 | np->name = concat ("M", fp == NULL ? curfile : fp + 1, ""); |
| 1327 | fp = etags_strrchr (np->name, '.'); | 1573 | fp = etags_strrchr (np->name, '.'); |
| 1328 | if (fp && fp[1] != '\0' && fp[2] == '\0') | 1574 | if (fp != NULL && fp[1] != '\0' && fp[2] == '\0') |
| 1329 | fp[0] = 0; | 1575 | fp[0] = '\0'; |
| 1330 | } | 1576 | } |
| 1331 | else | 1577 | else |
| 1332 | np->name = name; | 1578 | np->name = name; |
| @@ -1354,19 +1600,23 @@ pfnote (name, is_func, linestart, linelen, lno, cno) | |||
| 1354 | add_node (np, &head); | 1600 | add_node (np, &head); |
| 1355 | } | 1601 | } |
| 1356 | 1602 | ||
| 1357 | /* Date: Wed, 22 Jan 1997 02:56:31 -0500 | 1603 | /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997] |
| 1358 | * From: Sam Kendall <kendall@cybercom.net> | 1604 | * From: Sam Kendall <kendall@mv.mv.com> |
| 1359 | * Subject: Proposal for firming up the TAGS format specification | 1605 | * Subject: Proposal for firming up the TAGS format specification |
| 1360 | * To: F.Potorti@cnuce.cnr.it | 1606 | * To: F.Potorti@cnuce.cnr.it |
| 1361 | * | 1607 | * |
| 1362 | * pfnote should emit the optimized form [unnamed tag] only if: | 1608 | * pfnote should emit the optimized form [unnamed tag] only if: |
| 1363 | * 1. name does not contain any of the characters " \t\r\n()"; | 1609 | * 1. name does not contain any of the characters " \t\r\n(),;"; |
| 1364 | * 2. linestart contains name as either a rightmost, or rightmost but | 1610 | * 2. linestart contains name as either a rightmost, or rightmost but |
| 1365 | * one character, substring; | 1611 | * one character, substring; |
| 1366 | * 3. the character, if any, immediately before name in linestart must | 1612 | * 3. the character, if any, immediately before name in linestart must |
| 1367 | * be one of the characters " \t()"; | 1613 | * be one of the characters " \t(),;"; |
| 1368 | * 4. the character, if any, immediately after name in linestart must | 1614 | * 4. the character, if any, immediately after name in linestart must |
| 1369 | * also be one of the characters " \t()". | 1615 | * also be one of the characters " \t(),;". |
| 1616 | * | ||
| 1617 | * The real implementation uses the notinname() macro, which recognises | ||
| 1618 | * characters slightly different form " \t\r\n(),;". See the variable | ||
| 1619 | * `nonam'. | ||
| 1370 | */ | 1620 | */ |
| 1371 | #define traditional_tag_style TRUE | 1621 | #define traditional_tag_style TRUE |
| 1372 | void | 1622 | void |
| @@ -1399,7 +1649,7 @@ new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) | |||
| 1399 | named = FALSE; /* use unnamed tag */ | 1649 | named = FALSE; /* use unnamed tag */ |
| 1400 | } | 1650 | } |
| 1401 | } | 1651 | } |
| 1402 | 1652 | ||
| 1403 | if (named) | 1653 | if (named) |
| 1404 | name = savenstr (name, namelen); | 1654 | name = savenstr (name, namelen); |
| 1405 | else | 1655 | else |
| @@ -1412,18 +1662,18 @@ new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) | |||
| 1412 | * recurse on left children, iterate on right children. | 1662 | * recurse on left children, iterate on right children. |
| 1413 | */ | 1663 | */ |
| 1414 | void | 1664 | void |
| 1415 | free_tree (node) | 1665 | free_tree (np) |
| 1416 | register NODE *node; | 1666 | register node *np; |
| 1417 | { | 1667 | { |
| 1418 | while (node) | 1668 | while (np) |
| 1419 | { | 1669 | { |
| 1420 | register NODE *node_right = node->right; | 1670 | register node *node_right = np->right; |
| 1421 | free_tree (node->left); | 1671 | free_tree (np->left); |
| 1422 | if (node->name != NULL) | 1672 | if (np->name != NULL) |
| 1423 | free (node->name); | 1673 | free (np->name); |
| 1424 | free (node->pat); | 1674 | free (np->pat); |
| 1425 | free ((char *) node); | 1675 | free (np); |
| 1426 | node = node_right; | 1676 | np = node_right; |
| 1427 | } | 1677 | } |
| 1428 | } | 1678 | } |
| 1429 | 1679 | ||
| @@ -1436,18 +1686,17 @@ free_tree (node) | |||
| 1436 | * add_node is the only function allowed to add nodes, so it can | 1686 | * add_node is the only function allowed to add nodes, so it can |
| 1437 | * maintain state. | 1687 | * maintain state. |
| 1438 | */ | 1688 | */ |
| 1439 | NODE *last_node = NULL; | ||
| 1440 | void | 1689 | void |
| 1441 | add_node (node, cur_node_p) | 1690 | add_node (np, cur_node_p) |
| 1442 | NODE *node, **cur_node_p; | 1691 | node *np, **cur_node_p; |
| 1443 | { | 1692 | { |
| 1444 | register int dif; | 1693 | register int dif; |
| 1445 | register NODE *cur_node = *cur_node_p; | 1694 | register node *cur_node = *cur_node_p; |
| 1446 | 1695 | ||
| 1447 | if (cur_node == NULL) | 1696 | if (cur_node == NULL) |
| 1448 | { | 1697 | { |
| 1449 | *cur_node_p = node; | 1698 | *cur_node_p = np; |
| 1450 | last_node = node; | 1699 | last_node = np; |
| 1451 | return; | 1700 | return; |
| 1452 | } | 1701 | } |
| 1453 | 1702 | ||
| @@ -1456,13 +1705,13 @@ add_node (node, cur_node_p) | |||
| 1456 | /* Etags Mode */ | 1705 | /* Etags Mode */ |
| 1457 | if (last_node == NULL) | 1706 | if (last_node == NULL) |
| 1458 | fatal ("internal error in add_node", (char *)NULL); | 1707 | fatal ("internal error in add_node", (char *)NULL); |
| 1459 | last_node->right = node; | 1708 | last_node->right = np; |
| 1460 | last_node = node; | 1709 | last_node = np; |
| 1461 | } | 1710 | } |
| 1462 | else | 1711 | else |
| 1463 | { | 1712 | { |
| 1464 | /* Ctags Mode */ | 1713 | /* Ctags Mode */ |
| 1465 | dif = strcmp (node->name, cur_node->name); | 1714 | dif = strcmp (np->name, cur_node->name); |
| 1466 | 1715 | ||
| 1467 | /* | 1716 | /* |
| 1468 | * If this tag name matches an existing one, then | 1717 | * If this tag name matches an existing one, then |
| @@ -1470,12 +1719,12 @@ add_node (node, cur_node_p) | |||
| 1470 | */ | 1719 | */ |
| 1471 | if (!dif) | 1720 | if (!dif) |
| 1472 | { | 1721 | { |
| 1473 | if (streq (node->file, cur_node->file)) | 1722 | if (streq (np->file, cur_node->file)) |
| 1474 | { | 1723 | { |
| 1475 | if (!no_warnings) | 1724 | if (!no_warnings) |
| 1476 | { | 1725 | { |
| 1477 | fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n", | 1726 | fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n", |
| 1478 | node->file, lineno, node->name); | 1727 | np->file, lineno, np->name); |
| 1479 | fprintf (stderr, "Second entry ignored\n"); | 1728 | fprintf (stderr, "Second entry ignored\n"); |
| 1480 | } | 1729 | } |
| 1481 | } | 1730 | } |
| @@ -1484,64 +1733,64 @@ add_node (node, cur_node_p) | |||
| 1484 | fprintf | 1733 | fprintf |
| 1485 | (stderr, | 1734 | (stderr, |
| 1486 | "Duplicate entry in files %s and %s: %s (Warning only)\n", | 1735 | "Duplicate entry in files %s and %s: %s (Warning only)\n", |
| 1487 | node->file, cur_node->file, node->name); | 1736 | np->file, cur_node->file, np->name); |
| 1488 | cur_node->been_warned = TRUE; | 1737 | cur_node->been_warned = TRUE; |
| 1489 | } | 1738 | } |
| 1490 | return; | 1739 | return; |
| 1491 | } | 1740 | } |
| 1492 | 1741 | ||
| 1493 | /* Actually add the node */ | 1742 | /* Actually add the node */ |
| 1494 | add_node (node, dif < 0 ? &cur_node->left : &cur_node->right); | 1743 | add_node (np, dif < 0 ? &cur_node->left : &cur_node->right); |
| 1495 | } | 1744 | } |
| 1496 | } | 1745 | } |
| 1497 | 1746 | ||
| 1498 | void | 1747 | void |
| 1499 | put_entries (node) | 1748 | put_entries (np) |
| 1500 | register NODE *node; | 1749 | register node *np; |
| 1501 | { | 1750 | { |
| 1502 | register char *sp; | 1751 | register char *sp; |
| 1503 | 1752 | ||
| 1504 | if (node == NULL) | 1753 | if (np == NULL) |
| 1505 | return; | 1754 | return; |
| 1506 | 1755 | ||
| 1507 | /* Output subentries that precede this one */ | 1756 | /* Output subentries that precede this one */ |
| 1508 | put_entries (node->left); | 1757 | put_entries (np->left); |
| 1509 | 1758 | ||
| 1510 | /* Output this entry */ | 1759 | /* Output this entry */ |
| 1511 | 1760 | ||
| 1512 | if (!CTAGS) | 1761 | if (!CTAGS) |
| 1513 | { | 1762 | { |
| 1514 | if (node->name != NULL) | 1763 | if (np->name != NULL) |
| 1515 | fprintf (tagf, "%s\177%s\001%d,%ld\n", | 1764 | fprintf (tagf, "%s\177%s\001%d,%ld\n", |
| 1516 | node->pat, node->name, node->lno, node->cno); | 1765 | np->pat, np->name, np->lno, np->cno); |
| 1517 | else | 1766 | else |
| 1518 | fprintf (tagf, "%s\177%d,%ld\n", | 1767 | fprintf (tagf, "%s\177%d,%ld\n", |
| 1519 | node->pat, node->lno, node->cno); | 1768 | np->pat, np->lno, np->cno); |
| 1520 | } | 1769 | } |
| 1521 | else | 1770 | else |
| 1522 | { | 1771 | { |
| 1523 | if (node->name == NULL) | 1772 | if (np->name == NULL) |
| 1524 | error ("internal error: NULL name in ctags mode.", (char *)NULL); | 1773 | error ("internal error: NULL name in ctags mode.", (char *)NULL); |
| 1525 | 1774 | ||
| 1526 | if (cxref_style) | 1775 | if (cxref_style) |
| 1527 | { | 1776 | { |
| 1528 | if (vgrind_style) | 1777 | if (vgrind_style) |
| 1529 | fprintf (stdout, "%s %s %d\n", | 1778 | fprintf (stdout, "%s %s %d\n", |
| 1530 | node->name, node->file, (node->lno + 63) / 64); | 1779 | np->name, np->file, (np->lno + 63) / 64); |
| 1531 | else | 1780 | else |
| 1532 | fprintf (stdout, "%-16s %3d %-16s %s\n", | 1781 | fprintf (stdout, "%-16s %3d %-16s %s\n", |
| 1533 | node->name, node->lno, node->file, node->pat); | 1782 | np->name, np->lno, np->file, np->pat); |
| 1534 | } | 1783 | } |
| 1535 | else | 1784 | else |
| 1536 | { | 1785 | { |
| 1537 | fprintf (tagf, "%s\t%s\t", node->name, node->file); | 1786 | fprintf (tagf, "%s\t%s\t", np->name, np->file); |
| 1538 | 1787 | ||
| 1539 | if (node->is_func) | 1788 | if (np->is_func) |
| 1540 | { /* a function */ | 1789 | { /* a function */ |
| 1541 | putc (searchar, tagf); | 1790 | putc (searchar, tagf); |
| 1542 | putc ('^', tagf); | 1791 | putc ('^', tagf); |
| 1543 | 1792 | ||
| 1544 | for (sp = node->pat; *sp; sp++) | 1793 | for (sp = np->pat; *sp; sp++) |
| 1545 | { | 1794 | { |
| 1546 | if (*sp == '\\' || *sp == searchar) | 1795 | if (*sp == '\\' || *sp == searchar) |
| 1547 | putc ('\\', tagf); | 1796 | putc ('\\', tagf); |
| @@ -1551,14 +1800,14 @@ put_entries (node) | |||
| 1551 | } | 1800 | } |
| 1552 | else | 1801 | else |
| 1553 | { /* a typedef; text pattern inadequate */ | 1802 | { /* a typedef; text pattern inadequate */ |
| 1554 | fprintf (tagf, "%d", node->lno); | 1803 | fprintf (tagf, "%d", np->lno); |
| 1555 | } | 1804 | } |
| 1556 | putc ('\n', tagf); | 1805 | putc ('\n', tagf); |
| 1557 | } | 1806 | } |
| 1558 | } | 1807 | } |
| 1559 | 1808 | ||
| 1560 | /* Output subentries that follow this one */ | 1809 | /* Output subentries that follow this one */ |
| 1561 | put_entries (node->right); | 1810 | put_entries (np->right); |
| 1562 | } | 1811 | } |
| 1563 | 1812 | ||
| 1564 | /* Length of a number's decimal representation. */ | 1813 | /* Length of a number's decimal representation. */ |
| @@ -1566,11 +1815,9 @@ int | |||
| 1566 | number_len (num) | 1815 | number_len (num) |
| 1567 | long num; | 1816 | long num; |
| 1568 | { | 1817 | { |
| 1569 | int len = 0; | 1818 | int len = 1; |
| 1570 | if (!num) | 1819 | while ((num /= 10) > 0) |
| 1571 | return 1; | 1820 | len += 1; |
| 1572 | for (; num; num /= 10) | ||
| 1573 | ++len; | ||
| 1574 | return len; | 1821 | return len; |
| 1575 | } | 1822 | } |
| 1576 | 1823 | ||
| @@ -1582,25 +1829,24 @@ number_len (num) | |||
| 1582 | * backward compatibility. | 1829 | * backward compatibility. |
| 1583 | */ | 1830 | */ |
| 1584 | int | 1831 | int |
| 1585 | total_size_of_entries (node) | 1832 | total_size_of_entries (np) |
| 1586 | register NODE *node; | 1833 | register node *np; |
| 1587 | { | 1834 | { |
| 1588 | register int total; | 1835 | register int total; |
| 1589 | 1836 | ||
| 1590 | if (node == NULL) | 1837 | if (np == NULL) |
| 1591 | return 0; | 1838 | return 0; |
| 1592 | 1839 | ||
| 1593 | total = 0; | 1840 | for (total = 0; np != NULL; np = np->right) |
| 1594 | for (; node; node = node->right) | ||
| 1595 | { | 1841 | { |
| 1596 | /* Count left subentries. */ | 1842 | /* Count left subentries. */ |
| 1597 | total += total_size_of_entries (node->left); | 1843 | total += total_size_of_entries (np->left); |
| 1598 | 1844 | ||
| 1599 | /* Count this entry */ | 1845 | /* Count this entry */ |
| 1600 | total += strlen (node->pat) + 1; | 1846 | total += strlen (np->pat) + 1; |
| 1601 | total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1; | 1847 | total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1; |
| 1602 | if (node->name != NULL) | 1848 | if (np->name != NULL) |
| 1603 | total += 1 + strlen (node->name); /* \001name */ | 1849 | total += 1 + strlen (np->name); /* \001name */ |
| 1604 | } | 1850 | } |
| 1605 | 1851 | ||
| 1606 | return total; | 1852 | return total; |
| @@ -1616,7 +1862,8 @@ enum sym_type | |||
| 1616 | st_C_gnumacro, | 1862 | st_C_gnumacro, |
| 1617 | st_C_ignore, | 1863 | st_C_ignore, |
| 1618 | st_C_javastruct, | 1864 | st_C_javastruct, |
| 1619 | st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec | 1865 | st_C_operator, |
| 1866 | st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec | ||
| 1620 | }; | 1867 | }; |
| 1621 | 1868 | ||
| 1622 | /* Feed stuff between (but not including) %[ and %] lines to: | 1869 | /* Feed stuff between (but not including) %[ and %] lines to: |
| @@ -1624,6 +1871,11 @@ enum sym_type | |||
| 1624 | %[ | 1871 | %[ |
| 1625 | struct C_stab_entry { char *name; int c_ext; enum sym_type type; } | 1872 | struct C_stab_entry { char *name; int c_ext; enum sym_type type; } |
| 1626 | %% | 1873 | %% |
| 1874 | if, 0, st_C_ignore | ||
| 1875 | for, 0, st_C_ignore | ||
| 1876 | while, 0, st_C_ignore | ||
| 1877 | switch, 0, st_C_ignore | ||
| 1878 | return, 0, st_C_ignore | ||
| 1627 | @interface, 0, st_C_objprot | 1879 | @interface, 0, st_C_objprot |
| 1628 | @protocol, 0, st_C_objprot | 1880 | @protocol, 0, st_C_objprot |
| 1629 | @implementation,0, st_C_objimpl | 1881 | @implementation,0, st_C_objimpl |
| @@ -1633,14 +1885,17 @@ package, C_JAVA, st_C_ignore | |||
| 1633 | friend, C_PLPL, st_C_ignore | 1885 | friend, C_PLPL, st_C_ignore |
| 1634 | extends, C_JAVA, st_C_javastruct | 1886 | extends, C_JAVA, st_C_javastruct |
| 1635 | implements, C_JAVA, st_C_javastruct | 1887 | implements, C_JAVA, st_C_javastruct |
| 1888 | interface, C_JAVA, st_C_struct | ||
| 1636 | class, C_PLPL, st_C_struct | 1889 | class, C_PLPL, st_C_struct |
| 1637 | namespace, C_PLPL, st_C_struct | 1890 | namespace, C_PLPL, st_C_struct |
| 1638 | domain, C_STAR, st_C_struct | 1891 | domain, C_STAR, st_C_struct |
| 1639 | union, 0, st_C_struct | 1892 | union, 0, st_C_struct |
| 1640 | struct, 0, st_C_struct | 1893 | struct, 0, st_C_struct |
| 1894 | extern, 0, st_C_extern | ||
| 1641 | enum, 0, st_C_enum | 1895 | enum, 0, st_C_enum |
| 1642 | typedef, 0, st_C_typedef | 1896 | typedef, 0, st_C_typedef |
| 1643 | define, 0, st_C_define | 1897 | define, 0, st_C_define |
| 1898 | operator, C_PLPL, st_C_operator | ||
| 1644 | bool, C_PLPL, st_C_typespec | 1899 | bool, C_PLPL, st_C_typespec |
| 1645 | long, 0, st_C_typespec | 1900 | long, 0, st_C_typespec |
| 1646 | short, 0, st_C_typespec | 1901 | short, 0, st_C_typespec |
| @@ -1652,7 +1907,6 @@ signed, 0, st_C_typespec | |||
| 1652 | unsigned, 0, st_C_typespec | 1907 | unsigned, 0, st_C_typespec |
| 1653 | auto, 0, st_C_typespec | 1908 | auto, 0, st_C_typespec |
| 1654 | void, 0, st_C_typespec | 1909 | void, 0, st_C_typespec |
| 1655 | extern, 0, st_C_typespec | ||
| 1656 | static, 0, st_C_typespec | 1910 | static, 0, st_C_typespec |
| 1657 | const, 0, st_C_typespec | 1911 | const, 0, st_C_typespec |
| 1658 | volatile, 0, st_C_typespec | 1912 | volatile, 0, st_C_typespec |
| @@ -1671,137 +1925,168 @@ PSEUDO, 0, st_C_gnumacro | |||
| 1671 | %] | 1925 | %] |
| 1672 | and replace lines between %< and %> with its output. */ | 1926 | and replace lines between %< and %> with its output. */ |
| 1673 | /*%<*/ | 1927 | /*%<*/ |
| 1674 | /* starting time is 10:31:16 */ | 1928 | /* C code produced by gperf version 2.7.1 (19981006 egcs) */ |
| 1675 | /* C code produced by gperf version 2.1 (K&R C version) */ | ||
| 1676 | /* Command-line: gperf -c -k 1,3 -o -p -r -t */ | 1929 | /* Command-line: gperf -c -k 1,3 -o -p -r -t */ |
| 1677 | |||
| 1678 | |||
| 1679 | struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; | 1930 | struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; |
| 1680 | 1931 | ||
| 1681 | #define MIN_WORD_LENGTH 3 | 1932 | #define TOTAL_KEYWORDS 46 |
| 1933 | #define MIN_WORD_LENGTH 2 | ||
| 1682 | #define MAX_WORD_LENGTH 15 | 1934 | #define MAX_WORD_LENGTH 15 |
| 1683 | #define MIN_HASH_VALUE 15 | 1935 | #define MIN_HASH_VALUE 13 |
| 1684 | #define MAX_HASH_VALUE 128 | 1936 | #define MAX_HASH_VALUE 123 |
| 1685 | /* | 1937 | /* maximum key range = 111, duplicates = 0 */ |
| 1686 | 39 keywords | ||
| 1687 | 114 is the maximum key range | ||
| 1688 | */ | ||
| 1689 | 1938 | ||
| 1690 | static int | 1939 | #ifdef __GNUC__ |
| 1940 | __inline | ||
| 1941 | #endif | ||
| 1942 | static unsigned int | ||
| 1691 | hash (str, len) | 1943 | hash (str, len) |
| 1692 | register char *str; | 1944 | register const char *str; |
| 1693 | register unsigned int len; | 1945 | register unsigned int len; |
| 1694 | { | 1946 | { |
| 1695 | static unsigned char hash_table[] = | 1947 | static unsigned char asso_values[] = |
| 1696 | { | 1948 | { |
| 1697 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1949 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1698 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1950 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1699 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1951 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1700 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1952 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1701 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1953 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1702 | 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1954 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1703 | 128, 128, 128, 128, 39, 128, 128, 128, 54, 48, | 1955 | 124, 124, 124, 124, 3, 124, 124, 124, 43, 6, |
| 1704 | 46, 128, 128, 128, 128, 128, 128, 128, 128, 128, | 1956 | 11, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1705 | 28, 128, 128, 40, 32, 128, 128, 128, 128, 128, | 1957 | 11, 124, 124, 58, 7, 124, 124, 124, 124, 124, |
| 1706 | 128, 128, 128, 128, 128, 128, 128, 24, 30, 47, | 1958 | 124, 124, 124, 124, 124, 124, 124, 57, 7, 42, |
| 1707 | 62, 7, 60, 27, 128, 60, 128, 128, 59, 16, | 1959 | 4, 14, 52, 0, 124, 53, 124, 124, 29, 11, |
| 1708 | 31, 23, 45, 128, 4, 14, 2, 55, 5, 128, | 1960 | 6, 35, 32, 124, 29, 34, 59, 58, 51, 24, |
| 1709 | 128, 128, 128, 128, 128, 128, 128, 128, | 1961 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1710 | }; | 1962 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1711 | return len + hash_table[str[2]] + hash_table[str[0]]; | 1963 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, |
| 1964 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1965 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1966 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1967 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1968 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1969 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1970 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1971 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1972 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1973 | 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, | ||
| 1974 | 124, 124, 124, 124, 124, 124 | ||
| 1975 | }; | ||
| 1976 | register int hval = len; | ||
| 1977 | |||
| 1978 | switch (hval) | ||
| 1979 | { | ||
| 1980 | default: | ||
| 1981 | case 3: | ||
| 1982 | hval += asso_values[(unsigned char)str[2]]; | ||
| 1983 | case 2: | ||
| 1984 | case 1: | ||
| 1985 | hval += asso_values[(unsigned char)str[0]]; | ||
| 1986 | break; | ||
| 1987 | } | ||
| 1988 | return hval; | ||
| 1712 | } | 1989 | } |
| 1713 | 1990 | ||
| 1991 | #ifdef __GNUC__ | ||
| 1992 | __inline | ||
| 1993 | #endif | ||
| 1714 | struct C_stab_entry * | 1994 | struct C_stab_entry * |
| 1715 | in_word_set (str, len) | 1995 | in_word_set (str, len) |
| 1716 | register char *str; | 1996 | register const char *str; |
| 1717 | register unsigned int len; | 1997 | register unsigned int len; |
| 1718 | { | 1998 | { |
| 1719 | 1999 | static struct C_stab_entry wordlist[] = | |
| 1720 | static struct C_stab_entry wordlist[] = | ||
| 1721 | { | 2000 | { |
| 1722 | {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, | 2001 | {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, |
| 1723 | {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, | 2002 | {""}, {""}, {""}, {""}, |
| 1724 | {"extern", 0, st_C_typespec}, | 2003 | {"@end", 0, st_C_objend}, |
| 1725 | {"extends", C_JAVA, st_C_javastruct}, | 2004 | {""}, {""}, {""}, {""}, |
| 1726 | {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, | 2005 | {"ENTRY", 0, st_C_gnumacro}, |
| 1727 | {"struct", 0, st_C_struct}, | 2006 | {"@interface", 0, st_C_objprot}, |
| 1728 | {"mutable", C_PLPL, st_C_typespec}, | 2007 | {""}, |
| 1729 | {"",}, {"",}, {"",}, {"",}, | 2008 | {"domain", C_STAR, st_C_struct}, |
| 1730 | {"auto", 0, st_C_typespec}, | 2009 | {""}, |
| 1731 | {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, | 2010 | {"PSEUDO", 0, st_C_gnumacro}, |
| 1732 | {"",}, {"",}, | 2011 | {""}, {""}, |
| 1733 | {"short", 0, st_C_typespec}, | 2012 | {"namespace", C_PLPL, st_C_struct}, |
| 1734 | {"",}, | 2013 | {""}, {""}, |
| 1735 | {"static", 0, st_C_typespec}, | 2014 | {"@implementation",0, st_C_objimpl}, |
| 1736 | {"",}, {"",}, | 2015 | {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, |
| 1737 | {"signed", 0, st_C_typespec}, | 2016 | {"long", 0, st_C_typespec}, |
| 1738 | {"",}, {"",}, {"",}, {"",}, | 2017 | {"signed", 0, st_C_typespec}, |
| 1739 | {"@protocol", 0, st_C_objprot}, | 2018 | {"@protocol", 0, st_C_objprot}, |
| 1740 | {"",}, | 2019 | {""}, {""}, {""}, {""}, |
| 1741 | {"typedef", 0, st_C_typedef}, | 2020 | {"bool", C_PLPL, st_C_typespec}, |
| 1742 | {"typename", C_PLPL, st_C_typespec}, | 2021 | {""}, {""}, {""}, {""}, {""}, {""}, |
| 1743 | {"namespace", C_PLPL, st_C_struct}, | 2022 | {"const", 0, st_C_typespec}, |
| 1744 | {"bool", C_PLPL, st_C_typespec}, | 2023 | {"explicit", C_PLPL, st_C_typespec}, |
| 1745 | {"",}, {"",}, | 2024 | {"if", 0, st_C_ignore}, |
| 1746 | {"explicit", C_PLPL, st_C_typespec}, | 2025 | {""}, |
| 1747 | {"",}, {"",}, {"",}, {"",}, | 2026 | {"operator", C_PLPL, st_C_operator}, |
| 1748 | {"int", 0, st_C_typespec}, | 2027 | {""}, |
| 1749 | {"enum", 0, st_C_enum}, | 2028 | {"DEFUN", 0, st_C_gnumacro}, |
| 1750 | {"",}, {"",}, | 2029 | {""}, {""}, |
| 1751 | {"void", 0, st_C_typespec}, | 2030 | {"define", 0, st_C_define}, |
| 1752 | {"@implementation", 0, st_C_objimpl}, | 2031 | {""}, {""}, {""}, {""}, {""}, |
| 1753 | {"",}, | 2032 | {"double", 0, st_C_typespec}, |
| 1754 | {"volatile", 0, st_C_typespec}, | 2033 | {"struct", 0, st_C_struct}, |
| 1755 | {"",}, | 2034 | {""}, {""}, {""}, {""}, |
| 1756 | {"@end", 0, st_C_objend}, | 2035 | {"short", 0, st_C_typespec}, |
| 1757 | {"char", 0, st_C_typespec}, | 2036 | {""}, |
| 1758 | {"class", C_PLPL, st_C_struct}, | 2037 | {"enum", 0, st_C_enum}, |
| 1759 | {"unsigned", 0, st_C_typespec}, | 2038 | {"mutable", C_PLPL, st_C_typespec}, |
| 1760 | {"",}, {"",}, | 2039 | {""}, |
| 1761 | {"@interface", 0, st_C_objprot}, | 2040 | {"extern", 0, st_C_extern}, |
| 1762 | {"",}, | 2041 | {"extends", C_JAVA, st_C_javastruct}, |
| 1763 | {"PSEUDO", 0, st_C_gnumacro}, | 2042 | {"package", C_JAVA, st_C_ignore}, |
| 1764 | {"const", 0, st_C_typespec}, | 2043 | {"while", 0, st_C_ignore}, |
| 1765 | {"domain", C_STAR, st_C_struct}, | 2044 | {""}, |
| 1766 | {"ENTRY", 0, st_C_gnumacro}, | 2045 | {"for", 0, st_C_ignore}, |
| 1767 | {"",}, | 2046 | {""}, {""}, {""}, |
| 1768 | {"SYSCALL", 0, st_C_gnumacro}, | 2047 | {"volatile", 0, st_C_typespec}, |
| 1769 | {"float", 0, st_C_typespec}, | 2048 | {""}, {""}, |
| 1770 | {"",}, {"",}, {"",}, {"",}, {"",}, | 2049 | {"import", C_JAVA, st_C_ignore}, |
| 1771 | {"long", 0, st_C_typespec}, | 2050 | {"float", 0, st_C_typespec}, |
| 1772 | {"",}, {"",}, {"",}, {"",}, | 2051 | {"switch", 0, st_C_ignore}, |
| 1773 | {"package", C_JAVA, st_C_ignore}, | 2052 | {"return", 0, st_C_ignore}, |
| 1774 | {"",}, {"",}, {"",}, {"",}, {"",}, | 2053 | {"implements", C_JAVA, st_C_javastruct}, |
| 1775 | {"DEFUN", 0, st_C_gnumacro}, | 2054 | {""}, |
| 1776 | {"",}, {"",}, {"",}, {"",}, {"",}, | 2055 | {"static", 0, st_C_typespec}, |
| 1777 | {"import", C_JAVA, st_C_ignore}, | 2056 | {"typedef", 0, st_C_typedef}, |
| 1778 | {"",}, {"",}, {"",}, | 2057 | {"typename", C_PLPL, st_C_typespec}, |
| 1779 | {"implements", C_JAVA, st_C_javastruct}, | 2058 | {"unsigned", 0, st_C_typespec}, |
| 1780 | {"",}, {"",}, {"",}, {"",}, | 2059 | {""}, {""}, |
| 1781 | {"union", 0, st_C_struct}, | 2060 | {"char", 0, st_C_typespec}, |
| 1782 | {"",}, {"",}, | 2061 | {"class", C_PLPL, st_C_struct}, |
| 1783 | {"double", 0, st_C_typespec}, | 2062 | {""}, {""}, {""}, |
| 1784 | {"",}, {"",}, | 2063 | {"void", 0, st_C_typespec}, |
| 1785 | {"friend", C_PLPL, st_C_ignore}, | 2064 | {""}, {""}, |
| 1786 | {"",}, | 2065 | {"friend", C_PLPL, st_C_ignore}, |
| 1787 | {"define", 0, st_C_define}, | 2066 | {""}, {""}, {""}, |
| 2067 | {"int", 0, st_C_typespec}, | ||
| 2068 | {"union", 0, st_C_struct}, | ||
| 2069 | {""}, {""}, {""}, | ||
| 2070 | {"auto", 0, st_C_typespec}, | ||
| 2071 | {"interface", C_JAVA, st_C_struct}, | ||
| 2072 | {""}, | ||
| 2073 | {"SYSCALL", 0, st_C_gnumacro} | ||
| 1788 | }; | 2074 | }; |
| 1789 | 2075 | ||
| 1790 | if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) | 2076 | if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) |
| 1791 | { | 2077 | { |
| 1792 | register int key = hash (str, len); | 2078 | register int key = hash (str, len); |
| 1793 | 2079 | ||
| 1794 | if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) | 2080 | if (key <= MAX_HASH_VALUE && key >= 0) |
| 1795 | { | 2081 | { |
| 1796 | register char *s = wordlist[key].name; | 2082 | register const char *s = wordlist[key].name; |
| 1797 | 2083 | ||
| 1798 | if (*s == *str && !strncmp (str + 1, s + 1, len - 1)) | 2084 | if (*str == *s && !strncmp (str + 1, s + 1, len - 1)) |
| 1799 | return &wordlist[key]; | 2085 | return &wordlist[key]; |
| 1800 | } | 2086 | } |
| 1801 | } | 2087 | } |
| 1802 | return 0; | 2088 | return 0; |
| 1803 | } | 2089 | } |
| 1804 | /* ending time is 10:31:16 */ | ||
| 1805 | /*%>*/ | 2090 | /*%>*/ |
| 1806 | 2091 | ||
| 1807 | enum sym_type | 2092 | enum sym_type |
| @@ -1824,6 +2109,7 @@ C_symtype (str, len, c_ext) | |||
| 1824 | enum | 2109 | enum |
| 1825 | { | 2110 | { |
| 1826 | fvnone, /* nothing seen */ | 2111 | fvnone, /* nothing seen */ |
| 2112 | foperator, /* func: operator keyword seen (cplpl) */ | ||
| 1827 | fvnameseen, /* function or variable name seen */ | 2113 | fvnameseen, /* function or variable name seen */ |
| 1828 | fstartlist, /* func: just after open parenthesis */ | 2114 | fstartlist, /* func: just after open parenthesis */ |
| 1829 | finlist, /* func: in parameter list */ | 2115 | finlist, /* func: in parameter list */ |
| @@ -1832,6 +2118,7 @@ enum | |||
| 1832 | vignore /* var-like: ignore until ';' */ | 2118 | vignore /* var-like: ignore until ';' */ |
| 1833 | } fvdef; | 2119 | } fvdef; |
| 1834 | 2120 | ||
| 2121 | bool fvextern; /* func or var: extern keyword seen; */ | ||
| 1835 | 2122 | ||
| 1836 | /* | 2123 | /* |
| 1837 | * typedefs are recognized using a simple finite automaton. | 2124 | * typedefs are recognized using a simple finite automaton. |
| @@ -1840,7 +2127,8 @@ enum | |||
| 1840 | enum | 2127 | enum |
| 1841 | { | 2128 | { |
| 1842 | tnone, /* nothing seen */ | 2129 | tnone, /* nothing seen */ |
| 1843 | ttypedseen, /* typedef keyword seen */ | 2130 | tkeyseen, /* typedef keyword seen */ |
| 2131 | ttypeseen, /* defined type seen */ | ||
| 1844 | tinbody, /* inside typedef body */ | 2132 | tinbody, /* inside typedef body */ |
| 1845 | tend, /* just before typedef tag */ | 2133 | tend, /* just before typedef tag */ |
| 1846 | tignore /* junk after typedef tag */ | 2134 | tignore /* junk after typedef tag */ |
| @@ -1919,9 +2207,9 @@ typedef struct | |||
| 1919 | int lineno; | 2207 | int lineno; |
| 1920 | long linepos; | 2208 | long linepos; |
| 1921 | char *buffer; | 2209 | char *buffer; |
| 1922 | } TOKEN; | 2210 | } token; |
| 1923 | TOKEN tok; /* latest token read */ | ||
| 1924 | 2211 | ||
| 2212 | token tok; /* latest token read */ | ||
| 1925 | 2213 | ||
| 1926 | /* | 2214 | /* |
| 1927 | * Set this to TRUE, and the next token considered is called a function. | 2215 | * Set this to TRUE, and the next token considered is called a function. |
| @@ -1948,11 +2236,6 @@ int methodlen; | |||
| 1948 | * *IS_FUNC gets TRUE iff the token is a function or #define macro | 2236 | * *IS_FUNC gets TRUE iff the token is a function or #define macro |
| 1949 | * with args. C_EXT is which language we are looking at. | 2237 | * with args. C_EXT is which language we are looking at. |
| 1950 | * | 2238 | * |
| 1951 | * In the future we will need some way to adjust where the end of | ||
| 1952 | * the token is; for instance, implementing the C++ keyword | ||
| 1953 | * `operator' properly will adjust the end of the token to be after | ||
| 1954 | * whatever follows `operator'. | ||
| 1955 | * | ||
| 1956 | * Globals | 2239 | * Globals |
| 1957 | * fvdef IN OUT | 2240 | * fvdef IN OUT |
| 1958 | * structdef IN OUT | 2241 | * structdef IN OUT |
| @@ -2018,20 +2301,20 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2018 | if (toktype == st_C_typedef) | 2301 | if (toktype == st_C_typedef) |
| 2019 | { | 2302 | { |
| 2020 | if (typedefs) | 2303 | if (typedefs) |
| 2021 | typdef = ttypedseen; | 2304 | typdef = tkeyseen; |
| 2305 | fvextern = FALSE; | ||
| 2022 | fvdef = fvnone; | 2306 | fvdef = fvnone; |
| 2023 | return FALSE; | 2307 | return FALSE; |
| 2024 | } | 2308 | } |
| 2025 | break; | 2309 | break; |
| 2026 | case ttypedseen: | 2310 | case tkeyseen: |
| 2027 | switch (toktype) | 2311 | switch (toktype) |
| 2028 | { | 2312 | { |
| 2029 | case st_none: | 2313 | case st_none: |
| 2030 | case st_C_typespec: | 2314 | case st_C_typespec: |
| 2031 | typdef = tend; | ||
| 2032 | break; | ||
| 2033 | case st_C_struct: | 2315 | case st_C_struct: |
| 2034 | case st_C_enum: | 2316 | case st_C_enum: |
| 2317 | typdef = ttypeseen; | ||
| 2035 | break; | 2318 | break; |
| 2036 | } | 2319 | } |
| 2037 | /* Do not return here, so the structdef stuff has a chance. */ | 2320 | /* Do not return here, so the structdef stuff has a chance. */ |
| @@ -2063,10 +2346,9 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2063 | if (structdef == stagseen) | 2346 | if (structdef == stagseen) |
| 2064 | structdef = scolonseen; | 2347 | structdef = scolonseen; |
| 2065 | return FALSE; | 2348 | return FALSE; |
| 2066 | break; | ||
| 2067 | case st_C_struct: | 2349 | case st_C_struct: |
| 2068 | case st_C_enum: | 2350 | case st_C_enum: |
| 2069 | if (typdef == ttypedseen | 2351 | if (typdef == tkeyseen |
| 2070 | || (typedefs_and_cplusplus && cblev == 0 && structdef == snone)) | 2352 | || (typedefs_and_cplusplus && cblev == 0 && structdef == snone)) |
| 2071 | { | 2353 | { |
| 2072 | structdef = skeyseen; | 2354 | structdef = skeyseen; |
| @@ -2087,16 +2369,14 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2087 | return TRUE; | 2369 | return TRUE; |
| 2088 | } | 2370 | } |
| 2089 | 2371 | ||
| 2090 | /* Avoid entering fvdef stuff if typdef is going on. */ | ||
| 2091 | if (typdef != tnone) | 2372 | if (typdef != tnone) |
| 2092 | { | 2373 | definedef = dnone; |
| 2093 | definedef = dnone; | ||
| 2094 | return FALSE; | ||
| 2095 | } | ||
| 2096 | 2374 | ||
| 2097 | /* Detect GNU macros. | 2375 | /* Detect GNU macros. |
| 2098 | 2376 | ||
| 2099 | DEFUN note for writers of emacs C code: | 2377 | Writers of emacs code are recommended to put the |
| 2378 | first two args of a DEFUN on the same line. | ||
| 2379 | |||
| 2100 | The DEFUN macro, used in emacs C source code, has a first arg | 2380 | The DEFUN macro, used in emacs C source code, has a first arg |
| 2101 | that is a string (the lisp function name), and a second arg that | 2381 | that is a string (the lisp function name), and a second arg that |
| 2102 | is a C function name. Since etags skips strings, the second arg | 2382 | is a C function name. Since etags skips strings, the second arg |
| @@ -2106,8 +2386,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2106 | removing the initial 'F' character and substituting '-' for '_'. | 2386 | removing the initial 'F' character and substituting '-' for '_'. |
| 2107 | Anyway, this assumes that the conventions of naming lisp | 2387 | Anyway, this assumes that the conventions of naming lisp |
| 2108 | functions will never change. Currently, this method is not | 2388 | functions will never change. Currently, this method is not |
| 2109 | implemented, so writers of emacs code are recommended to put the | 2389 | implemented. */ |
| 2110 | first two args of a DEFUN on the same line. */ | ||
| 2111 | if (definedef == dnone && toktype == st_C_gnumacro) | 2390 | if (definedef == dnone && toktype == st_C_gnumacro) |
| 2112 | { | 2391 | { |
| 2113 | next_token_is_func = TRUE; | 2392 | next_token_is_func = TRUE; |
| @@ -2196,14 +2475,28 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2196 | /* A function, variable or enum constant? */ | 2475 | /* A function, variable or enum constant? */ |
| 2197 | switch (toktype) | 2476 | switch (toktype) |
| 2198 | { | 2477 | { |
| 2478 | case st_C_extern: | ||
| 2479 | fvextern = TRUE; | ||
| 2480 | /* FALLTHRU */ | ||
| 2199 | case st_C_typespec: | 2481 | case st_C_typespec: |
| 2200 | if (fvdef != finlist && fvdef != fignore && fvdef != vignore) | 2482 | if (fvdef != finlist && fvdef != fignore && fvdef != vignore) |
| 2201 | fvdef = fvnone; /* should be useless */ | 2483 | fvdef = fvnone; /* should be useless */ |
| 2202 | return FALSE; | 2484 | return FALSE; |
| 2203 | case st_C_ignore: | 2485 | case st_C_ignore: |
| 2486 | fvextern = FALSE; | ||
| 2204 | fvdef = vignore; | 2487 | fvdef = vignore; |
| 2205 | return FALSE; | 2488 | return FALSE; |
| 2489 | case st_C_operator: | ||
| 2490 | fvdef = foperator; | ||
| 2491 | *is_func_or_var = TRUE; | ||
| 2492 | return TRUE; | ||
| 2206 | case st_none: | 2493 | case st_none: |
| 2494 | if ((c_ext & C_PLPL) && strneq (str+len-10, "::operator", 10)) | ||
| 2495 | { | ||
| 2496 | fvdef = foperator; | ||
| 2497 | *is_func_or_var = TRUE; | ||
| 2498 | return TRUE; | ||
| 2499 | } | ||
| 2207 | if (constantypedefs && structdef == sinbody && structtype == st_C_enum) | 2500 | if (constantypedefs && structdef == sinbody && structtype == st_C_enum) |
| 2208 | return TRUE; | 2501 | return TRUE; |
| 2209 | if (fvdef == fvnone) | 2502 | if (fvdef == fvnone) |
| @@ -2212,6 +2505,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2212 | *is_func_or_var = TRUE; | 2505 | *is_func_or_var = TRUE; |
| 2213 | return TRUE; | 2506 | return TRUE; |
| 2214 | } | 2507 | } |
| 2508 | break; | ||
| 2215 | } | 2509 | } |
| 2216 | 2510 | ||
| 2217 | return FALSE; | 2511 | return FALSE; |
| @@ -2221,7 +2515,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2221 | * C_entries () | 2515 | * C_entries () |
| 2222 | * This routine finds functions, variables, typedefs, | 2516 | * This routine finds functions, variables, typedefs, |
| 2223 | * #define's, enum constants and struct/union/enum definitions in | 2517 | * #define's, enum constants and struct/union/enum definitions in |
| 2224 | * #C syntax and adds them to the list. | 2518 | * C syntax and adds them to the list. |
| 2225 | */ | 2519 | */ |
| 2226 | #define current_lb_is_new (newndx == curndx) | 2520 | #define current_lb_is_new (newndx == curndx) |
| 2227 | #define switch_line_buffers() (curndx = 1 - curndx) | 2521 | #define switch_line_buffers() (curndx = 1 - curndx) |
| @@ -2233,7 +2527,7 @@ consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) | |||
| 2233 | #define othlinepos (lbs[1-curndx].linepos) | 2527 | #define othlinepos (lbs[1-curndx].linepos) |
| 2234 | #define newlinepos (lbs[newndx].linepos) | 2528 | #define newlinepos (lbs[newndx].linepos) |
| 2235 | 2529 | ||
| 2236 | #define CNL_SAVE_DEFINEDEF \ | 2530 | #define CNL_SAVE_DEFINEDEF() \ |
| 2237 | do { \ | 2531 | do { \ |
| 2238 | curlinepos = charno; \ | 2532 | curlinepos = charno; \ |
| 2239 | lineno++; \ | 2533 | lineno++; \ |
| @@ -2244,9 +2538,9 @@ do { \ | |||
| 2244 | newndx = curndx; \ | 2538 | newndx = curndx; \ |
| 2245 | } while (0) | 2539 | } while (0) |
| 2246 | 2540 | ||
| 2247 | #define CNL \ | 2541 | #define CNL() \ |
| 2248 | do { \ | 2542 | do { \ |
| 2249 | CNL_SAVE_DEFINEDEF; \ | 2543 | CNL_SAVE_DEFINEDEF(); \ |
| 2250 | if (savetok.valid) \ | 2544 | if (savetok.valid) \ |
| 2251 | { \ | 2545 | { \ |
| 2252 | tok = savetok; \ | 2546 | tok = savetok; \ |
| @@ -2300,23 +2594,25 @@ C_entries (c_ext, inf) | |||
| 2300 | int cblev; /* current curly brace level */ | 2594 | int cblev; /* current curly brace level */ |
| 2301 | int parlev; /* current parenthesis level */ | 2595 | int parlev; /* current parenthesis level */ |
| 2302 | bool incomm, inquote, inchar, quotednl, midtoken; | 2596 | bool incomm, inquote, inchar, quotednl, midtoken; |
| 2303 | bool cplpl, cjava; | 2597 | bool purec, cplpl, cjava; |
| 2304 | TOKEN savetok; /* token saved during preprocessor handling */ | 2598 | token savetok; /* token saved during preprocessor handling */ |
| 2305 | 2599 | ||
| 2306 | 2600 | ||
| 2601 | tokoff = toklen = 0; /* keep compiler quiet */ | ||
| 2307 | curndx = newndx = 0; | 2602 | curndx = newndx = 0; |
| 2308 | lineno = 0; | 2603 | lineno = 0; |
| 2309 | charno = 0; | 2604 | charno = 0; |
| 2310 | lp = curlb.buffer; | 2605 | lp = curlb.buffer; |
| 2311 | *lp = 0; | 2606 | *lp = 0; |
| 2312 | 2607 | ||
| 2313 | fvdef = fvnone; typdef = tnone; structdef = snone; | 2608 | fvdef = fvnone; fvextern = FALSE; typdef = tnone; |
| 2314 | definedef = dnone; objdef = onone; | 2609 | structdef = snone; definedef = dnone; objdef = onone; |
| 2315 | next_token_is_func = yacc_rules = FALSE; | 2610 | next_token_is_func = yacc_rules = FALSE; |
| 2316 | midtoken = inquote = inchar = incomm = quotednl = FALSE; | 2611 | midtoken = inquote = inchar = incomm = quotednl = FALSE; |
| 2317 | tok.valid = savetok.valid = FALSE; | 2612 | tok.valid = savetok.valid = FALSE; |
| 2318 | cblev = 0; | 2613 | cblev = 0; |
| 2319 | parlev = 0; | 2614 | parlev = 0; |
| 2615 | purec = !(c_ext & ~YACC); /* no extensions (apart from possibly yacc) */ | ||
| 2320 | cplpl = (c_ext & C_PLPL) == C_PLPL; | 2616 | cplpl = (c_ext & C_PLPL) == C_PLPL; |
| 2321 | cjava = (c_ext & C_JAVA) == C_JAVA; | 2617 | cjava = (c_ext & C_JAVA) == C_JAVA; |
| 2322 | if (cjava) | 2618 | if (cjava) |
| @@ -2354,7 +2650,7 @@ C_entries (c_ext, inf) | |||
| 2354 | case '\0': | 2650 | case '\0': |
| 2355 | /* Newlines inside comments do not end macro definitions in | 2651 | /* Newlines inside comments do not end macro definitions in |
| 2356 | traditional cpp. */ | 2652 | traditional cpp. */ |
| 2357 | CNL_SAVE_DEFINEDEF; | 2653 | CNL_SAVE_DEFINEDEF (); |
| 2358 | break; | 2654 | break; |
| 2359 | } | 2655 | } |
| 2360 | continue; | 2656 | continue; |
| @@ -2370,7 +2666,7 @@ C_entries (c_ext, inf) | |||
| 2370 | /* Newlines inside strings do not end macro definitions | 2666 | /* Newlines inside strings do not end macro definitions |
| 2371 | in traditional cpp, even though compilers don't | 2667 | in traditional cpp, even though compilers don't |
| 2372 | usually accept them. */ | 2668 | usually accept them. */ |
| 2373 | CNL_SAVE_DEFINEDEF; | 2669 | CNL_SAVE_DEFINEDEF (); |
| 2374 | break; | 2670 | break; |
| 2375 | } | 2671 | } |
| 2376 | continue; | 2672 | continue; |
| @@ -2381,7 +2677,7 @@ C_entries (c_ext, inf) | |||
| 2381 | { | 2677 | { |
| 2382 | case '\0': | 2678 | case '\0': |
| 2383 | /* Hmmm, something went wrong. */ | 2679 | /* Hmmm, something went wrong. */ |
| 2384 | CNL; | 2680 | CNL (); |
| 2385 | /* FALLTHRU */ | 2681 | /* FALLTHRU */ |
| 2386 | case '\'': | 2682 | case '\'': |
| 2387 | inchar = FALSE; | 2683 | inchar = FALSE; |
| @@ -2395,12 +2691,18 @@ C_entries (c_ext, inf) | |||
| 2395 | case '"': | 2691 | case '"': |
| 2396 | inquote = TRUE; | 2692 | inquote = TRUE; |
| 2397 | if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) | 2693 | if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) |
| 2398 | fvdef = fvnone; | 2694 | { |
| 2695 | fvextern = FALSE; | ||
| 2696 | fvdef = fvnone; | ||
| 2697 | } | ||
| 2399 | continue; | 2698 | continue; |
| 2400 | case '\'': | 2699 | case '\'': |
| 2401 | inchar = TRUE; | 2700 | inchar = TRUE; |
| 2402 | if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) | 2701 | if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) |
| 2403 | fvdef = fvnone; | 2702 | { |
| 2703 | fvextern = FALSE; | ||
| 2704 | fvdef = fvnone; | ||
| 2705 | } | ||
| 2404 | continue; | 2706 | continue; |
| 2405 | case '/': | 2707 | case '/': |
| 2406 | if (*lp == '*') | 2708 | if (*lp == '*') |
| @@ -2421,7 +2723,7 @@ C_entries (c_ext, inf) | |||
| 2421 | { | 2723 | { |
| 2422 | /* entering or exiting rules section in yacc file */ | 2724 | /* entering or exiting rules section in yacc file */ |
| 2423 | lp++; | 2725 | lp++; |
| 2424 | definedef = dnone; fvdef = fvnone; | 2726 | definedef = dnone; fvdef = fvnone; fvextern = FALSE; |
| 2425 | typdef = tnone; structdef = snone; | 2727 | typdef = tnone; structdef = snone; |
| 2426 | next_token_is_func = FALSE; | 2728 | next_token_is_func = FALSE; |
| 2427 | midtoken = inquote = inchar = incomm = quotednl = FALSE; | 2729 | midtoken = inquote = inchar = incomm = quotednl = FALSE; |
| @@ -2463,7 +2765,7 @@ C_entries (c_ext, inf) | |||
| 2463 | if ((definedef != dnone | 2765 | if ((definedef != dnone |
| 2464 | || (cblev == 0 && structdef != scolonseen) | 2766 | || (cblev == 0 && structdef != scolonseen) |
| 2465 | || (cblev == 1 && cplpl && structdef == sinbody) | 2767 | || (cblev == 1 && cplpl && structdef == sinbody) |
| 2466 | || (structdef == sinbody && structtype == st_C_enum)) | 2768 | || (structdef == sinbody && purec)) |
| 2467 | && typdef != tignore | 2769 | && typdef != tignore |
| 2468 | && definedef != dignorerest | 2770 | && definedef != dignorerest |
| 2469 | && fvdef != finlist) | 2771 | && fvdef != finlist) |
| @@ -2472,27 +2774,43 @@ C_entries (c_ext, inf) | |||
| 2472 | { | 2774 | { |
| 2473 | if (endtoken (c)) | 2775 | if (endtoken (c)) |
| 2474 | { | 2776 | { |
| 2475 | if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1))) | 2777 | bool funorvar = FALSE; |
| 2778 | |||
| 2779 | if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1])) | ||
| 2476 | { | 2780 | { |
| 2477 | /* | 2781 | /* |
| 2478 | * This handles :: in the middle, but not at the | 2782 | * This handles :: in the middle, but not at the |
| 2479 | * beginning of an identifier. | 2783 | * beginning of an identifier. Also, space-separated |
| 2784 | * :: is not recognised. | ||
| 2480 | */ | 2785 | */ |
| 2481 | lp += 2; | 2786 | lp += 2; |
| 2482 | toklen += 3; | 2787 | toklen += 2; |
| 2788 | c = lp[-1]; | ||
| 2789 | goto intoken; | ||
| 2483 | } | 2790 | } |
| 2484 | else | 2791 | else |
| 2485 | { | 2792 | { |
| 2486 | bool funorvar = FALSE; | ||
| 2487 | |||
| 2488 | if (yacc_rules | 2793 | if (yacc_rules |
| 2489 | || consider_token (newlb.buffer + tokoff, toklen, c, | 2794 | || consider_token (newlb.buffer + tokoff, toklen, c, |
| 2490 | c_ext, cblev, parlev, &funorvar)) | 2795 | c_ext, cblev, parlev, &funorvar)) |
| 2491 | { | 2796 | { |
| 2797 | if (fvdef == foperator) | ||
| 2798 | { | ||
| 2799 | char *oldlp = lp; | ||
| 2800 | lp = skip_spaces (lp-1); | ||
| 2801 | if (*lp != '\0') | ||
| 2802 | lp += 1; | ||
| 2803 | while (*lp != '\0' | ||
| 2804 | && !isspace (*lp) && *lp != '(') | ||
| 2805 | lp += 1; | ||
| 2806 | c = *lp++; | ||
| 2807 | toklen += lp - oldlp; | ||
| 2808 | } | ||
| 2492 | tok.named = FALSE; | 2809 | tok.named = FALSE; |
| 2493 | if (structdef == sinbody | 2810 | if (!purec |
| 2811 | && funorvar | ||
| 2494 | && definedef == dnone | 2812 | && definedef == dnone |
| 2495 | && funorvar) | 2813 | && structdef == sinbody) |
| 2496 | /* function or var defined in C++ class body */ | 2814 | /* function or var defined in C++ class body */ |
| 2497 | { | 2815 | { |
| 2498 | int len = strlen (structtag) + qlen + toklen; | 2816 | int len = strlen (structtag) + qlen + toklen; |
| @@ -2530,11 +2848,15 @@ C_entries (c_ext, inf) | |||
| 2530 | newlb.buffer + tokoff, toklen); | 2848 | newlb.buffer + tokoff, toklen); |
| 2531 | token_name.buffer[toklen] = '\0'; | 2849 | token_name.buffer[toklen] = '\0'; |
| 2532 | token_name.len = toklen; | 2850 | token_name.len = toklen; |
| 2533 | /* Name macros. */ | 2851 | /* Name macros and members. */ |
| 2534 | tok.named = (structdef == stagseen | 2852 | tok.named = (structdef == stagseen |
| 2853 | || typdef == ttypeseen | ||
| 2535 | || typdef == tend | 2854 | || typdef == tend |
| 2536 | || (funorvar | 2855 | || (funorvar |
| 2537 | && definedef == dignorerest)); | 2856 | && definedef == dignorerest) |
| 2857 | || (funorvar | ||
| 2858 | && definedef == dnone | ||
| 2859 | && structdef == sinbody)); | ||
| 2538 | } | 2860 | } |
| 2539 | tok.lineno = lineno; | 2861 | tok.lineno = lineno; |
| 2540 | tok.linelen = tokoff + toklen + 1; | 2862 | tok.linelen = tokoff + toklen + 1; |
| @@ -2544,6 +2866,7 @@ C_entries (c_ext, inf) | |||
| 2544 | 2866 | ||
| 2545 | if (definedef == dnone | 2867 | if (definedef == dnone |
| 2546 | && (fvdef == fvnameseen | 2868 | && (fvdef == fvnameseen |
| 2869 | || fvdef == foperator | ||
| 2547 | || structdef == stagseen | 2870 | || structdef == stagseen |
| 2548 | || typdef == tend | 2871 | || typdef == tend |
| 2549 | || objdef != onone)) | 2872 | || objdef != onone)) |
| @@ -2558,6 +2881,7 @@ C_entries (c_ext, inf) | |||
| 2558 | } | 2881 | } |
| 2559 | } /* if (endtoken (c)) */ | 2882 | } /* if (endtoken (c)) */ |
| 2560 | else if (intoken (c)) | 2883 | else if (intoken (c)) |
| 2884 | intoken: | ||
| 2561 | { | 2885 | { |
| 2562 | toklen++; | 2886 | toklen++; |
| 2563 | continue; | 2887 | continue; |
| @@ -2633,6 +2957,7 @@ C_entries (c_ext, inf) | |||
| 2633 | } | 2957 | } |
| 2634 | break; | 2958 | break; |
| 2635 | case fstartlist: | 2959 | case fstartlist: |
| 2960 | fvextern = FALSE; | ||
| 2636 | fvdef = fvnone; | 2961 | fvdef = fvnone; |
| 2637 | break; | 2962 | break; |
| 2638 | } | 2963 | } |
| @@ -2654,10 +2979,19 @@ C_entries (c_ext, inf) | |||
| 2654 | case fignore: | 2979 | case fignore: |
| 2655 | break; | 2980 | break; |
| 2656 | case fvnameseen: | 2981 | case fvnameseen: |
| 2657 | if ((globals && cblev == 0) || (members && cblev == 1)) | 2982 | if ((members && cblev == 1) |
| 2983 | || (globals && cblev == 0 && (!fvextern || declarations))) | ||
| 2658 | make_C_tag (FALSE); /* a variable */ | 2984 | make_C_tag (FALSE); /* a variable */ |
| 2985 | fvextern = FALSE; | ||
| 2986 | fvdef = fvnone; | ||
| 2987 | tok.valid = FALSE; | ||
| 2988 | break; | ||
| 2989 | case flistseen: | ||
| 2990 | if (declarations && (cblev == 0 || cblev == 1)) | ||
| 2991 | make_C_tag (TRUE); /* a function declaration */ | ||
| 2659 | /* FALLTHRU */ | 2992 | /* FALLTHRU */ |
| 2660 | default: | 2993 | default: |
| 2994 | fvextern = FALSE; | ||
| 2661 | fvdef = fvnone; | 2995 | fvdef = fvnone; |
| 2662 | /* The following instruction invalidates the token. | 2996 | /* The following instruction invalidates the token. |
| 2663 | Probably the token should be invalidated in all | 2997 | Probably the token should be invalidated in all |
| @@ -2680,12 +3014,14 @@ C_entries (c_ext, inf) | |||
| 2680 | } | 3014 | } |
| 2681 | switch (fvdef) | 3015 | switch (fvdef) |
| 2682 | { | 3016 | { |
| 3017 | case foperator: | ||
| 2683 | case finlist: | 3018 | case finlist: |
| 2684 | case fignore: | 3019 | case fignore: |
| 2685 | case vignore: | 3020 | case vignore: |
| 2686 | break; | 3021 | break; |
| 2687 | case fvnameseen: | 3022 | case fvnameseen: |
| 2688 | if ((globals && cblev == 0) || (members && cblev == 1)) | 3023 | if ((members && cblev == 1) |
| 3024 | || (globals && cblev == 0 && (!fvextern || declarations))) | ||
| 2689 | make_C_tag (FALSE); /* a variable */ | 3025 | make_C_tag (FALSE); /* a variable */ |
| 2690 | break; | 3026 | break; |
| 2691 | default: | 3027 | default: |
| @@ -2705,12 +3041,14 @@ C_entries (c_ext, inf) | |||
| 2705 | } | 3041 | } |
| 2706 | switch (fvdef) | 3042 | switch (fvdef) |
| 2707 | { | 3043 | { |
| 3044 | case foperator: | ||
| 2708 | case finlist: | 3045 | case finlist: |
| 2709 | case fignore: | 3046 | case fignore: |
| 2710 | case vignore: | 3047 | case vignore: |
| 2711 | break; | 3048 | break; |
| 2712 | case fvnameseen: | 3049 | case fvnameseen: |
| 2713 | if ((globals && cblev == 0) || (members && cblev == 1)) | 3050 | if ((members && cblev == 1) |
| 3051 | || (globals && cblev == 0 && (!fvextern || declarations))) | ||
| 2714 | make_C_tag (FALSE); /* a variable */ | 3052 | make_C_tag (FALSE); /* a variable */ |
| 2715 | /* FALLTHRU */ | 3053 | /* FALLTHRU */ |
| 2716 | default: | 3054 | default: |
| @@ -2726,22 +3064,19 @@ C_entries (c_ext, inf) | |||
| 2726 | objdef = oparenseen; | 3064 | objdef = oparenseen; |
| 2727 | switch (fvdef) | 3065 | switch (fvdef) |
| 2728 | { | 3066 | { |
| 2729 | case fvnone: | ||
| 2730 | switch (typdef) | ||
| 2731 | { | ||
| 2732 | case ttypedseen: | ||
| 2733 | case tend: | ||
| 2734 | if (tok.valid && *lp != '*') | ||
| 2735 | { | ||
| 2736 | /* This handles constructs like: | ||
| 2737 | typedef void OperatorFun (int fun); */ | ||
| 2738 | make_C_tag (FALSE); | ||
| 2739 | typdef = tignore; | ||
| 2740 | } | ||
| 2741 | break; | ||
| 2742 | } /* switch (typdef) */ | ||
| 2743 | break; | ||
| 2744 | case fvnameseen: | 3067 | case fvnameseen: |
| 3068 | if (typdef == ttypeseen | ||
| 3069 | && tok.valid | ||
| 3070 | && *lp != '*' | ||
| 3071 | && structdef != sinbody) | ||
| 3072 | { | ||
| 3073 | /* This handles constructs like: | ||
| 3074 | typedef void OperatorFun (int fun); */ | ||
| 3075 | make_C_tag (FALSE); | ||
| 3076 | typdef = tignore; | ||
| 3077 | } | ||
| 3078 | /* FALLTHRU */ | ||
| 3079 | case foperator: | ||
| 2745 | fvdef = fstartlist; | 3080 | fvdef = fstartlist; |
| 2746 | break; | 3081 | break; |
| 2747 | case flistseen: | 3082 | case flistseen: |
| @@ -2767,7 +3102,7 @@ C_entries (c_ext, inf) | |||
| 2767 | fvdef = flistseen; | 3102 | fvdef = flistseen; |
| 2768 | break; | 3103 | break; |
| 2769 | } | 3104 | } |
| 2770 | if (cblev == 0 && typdef == tend) | 3105 | if (cblev == 0 && (typdef == tend)) |
| 2771 | { | 3106 | { |
| 2772 | typdef = tignore; | 3107 | typdef = tignore; |
| 2773 | make_C_tag (FALSE); /* a typedef */ | 3108 | make_C_tag (FALSE); /* a typedef */ |
| @@ -2779,7 +3114,7 @@ C_entries (c_ext, inf) | |||
| 2779 | case '{': | 3114 | case '{': |
| 2780 | if (definedef != dnone) | 3115 | if (definedef != dnone) |
| 2781 | break; | 3116 | break; |
| 2782 | if (typdef == ttypedseen) | 3117 | if (typdef == ttypeseen) |
| 2783 | typdef = tinbody; | 3118 | typdef = tinbody; |
| 2784 | switch (structdef) | 3119 | switch (structdef) |
| 2785 | { | 3120 | { |
| @@ -2858,12 +3193,14 @@ C_entries (c_ext, inf) | |||
| 2858 | break; | 3193 | break; |
| 2859 | switch (fvdef) | 3194 | switch (fvdef) |
| 2860 | { | 3195 | { |
| 3196 | case foperator: | ||
| 2861 | case finlist: | 3197 | case finlist: |
| 2862 | case fignore: | 3198 | case fignore: |
| 2863 | case vignore: | 3199 | case vignore: |
| 2864 | break; | 3200 | break; |
| 2865 | case fvnameseen: | 3201 | case fvnameseen: |
| 2866 | if ((globals && cblev == 0) || (members && cblev == 1)) | 3202 | if ((members && cblev == 1) |
| 3203 | || (globals && cblev == 0 && (!fvextern || declarations))) | ||
| 2867 | make_C_tag (FALSE); /* a variable */ | 3204 | make_C_tag (FALSE); /* a variable */ |
| 2868 | /* FALLTHRU */ | 3205 | /* FALLTHRU */ |
| 2869 | default: | 3206 | default: |
| @@ -2882,9 +3219,17 @@ C_entries (c_ext, inf) | |||
| 2882 | case '^': case '!': case '<': case '>': case '.': case '?': case ']': | 3219 | case '^': case '!': case '<': case '>': case '.': case '?': case ']': |
| 2883 | if (definedef != dnone) | 3220 | if (definedef != dnone) |
| 2884 | break; | 3221 | break; |
| 2885 | /* These surely cannot follow a function tag. */ | 3222 | /* These surely cannot follow a function tag in C. */ |
| 2886 | if (fvdef != finlist && fvdef != fignore && fvdef != vignore) | 3223 | switch (fvdef) |
| 2887 | fvdef = fvnone; | 3224 | { |
| 3225 | case foperator: | ||
| 3226 | case finlist: | ||
| 3227 | case fignore: | ||
| 3228 | case vignore: | ||
| 3229 | break; | ||
| 3230 | default: | ||
| 3231 | fvdef = fvnone; | ||
| 3232 | } | ||
| 2888 | break; | 3233 | break; |
| 2889 | case '\0': | 3234 | case '\0': |
| 2890 | if (objdef == otagseen) | 3235 | if (objdef == otagseen) |
| @@ -2894,9 +3239,9 @@ C_entries (c_ext, inf) | |||
| 2894 | } | 3239 | } |
| 2895 | /* If a macro spans multiple lines don't reset its state. */ | 3240 | /* If a macro spans multiple lines don't reset its state. */ |
| 2896 | if (quotednl) | 3241 | if (quotednl) |
| 2897 | CNL_SAVE_DEFINEDEF; | 3242 | CNL_SAVE_DEFINEDEF (); |
| 2898 | else | 3243 | else |
| 2899 | CNL; | 3244 | CNL (); |
| 2900 | break; | 3245 | break; |
| 2901 | } /* switch (c) */ | 3246 | } /* switch (c) */ |
| 2902 | 3247 | ||
| @@ -2954,9 +3299,33 @@ Yacc_entries (inf) | |||
| 2954 | C_entries (YACC, inf); | 3299 | C_entries (YACC, inf); |
| 2955 | } | 3300 | } |
| 2956 | 3301 | ||
| 2957 | /* Fortran parsing */ | 3302 | /* A useful macro. */ |
| 3303 | #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \ | ||
| 3304 | for (lineno = charno = 0; /* loop initialization */ \ | ||
| 3305 | !feof (file_pointer) /* loop test */ \ | ||
| 3306 | && (lineno++, /* instructions at start of loop */ \ | ||
| 3307 | linecharno = charno, \ | ||
| 3308 | charno += readline (&line_buffer, file_pointer), \ | ||
| 3309 | char_pointer = lb.buffer, \ | ||
| 3310 | TRUE); \ | ||
| 3311 | ) | ||
| 3312 | |||
| 3313 | |||
| 3314 | /* | ||
| 3315 | * Read a file, but do no processing. This is used to do regexp | ||
| 3316 | * matching on files that have no language defined. | ||
| 3317 | */ | ||
| 3318 | void | ||
| 3319 | just_read_file (inf) | ||
| 3320 | FILE *inf; | ||
| 3321 | { | ||
| 3322 | register char *dummy; | ||
| 2958 | 3323 | ||
| 2959 | char *dbp; | 3324 | LOOP_ON_INPUT_LINES (inf, lb, dummy) |
| 3325 | continue; | ||
| 3326 | } | ||
| 3327 | |||
| 3328 | /* Fortran parsing */ | ||
| 2960 | 3329 | ||
| 2961 | bool | 3330 | bool |
| 2962 | tail (cp) | 3331 | tail (cp) |
| @@ -2964,9 +3333,9 @@ tail (cp) | |||
| 2964 | { | 3333 | { |
| 2965 | register int len = 0; | 3334 | register int len = 0; |
| 2966 | 3335 | ||
| 2967 | while (*cp && lowcase(*cp) == lowcase(dbp[len])) | 3336 | while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len])) |
| 2968 | cp++, len++; | 3337 | cp++, len++; |
| 2969 | if (*cp == '\0' && !intoken(dbp[len])) | 3338 | if (*cp == '\0' && !intoken (dbp[len])) |
| 2970 | { | 3339 | { |
| 2971 | dbp += len; | 3340 | dbp += len; |
| 2972 | return TRUE; | 3341 | return TRUE; |
| @@ -2977,13 +3346,11 @@ tail (cp) | |||
| 2977 | void | 3346 | void |
| 2978 | takeprec () | 3347 | takeprec () |
| 2979 | { | 3348 | { |
| 2980 | while (isspace (*dbp)) | 3349 | dbp = skip_spaces (dbp); |
| 2981 | dbp++; | ||
| 2982 | if (*dbp != '*') | 3350 | if (*dbp != '*') |
| 2983 | return; | 3351 | return; |
| 2984 | dbp++; | 3352 | dbp++; |
| 2985 | while (isspace (*dbp)) | 3353 | dbp = skip_spaces (dbp); |
| 2986 | dbp++; | ||
| 2987 | if (strneq (dbp, "(*)", 3)) | 3354 | if (strneq (dbp, "(*)", 3)) |
| 2988 | { | 3355 | { |
| 2989 | dbp += 3; | 3356 | dbp += 3; |
| @@ -3005,8 +3372,7 @@ getit (inf) | |||
| 3005 | { | 3372 | { |
| 3006 | register char *cp; | 3373 | register char *cp; |
| 3007 | 3374 | ||
| 3008 | while (isspace (*dbp)) | 3375 | dbp = skip_spaces (dbp); |
| 3009 | dbp++; | ||
| 3010 | if (*dbp == '\0') | 3376 | if (*dbp == '\0') |
| 3011 | { | 3377 | { |
| 3012 | lineno++; | 3378 | lineno++; |
| @@ -3016,39 +3382,26 @@ getit (inf) | |||
| 3016 | if (dbp[5] != '&') | 3382 | if (dbp[5] != '&') |
| 3017 | return; | 3383 | return; |
| 3018 | dbp += 6; | 3384 | dbp += 6; |
| 3019 | while (isspace (*dbp)) | 3385 | dbp = skip_spaces (dbp); |
| 3020 | dbp++; | ||
| 3021 | } | 3386 | } |
| 3022 | if (!isalpha (*dbp) | 3387 | if (!isalpha (*dbp) && *dbp != '_' && *dbp != '$') |
| 3023 | && *dbp != '_' | ||
| 3024 | && *dbp != '$') | ||
| 3025 | return; | 3388 | return; |
| 3026 | for (cp = dbp + 1; | 3389 | for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++) |
| 3027 | (*cp | ||
| 3028 | && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$'))); | ||
| 3029 | cp++) | ||
| 3030 | continue; | 3390 | continue; |
| 3031 | pfnote (savenstr (dbp, cp-dbp), TRUE, | 3391 | pfnote (savenstr (dbp, cp-dbp), TRUE, |
| 3032 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | 3392 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); |
| 3033 | } | 3393 | } |
| 3034 | 3394 | ||
| 3395 | |||
| 3035 | void | 3396 | void |
| 3036 | Fortran_functions (inf) | 3397 | Fortran_functions (inf) |
| 3037 | FILE *inf; | 3398 | FILE *inf; |
| 3038 | { | 3399 | { |
| 3039 | lineno = 0; | 3400 | LOOP_ON_INPUT_LINES (inf, lb, dbp) |
| 3040 | charno = 0; | ||
| 3041 | |||
| 3042 | while (!feof (inf)) | ||
| 3043 | { | 3401 | { |
| 3044 | lineno++; | ||
| 3045 | linecharno = charno; | ||
| 3046 | charno += readline (&lb, inf); | ||
| 3047 | dbp = lb.buffer; | ||
| 3048 | if (*dbp == '%') | 3402 | if (*dbp == '%') |
| 3049 | dbp++; /* Ratfor escape to fortran */ | 3403 | dbp++; /* Ratfor escape to fortran */ |
| 3050 | while (isspace (*dbp)) | 3404 | dbp = skip_spaces (dbp); |
| 3051 | dbp++; | ||
| 3052 | if (*dbp == '\0') | 3405 | if (*dbp == '\0') |
| 3053 | continue; | 3406 | continue; |
| 3054 | switch (lowcase (*dbp)) | 3407 | switch (lowcase (*dbp)) |
| @@ -3072,8 +3425,7 @@ Fortran_functions (inf) | |||
| 3072 | case 'd': | 3425 | case 'd': |
| 3073 | if (tail ("double")) | 3426 | if (tail ("double")) |
| 3074 | { | 3427 | { |
| 3075 | while (isspace (*dbp)) | 3428 | dbp = skip_spaces (dbp); |
| 3076 | dbp++; | ||
| 3077 | if (*dbp == '\0') | 3429 | if (*dbp == '\0') |
| 3078 | continue; | 3430 | continue; |
| 3079 | if (tail ("precision")) | 3431 | if (tail ("precision")) |
| @@ -3082,8 +3434,7 @@ Fortran_functions (inf) | |||
| 3082 | } | 3434 | } |
| 3083 | break; | 3435 | break; |
| 3084 | } | 3436 | } |
| 3085 | while (isspace (*dbp)) | 3437 | dbp = skip_spaces (dbp); |
| 3086 | dbp++; | ||
| 3087 | if (*dbp == '\0') | 3438 | if (*dbp == '\0') |
| 3088 | continue; | 3439 | continue; |
| 3089 | switch (lowcase (*dbp)) | 3440 | switch (lowcase (*dbp)) |
| @@ -3100,23 +3451,13 @@ Fortran_functions (inf) | |||
| 3100 | if (tail ("entry")) | 3451 | if (tail ("entry")) |
| 3101 | getit (inf); | 3452 | getit (inf); |
| 3102 | continue; | 3453 | continue; |
| 3103 | case 'p': | ||
| 3104 | if (tail ("program")) | ||
| 3105 | { | ||
| 3106 | getit (inf); | ||
| 3107 | continue; | ||
| 3108 | } | ||
| 3109 | if (tail ("procedure")) | ||
| 3110 | getit (inf); | ||
| 3111 | continue; | ||
| 3112 | case 'b': | 3454 | case 'b': |
| 3113 | if (tail ("blockdata") || tail ("block data")) | 3455 | if (tail ("blockdata") || tail ("block data")) |
| 3114 | { | 3456 | { |
| 3115 | while (isspace (*dbp)) | 3457 | dbp = skip_spaces (dbp); |
| 3116 | dbp++; | ||
| 3117 | if (*dbp == '\0') /* assume un-named */ | 3458 | if (*dbp == '\0') /* assume un-named */ |
| 3118 | pfnote (savestr ("blockdata"), TRUE, lb.buffer, | 3459 | pfnote (savestr ("blockdata"), TRUE, |
| 3119 | dbp - lb.buffer, lineno, linecharno); | 3460 | lb.buffer, dbp - lb.buffer, lineno, linecharno); |
| 3120 | else | 3461 | else |
| 3121 | getit (inf); /* look for name */ | 3462 | getit (inf); /* look for name */ |
| 3122 | } | 3463 | } |
| @@ -3126,6 +3467,171 @@ Fortran_functions (inf) | |||
| 3126 | } | 3467 | } |
| 3127 | 3468 | ||
| 3128 | /* | 3469 | /* |
| 3470 | * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be>, 1998-04-24 | ||
| 3471 | * Ada parsing | ||
| 3472 | */ | ||
| 3473 | /* Once we are positioned after an "interesting" keyword, let's get | ||
| 3474 | the real tag value necessary. */ | ||
| 3475 | void | ||
| 3476 | adagetit (inf, name_qualifier) | ||
| 3477 | FILE *inf; | ||
| 3478 | char *name_qualifier; | ||
| 3479 | { | ||
| 3480 | register char *cp; | ||
| 3481 | char *name; | ||
| 3482 | char c; | ||
| 3483 | |||
| 3484 | while (!feof (inf)) | ||
| 3485 | { | ||
| 3486 | dbp = skip_spaces (dbp); | ||
| 3487 | if (*dbp == '\0' | ||
| 3488 | || (dbp[0] == '-' && dbp[1] == '-')) | ||
| 3489 | { | ||
| 3490 | lineno++; | ||
| 3491 | linecharno = charno; | ||
| 3492 | charno += readline (&lb, inf); | ||
| 3493 | dbp = lb.buffer; | ||
| 3494 | } | ||
| 3495 | switch (*dbp) | ||
| 3496 | { | ||
| 3497 | case 'b': | ||
| 3498 | case 'B': | ||
| 3499 | if (tail ("body")) | ||
| 3500 | { | ||
| 3501 | /* Skipping body of procedure body or package body or .... | ||
| 3502 | resetting qualifier to body instead of spec. */ | ||
| 3503 | name_qualifier = "/b"; | ||
| 3504 | continue; | ||
| 3505 | } | ||
| 3506 | break; | ||
| 3507 | case 't': | ||
| 3508 | case 'T': | ||
| 3509 | /* Skipping type of task type or protected type ... */ | ||
| 3510 | if (tail ("type")) | ||
| 3511 | continue; | ||
| 3512 | break; | ||
| 3513 | } | ||
| 3514 | if (*dbp == '"') | ||
| 3515 | { | ||
| 3516 | dbp += 1; | ||
| 3517 | for (cp = dbp; *cp != '\0' && *cp != '"'; cp++) | ||
| 3518 | continue; | ||
| 3519 | } | ||
| 3520 | else | ||
| 3521 | { | ||
| 3522 | dbp = skip_spaces (dbp); | ||
| 3523 | for (cp = dbp; | ||
| 3524 | (*cp != '\0' | ||
| 3525 | && (isalpha (*cp) || isdigit (*cp) || *cp == '_' || *cp == '.')); | ||
| 3526 | cp++) | ||
| 3527 | continue; | ||
| 3528 | if (cp == dbp) | ||
| 3529 | return; | ||
| 3530 | } | ||
| 3531 | c = *cp; | ||
| 3532 | *cp = '\0'; | ||
| 3533 | name = concat (dbp, name_qualifier, ""); | ||
| 3534 | *cp = c; | ||
| 3535 | pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 3536 | if (c == '"') | ||
| 3537 | dbp = cp + 1; | ||
| 3538 | return; | ||
| 3539 | } | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | void | ||
| 3543 | Ada_funcs (inf) | ||
| 3544 | FILE *inf; | ||
| 3545 | { | ||
| 3546 | bool inquote = FALSE; | ||
| 3547 | |||
| 3548 | LOOP_ON_INPUT_LINES (inf, lb, dbp) | ||
| 3549 | { | ||
| 3550 | while (*dbp != '\0') | ||
| 3551 | { | ||
| 3552 | /* Skip a string i.e. "abcd". */ | ||
| 3553 | if (inquote || (*dbp == '"')) | ||
| 3554 | { | ||
| 3555 | dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"'); | ||
| 3556 | if (dbp != NULL) | ||
| 3557 | { | ||
| 3558 | inquote = FALSE; | ||
| 3559 | dbp += 1; | ||
| 3560 | continue; /* advance char */ | ||
| 3561 | } | ||
| 3562 | else | ||
| 3563 | { | ||
| 3564 | inquote = TRUE; | ||
| 3565 | break; /* advance line */ | ||
| 3566 | } | ||
| 3567 | } | ||
| 3568 | |||
| 3569 | /* Skip comments. */ | ||
| 3570 | if (dbp[0] == '-' && dbp[1] == '-') | ||
| 3571 | break; /* advance line */ | ||
| 3572 | |||
| 3573 | /* Skip character enclosed in single quote i.e. 'a' | ||
| 3574 | and skip single quote starting an attribute i.e. 'Image. */ | ||
| 3575 | if (*dbp == '\'') | ||
| 3576 | { | ||
| 3577 | dbp++ ; | ||
| 3578 | if (*dbp != '\0') | ||
| 3579 | dbp++; | ||
| 3580 | continue; | ||
| 3581 | } | ||
| 3582 | |||
| 3583 | /* Search for beginning of a token. */ | ||
| 3584 | if (!begtoken (*dbp)) | ||
| 3585 | { | ||
| 3586 | dbp++; | ||
| 3587 | continue; /* advance char */ | ||
| 3588 | } | ||
| 3589 | |||
| 3590 | /* We are at the beginning of a token. */ | ||
| 3591 | switch (*dbp) | ||
| 3592 | { | ||
| 3593 | case 'f': | ||
| 3594 | case 'F': | ||
| 3595 | if (!packages_only && tail ("function")) | ||
| 3596 | adagetit (inf, "/f"); | ||
| 3597 | else | ||
| 3598 | break; /* from switch */ | ||
| 3599 | continue; /* advance char */ | ||
| 3600 | case 'p': | ||
| 3601 | case 'P': | ||
| 3602 | if (!packages_only && tail ("procedure")) | ||
| 3603 | adagetit (inf, "/p"); | ||
| 3604 | else if (tail ("package")) | ||
| 3605 | adagetit (inf, "/s"); | ||
| 3606 | else if (tail ("protected")) /* protected type */ | ||
| 3607 | adagetit (inf, "/t"); | ||
| 3608 | else | ||
| 3609 | break; /* from switch */ | ||
| 3610 | continue; /* advance char */ | ||
| 3611 | case 't': | ||
| 3612 | case 'T': | ||
| 3613 | if (!packages_only && tail ("task")) | ||
| 3614 | adagetit (inf, "/k"); | ||
| 3615 | else if (typedefs && !packages_only && tail ("type")) | ||
| 3616 | { | ||
| 3617 | adagetit (inf, "/t"); | ||
| 3618 | while (*dbp != '\0') | ||
| 3619 | dbp += 1; | ||
| 3620 | } | ||
| 3621 | else | ||
| 3622 | break; /* from switch */ | ||
| 3623 | continue; /* advance char */ | ||
| 3624 | } | ||
| 3625 | |||
| 3626 | /* Look for the end of the token. */ | ||
| 3627 | while (!endtoken (*dbp)) | ||
| 3628 | dbp++; | ||
| 3629 | |||
| 3630 | } /* advance char */ | ||
| 3631 | } /* advance line */ | ||
| 3632 | } | ||
| 3633 | |||
| 3634 | /* | ||
| 3129 | * Bob Weiner, Motorola Inc., 4/3/94 | 3635 | * Bob Weiner, Motorola Inc., 4/3/94 |
| 3130 | * Unix and microcontroller assembly tag handling | 3636 | * Unix and microcontroller assembly tag handling |
| 3131 | * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]' | 3637 | * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]' |
| @@ -3136,16 +3642,8 @@ Asm_labels (inf) | |||
| 3136 | { | 3642 | { |
| 3137 | register char *cp; | 3643 | register char *cp; |
| 3138 | 3644 | ||
| 3139 | lineno = 0; | 3645 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 3140 | charno = 0; | ||
| 3141 | |||
| 3142 | while (!feof (inf)) | ||
| 3143 | { | 3646 | { |
| 3144 | lineno++; | ||
| 3145 | linecharno = charno; | ||
| 3146 | charno += readline (&lb, inf); | ||
| 3147 | cp = lb.buffer; | ||
| 3148 | |||
| 3149 | /* If first char is alphabetic or one of [_.$], test for colon | 3647 | /* If first char is alphabetic or one of [_.$], test for colon |
| 3150 | following identifier. */ | 3648 | following identifier. */ |
| 3151 | if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$') | 3649 | if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$') |
| @@ -3166,7 +3664,9 @@ Asm_labels (inf) | |||
| 3166 | 3664 | ||
| 3167 | /* | 3665 | /* |
| 3168 | * Perl support by Bart Robinson <lomew@cs.utah.edu> | 3666 | * Perl support by Bart Robinson <lomew@cs.utah.edu> |
| 3667 | * enhanced by Michael Ernst <mernst@alum.mit.edu> | ||
| 3169 | * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/ | 3668 | * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/ |
| 3669 | * Perl variable names: /^(my|local).../ | ||
| 3170 | */ | 3670 | */ |
| 3171 | void | 3671 | void |
| 3172 | Perl_functions (inf) | 3672 | Perl_functions (inf) |
| @@ -3174,23 +3674,96 @@ Perl_functions (inf) | |||
| 3174 | { | 3674 | { |
| 3175 | register char *cp; | 3675 | register char *cp; |
| 3176 | 3676 | ||
| 3177 | lineno = 0; | 3677 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 3178 | charno = 0; | ||
| 3179 | |||
| 3180 | while (!feof (inf)) | ||
| 3181 | { | 3678 | { |
| 3182 | lineno++; | 3679 | if (*cp++ == 's' |
| 3183 | linecharno = charno; | 3680 | && *cp++ == 'u' |
| 3184 | charno += readline (&lb, inf); | 3681 | && *cp++ == 'b' && isspace (*cp++)) |
| 3185 | cp = lb.buffer; | 3682 | { |
| 3683 | cp = skip_spaces (cp); | ||
| 3684 | if (*cp != '\0') | ||
| 3685 | { | ||
| 3686 | char *sp = cp; | ||
| 3687 | while (*cp != '\0' | ||
| 3688 | && !isspace (*cp) && *cp != '{' && *cp != '(') | ||
| 3689 | cp++; | ||
| 3690 | pfnote (savenstr (sp, cp-sp), TRUE, | ||
| 3691 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 3692 | } | ||
| 3693 | } | ||
| 3694 | else if (globals /* only if tagging global vars is enabled */ | ||
| 3695 | && ((cp = lb.buffer, | ||
| 3696 | *cp++ == 'm' | ||
| 3697 | && *cp++ == 'y') | ||
| 3698 | || (cp = lb.buffer, | ||
| 3699 | *cp++ == 'l' | ||
| 3700 | && *cp++ == 'o' | ||
| 3701 | && *cp++ == 'c' | ||
| 3702 | && *cp++ == 'a' | ||
| 3703 | && *cp++ == 'l')) | ||
| 3704 | && (*cp == '(' || isspace (*cp))) | ||
| 3705 | { | ||
| 3706 | /* After "my" or "local", but before any following paren or space. */ | ||
| 3707 | char *varname = NULL; | ||
| 3708 | |||
| 3709 | cp = skip_spaces (cp); | ||
| 3710 | if (*cp == '$' || *cp == '@' || *cp == '%') | ||
| 3711 | { | ||
| 3712 | char* varstart = ++cp; | ||
| 3713 | while (isalnum (*cp) || *cp == '_') | ||
| 3714 | cp++; | ||
| 3715 | varname = savenstr (varstart, cp-varstart); | ||
| 3716 | } | ||
| 3717 | else | ||
| 3718 | { | ||
| 3719 | /* Should be examining a variable list at this point; | ||
| 3720 | could insist on seeing an open parenthesis. */ | ||
| 3721 | while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')') | ||
| 3722 | cp++; | ||
| 3723 | } | ||
| 3724 | |||
| 3725 | /* Perhaps I should back cp up one character, so the TAGS table | ||
| 3726 | doesn't mention (and so depend upon) the following char. */ | ||
| 3727 | pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname, | ||
| 3728 | FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 3729 | } | ||
| 3730 | } | ||
| 3731 | } | ||
| 3732 | |||
| 3733 | /* | ||
| 3734 | * Python support by Eric S. Raymond <esr@thyrsus.com> | ||
| 3735 | * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/ | ||
| 3736 | */ | ||
| 3737 | void | ||
| 3738 | Python_functions (inf) | ||
| 3739 | FILE *inf; | ||
| 3740 | { | ||
| 3741 | register char *cp; | ||
| 3186 | 3742 | ||
| 3187 | if (*cp++ == 's' && *cp++ == 'u' && *cp++ == 'b' && isspace (*cp++)) | 3743 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 3744 | { | ||
| 3745 | if (*cp++ == 'd' | ||
| 3746 | && *cp++ == 'e' | ||
| 3747 | && *cp++ == 'f' && isspace (*cp++)) | ||
| 3188 | { | 3748 | { |
| 3189 | while (*cp && isspace (*cp)) | 3749 | cp = skip_spaces (cp); |
| 3750 | while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':') | ||
| 3190 | cp++; | 3751 | cp++; |
| 3191 | while (*cp && ! isspace (*cp) && *cp != '{') | 3752 | pfnote (NULL, TRUE, |
| 3753 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 3754 | } | ||
| 3755 | |||
| 3756 | cp = lb.buffer; | ||
| 3757 | if (*cp++ == 'c' | ||
| 3758 | && *cp++ == 'l' | ||
| 3759 | && *cp++ == 'a' | ||
| 3760 | && *cp++ == 's' | ||
| 3761 | && *cp++ == 's' && isspace (*cp++)) | ||
| 3762 | { | ||
| 3763 | cp = skip_spaces (cp); | ||
| 3764 | while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':') | ||
| 3192 | cp++; | 3765 | cp++; |
| 3193 | pfnote (savenstr (lb.buffer, cp-lb.buffer), TRUE, | 3766 | pfnote (NULL, TRUE, |
| 3194 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | 3767 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); |
| 3195 | } | 3768 | } |
| 3196 | } | 3769 | } |
| @@ -3205,30 +3778,23 @@ void | |||
| 3205 | Cobol_paragraphs (inf) | 3778 | Cobol_paragraphs (inf) |
| 3206 | FILE *inf; | 3779 | FILE *inf; |
| 3207 | { | 3780 | { |
| 3208 | register char *cp; | 3781 | register char *bp, *ep; |
| 3209 | |||
| 3210 | lineno = 0; | ||
| 3211 | charno = 0; | ||
| 3212 | 3782 | ||
| 3213 | while (!feof (inf)) | 3783 | LOOP_ON_INPUT_LINES (inf, lb, bp) |
| 3214 | { | 3784 | { |
| 3215 | lineno++; | ||
| 3216 | linecharno = charno; | ||
| 3217 | charno += readline (&lb, inf); | ||
| 3218 | |||
| 3219 | if (lb.len < 9) | 3785 | if (lb.len < 9) |
| 3220 | continue; | 3786 | continue; |
| 3221 | dbp = lb.buffer + 8; | 3787 | bp += 8; |
| 3222 | 3788 | ||
| 3223 | /* If eoln, compiler option or comment ignore whole line. */ | 3789 | /* If eoln, compiler option or comment ignore whole line. */ |
| 3224 | if (dbp[-1] != ' ' || !isalnum (dbp[0])) | 3790 | if (bp[-1] != ' ' || !isalnum (bp[0])) |
| 3225 | continue; | 3791 | continue; |
| 3226 | 3792 | ||
| 3227 | for (cp = dbp; isalnum (*cp) || *cp == '-'; cp++) | 3793 | for (ep = bp; isalnum (*ep) || *ep == '-'; ep++) |
| 3228 | continue; | 3794 | continue; |
| 3229 | if (*cp++ == '.') | 3795 | if (*ep++ == '.') |
| 3230 | pfnote (savenstr (dbp, cp-dbp), TRUE, | 3796 | pfnote (savenstr (bp, ep-bp), TRUE, |
| 3231 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | 3797 | lb.buffer, ep - lb.buffer + 1, lineno, linecharno); |
| 3232 | } | 3798 | } |
| 3233 | } | 3799 | } |
| 3234 | 3800 | ||
| @@ -3245,7 +3811,7 @@ void | |||
| 3245 | Pascal_functions (inf) | 3811 | Pascal_functions (inf) |
| 3246 | FILE *inf; | 3812 | FILE *inf; |
| 3247 | { | 3813 | { |
| 3248 | struct linebuffer tline; /* mostly copied from C_entries */ | 3814 | linebuffer tline; /* mostly copied from C_entries */ |
| 3249 | long save_lcno; | 3815 | long save_lcno; |
| 3250 | int save_lineno, save_len; | 3816 | int save_lineno, save_len; |
| 3251 | char c, *cp, *namebuf; | 3817 | char c, *cp, *namebuf; |
| @@ -3262,11 +3828,12 @@ Pascal_functions (inf) | |||
| 3262 | is a FORWARD/EXTERN to be ignored, or | 3828 | is a FORWARD/EXTERN to be ignored, or |
| 3263 | whether it is a real tag */ | 3829 | whether it is a real tag */ |
| 3264 | 3830 | ||
| 3831 | save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */ | ||
| 3832 | namebuf = NULL; /* keep compiler quiet */ | ||
| 3265 | lineno = 0; | 3833 | lineno = 0; |
| 3266 | charno = 0; | 3834 | charno = 0; |
| 3267 | dbp = lb.buffer; | 3835 | dbp = lb.buffer; |
| 3268 | *dbp = '\0'; | 3836 | *dbp = '\0'; |
| 3269 | save_len = 0; | ||
| 3270 | initbuffer (&tline); | 3837 | initbuffer (&tline); |
| 3271 | 3838 | ||
| 3272 | incomment = inquote = FALSE; | 3839 | incomment = inquote = FALSE; |
| @@ -3275,8 +3842,8 @@ Pascal_functions (inf) | |||
| 3275 | inparms = FALSE; /* found '(' after "proc" */ | 3842 | inparms = FALSE; /* found '(' after "proc" */ |
| 3276 | verify_tag = FALSE; /* check if "extern" is ahead */ | 3843 | verify_tag = FALSE; /* check if "extern" is ahead */ |
| 3277 | 3844 | ||
| 3278 | /* long main loop to get next char */ | 3845 | |
| 3279 | while (!feof (inf)) | 3846 | while (!feof (inf)) /* long main loop to get next char */ |
| 3280 | { | 3847 | { |
| 3281 | c = *dbp++; | 3848 | c = *dbp++; |
| 3282 | if (c == '\0') /* if end of line */ | 3849 | if (c == '\0') /* if end of line */ |
| @@ -3287,8 +3854,8 @@ Pascal_functions (inf) | |||
| 3287 | dbp = lb.buffer; | 3854 | dbp = lb.buffer; |
| 3288 | if (*dbp == '\0') | 3855 | if (*dbp == '\0') |
| 3289 | continue; | 3856 | continue; |
| 3290 | if (!((found_tag && verify_tag) || | 3857 | if (!((found_tag && verify_tag) |
| 3291 | get_tagname)) | 3858 | || get_tagname)) |
| 3292 | c = *dbp++; /* only if don't need *dbp pointing | 3859 | c = *dbp++; /* only if don't need *dbp pointing |
| 3293 | to the beginning of the name of | 3860 | to the beginning of the name of |
| 3294 | the procedure or function */ | 3861 | the procedure or function */ |
| @@ -3430,12 +3997,12 @@ int | |||
| 3430 | L_isquote (strp) | 3997 | L_isquote (strp) |
| 3431 | register char *strp; | 3998 | register char *strp; |
| 3432 | { | 3999 | { |
| 3433 | return ((*(++strp) == 'q' || *strp == 'Q') | 4000 | return ((*++strp == 'q' || *strp == 'Q') |
| 3434 | && (*(++strp) == 'u' || *strp == 'U') | 4001 | && (*++strp == 'u' || *strp == 'U') |
| 3435 | && (*(++strp) == 'o' || *strp == 'O') | 4002 | && (*++strp == 'o' || *strp == 'O') |
| 3436 | && (*(++strp) == 't' || *strp == 'T') | 4003 | && (*++strp == 't' || *strp == 'T') |
| 3437 | && (*(++strp) == 'e' || *strp == 'E') | 4004 | && (*++strp == 'e' || *strp == 'E') |
| 3438 | && isspace (*(++strp))); | 4005 | && isspace (*++strp)); |
| 3439 | } | 4006 | } |
| 3440 | 4007 | ||
| 3441 | void | 4008 | void |
| @@ -3445,14 +4012,17 @@ L_getit () | |||
| 3445 | 4012 | ||
| 3446 | if (*dbp == '\'') /* Skip prefix quote */ | 4013 | if (*dbp == '\'') /* Skip prefix quote */ |
| 3447 | dbp++; | 4014 | dbp++; |
| 3448 | else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */ | 4015 | else if (*dbp == '(') |
| 3449 | { | 4016 | { |
| 3450 | dbp += 7; | 4017 | if (L_isquote (dbp)) |
| 3451 | while (isspace (*dbp)) | 4018 | dbp += 7; /* Skip "(quote " */ |
| 3452 | dbp++; | 4019 | else |
| 4020 | dbp += 1; /* Skip "(" before name in (defstruct (foo)) */ | ||
| 4021 | dbp = skip_spaces (dbp); | ||
| 3453 | } | 4022 | } |
| 4023 | |||
| 3454 | for (cp = dbp /*+1*/; | 4024 | for (cp = dbp /*+1*/; |
| 3455 | *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')'; | 4025 | *cp != '\0' && *cp != '(' && !isspace(*cp) && *cp != ')'; |
| 3456 | cp++) | 4026 | cp++) |
| 3457 | continue; | 4027 | continue; |
| 3458 | if (cp == dbp) | 4028 | if (cp == dbp) |
| @@ -3466,23 +4036,14 @@ void | |||
| 3466 | Lisp_functions (inf) | 4036 | Lisp_functions (inf) |
| 3467 | FILE *inf; | 4037 | FILE *inf; |
| 3468 | { | 4038 | { |
| 3469 | lineno = 0; | 4039 | LOOP_ON_INPUT_LINES (inf, lb, dbp) |
| 3470 | charno = 0; | ||
| 3471 | |||
| 3472 | while (!feof (inf)) | ||
| 3473 | { | 4040 | { |
| 3474 | lineno++; | ||
| 3475 | linecharno = charno; | ||
| 3476 | charno += readline (&lb, inf); | ||
| 3477 | dbp = lb.buffer; | ||
| 3478 | if (dbp[0] == '(') | 4041 | if (dbp[0] == '(') |
| 3479 | { | 4042 | { |
| 3480 | if (L_isdef (dbp)) | 4043 | if (L_isdef (dbp)) |
| 3481 | { | 4044 | { |
| 3482 | while (!isspace (*dbp)) | 4045 | dbp = skip_non_spaces (dbp); |
| 3483 | dbp++; | 4046 | dbp = skip_spaces (dbp); |
| 3484 | while (isspace (*dbp)) | ||
| 3485 | dbp++; | ||
| 3486 | L_getit (); | 4047 | L_getit (); |
| 3487 | } | 4048 | } |
| 3488 | else | 4049 | else |
| @@ -3490,7 +4051,7 @@ Lisp_functions (inf) | |||
| 3490 | /* Check for (foo::defmumble name-defined ... */ | 4051 | /* Check for (foo::defmumble name-defined ... */ |
| 3491 | do | 4052 | do |
| 3492 | dbp++; | 4053 | dbp++; |
| 3493 | while (*dbp && !isspace (*dbp) | 4054 | while (*dbp != '\0' && !isspace (*dbp) |
| 3494 | && *dbp != ':' && *dbp != '(' && *dbp != ')'); | 4055 | && *dbp != ':' && *dbp != '(' && *dbp != ')'); |
| 3495 | if (*dbp == ':') | 4056 | if (*dbp == ':') |
| 3496 | { | 4057 | { |
| @@ -3500,10 +4061,8 @@ Lisp_functions (inf) | |||
| 3500 | 4061 | ||
| 3501 | if (L_isdef (dbp - 1)) | 4062 | if (L_isdef (dbp - 1)) |
| 3502 | { | 4063 | { |
| 3503 | while (!isspace (*dbp)) | 4064 | dbp = skip_non_spaces (dbp); |
| 3504 | dbp++; | 4065 | dbp = skip_spaces (dbp); |
| 3505 | while (isspace (*dbp)) | ||
| 3506 | dbp++; | ||
| 3507 | L_getit (); | 4066 | L_getit (); |
| 3508 | } | 4067 | } |
| 3509 | } | 4068 | } |
| @@ -3516,29 +4075,31 @@ Lisp_functions (inf) | |||
| 3516 | * Postscript tag functions | 4075 | * Postscript tag functions |
| 3517 | * Just look for lines where the first character is '/' | 4076 | * Just look for lines where the first character is '/' |
| 3518 | * Richard Mlynarik <mly@adoc.xerox.com> | 4077 | * Richard Mlynarik <mly@adoc.xerox.com> |
| 4078 | * Also look at "defineps" for PSWrap | ||
| 4079 | * suggested by Masatake YAMATO <masata-y@is.aist-nara.ac.jp> | ||
| 3519 | */ | 4080 | */ |
| 3520 | void | 4081 | void |
| 3521 | Postscript_functions (inf) | 4082 | Postscript_functions (inf) |
| 3522 | FILE *inf; | 4083 | FILE *inf; |
| 3523 | { | 4084 | { |
| 3524 | lineno = 0; | 4085 | register char *bp, *ep; |
| 3525 | charno = 0; | ||
| 3526 | 4086 | ||
| 3527 | while (!feof (inf)) | 4087 | LOOP_ON_INPUT_LINES (inf, lb, bp) |
| 3528 | { | 4088 | { |
| 3529 | lineno++; | 4089 | if (bp[0] == '/') |
| 3530 | linecharno = charno; | ||
| 3531 | charno += readline (&lb, inf); | ||
| 3532 | dbp = lb.buffer; | ||
| 3533 | if (dbp[0] == '/') | ||
| 3534 | { | 4090 | { |
| 3535 | register char *cp; | 4091 | for (ep = bp+1; |
| 3536 | for (cp = dbp+1; | 4092 | *ep != '\0' && *ep != ' ' && *ep != '{'; |
| 3537 | *cp != '\0' && *cp != ' ' && *cp != '{'; | 4093 | ep++) |
| 3538 | cp++) | ||
| 3539 | continue; | 4094 | continue; |
| 3540 | pfnote (savenstr (dbp, cp-dbp), TRUE, | 4095 | pfnote (savenstr (bp, ep-bp), TRUE, |
| 3541 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | 4096 | lb.buffer, ep - lb.buffer + 1, lineno, linecharno); |
| 4097 | } | ||
| 4098 | else if (strneq (bp, "defineps", 8)) | ||
| 4099 | { | ||
| 4100 | bp = skip_non_spaces (bp); | ||
| 4101 | bp = skip_spaces (bp); | ||
| 4102 | get_tag (bp); | ||
| 3542 | } | 4103 | } |
| 3543 | } | 4104 | } |
| 3544 | } | 4105 | } |
| @@ -3558,59 +4119,34 @@ void | |||
| 3558 | Scheme_functions (inf) | 4119 | Scheme_functions (inf) |
| 3559 | FILE *inf; | 4120 | FILE *inf; |
| 3560 | { | 4121 | { |
| 3561 | lineno = 0; | 4122 | register char *bp; |
| 3562 | charno = 0; | ||
| 3563 | 4123 | ||
| 3564 | while (!feof (inf)) | 4124 | LOOP_ON_INPUT_LINES (inf, lb, bp) |
| 3565 | { | 4125 | { |
| 3566 | lineno++; | 4126 | if (bp[0] == '(' |
| 3567 | linecharno = charno; | 4127 | && (bp[1] == 'D' || bp[1] == 'd') |
| 3568 | charno += readline (&lb, inf); | 4128 | && (bp[2] == 'E' || bp[2] == 'e') |
| 3569 | dbp = lb.buffer; | 4129 | && (bp[3] == 'F' || bp[3] == 'f')) |
| 3570 | if (dbp[0] == '(' && | ||
| 3571 | (dbp[1] == 'D' || dbp[1] == 'd') && | ||
| 3572 | (dbp[2] == 'E' || dbp[2] == 'e') && | ||
| 3573 | (dbp[3] == 'F' || dbp[3] == 'f')) | ||
| 3574 | { | 4130 | { |
| 3575 | while (!isspace (*dbp)) | 4131 | bp = skip_non_spaces (bp); |
| 3576 | dbp++; | ||
| 3577 | /* Skip over open parens and white space */ | 4132 | /* Skip over open parens and white space */ |
| 3578 | while (*dbp && (isspace (*dbp) || *dbp == '(')) | 4133 | while (isspace (*bp) || *bp == '(') |
| 3579 | dbp++; | 4134 | bp++; |
| 3580 | get_scheme (); | 4135 | get_tag (bp); |
| 3581 | } | 4136 | } |
| 3582 | if (dbp[0] == '(' && | 4137 | if (bp[0] == '(' |
| 3583 | (dbp[1] == 'S' || dbp[1] == 's') && | 4138 | && (bp[1] == 'S' || bp[1] == 's') |
| 3584 | (dbp[2] == 'E' || dbp[2] == 'e') && | 4139 | && (bp[2] == 'E' || bp[2] == 'e') |
| 3585 | (dbp[3] == 'T' || dbp[3] == 't') && | 4140 | && (bp[3] == 'T' || bp[3] == 't') |
| 3586 | (dbp[4] == '!' || dbp[4] == '!') && | 4141 | && (bp[4] == '!' || bp[4] == '!') |
| 3587 | (isspace (dbp[5]))) | 4142 | && (isspace (bp[5]))) |
| 3588 | { | 4143 | { |
| 3589 | while (!isspace (*dbp)) | 4144 | bp = skip_non_spaces (bp); |
| 3590 | dbp++; | 4145 | bp = skip_spaces (bp); |
| 3591 | /* Skip over white space */ | 4146 | get_tag (bp); |
| 3592 | while (isspace (*dbp)) | ||
| 3593 | dbp++; | ||
| 3594 | get_scheme (); | ||
| 3595 | } | 4147 | } |
| 3596 | } | 4148 | } |
| 3597 | } | 4149 | } |
| 3598 | |||
| 3599 | void | ||
| 3600 | get_scheme () | ||
| 3601 | { | ||
| 3602 | register char *cp; | ||
| 3603 | |||
| 3604 | if (*dbp == '\0') | ||
| 3605 | return; | ||
| 3606 | /* Go till you get to white space or a syntactic break */ | ||
| 3607 | for (cp = dbp + 1; | ||
| 3608 | *cp && *cp != '(' && *cp != ')' && !isspace (*cp); | ||
| 3609 | cp++) | ||
| 3610 | continue; | ||
| 3611 | pfnote (savenstr (dbp, cp-dbp), TRUE, | ||
| 3612 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 3613 | } | ||
| 3614 | 4150 | ||
| 3615 | /* Find tags in TeX and LaTeX input files. */ | 4151 | /* Find tags in TeX and LaTeX input files. */ |
| 3616 | 4152 | ||
| @@ -3647,12 +4183,9 @@ void | |||
| 3647 | TeX_functions (inf) | 4183 | TeX_functions (inf) |
| 3648 | FILE *inf; | 4184 | FILE *inf; |
| 3649 | { | 4185 | { |
| 3650 | char *lasthit; | 4186 | char *cp, *lasthit; |
| 3651 | register int i; | 4187 | register int i; |
| 3652 | 4188 | ||
| 3653 | lineno = 0; | ||
| 3654 | charno = 0; | ||
| 3655 | |||
| 3656 | /* Select either \ or ! as escape character. */ | 4189 | /* Select either \ or ! as escape character. */ |
| 3657 | TEX_mode (inf); | 4190 | TEX_mode (inf); |
| 3658 | 4191 | ||
| @@ -3660,19 +4193,16 @@ TeX_functions (inf) | |||
| 3660 | if (!TEX_toktab) | 4193 | if (!TEX_toktab) |
| 3661 | TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv); | 4194 | TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv); |
| 3662 | 4195 | ||
| 3663 | while (!feof (inf)) | 4196 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 3664 | { /* Scan each line in file */ | 4197 | { |
| 3665 | lineno++; | 4198 | lasthit = cp; |
| 3666 | linecharno = charno; | 4199 | /* Look at each esc in line. */ |
| 3667 | charno += readline (&lb, inf); | 4200 | while ((cp = etags_strchr (cp, TEX_esc)) != NULL) |
| 3668 | dbp = lb.buffer; | ||
| 3669 | lasthit = dbp; | ||
| 3670 | while (dbp = etags_strchr (dbp, TEX_esc)) /* Look at each esc in line */ | ||
| 3671 | { | 4201 | { |
| 3672 | if (!*(++dbp)) | 4202 | if (*++cp == '\0') |
| 3673 | break; | 4203 | break; |
| 3674 | linecharno += dbp - lasthit; | 4204 | linecharno += cp - lasthit; |
| 3675 | lasthit = dbp; | 4205 | lasthit = cp; |
| 3676 | i = TEX_Token (lasthit); | 4206 | i = TEX_Token (lasthit); |
| 3677 | if (i >= 0) | 4207 | if (i >= 0) |
| 3678 | { | 4208 | { |
| @@ -3724,6 +4254,8 @@ TEX_mode (inf) | |||
| 3724 | TEX_opgrp = '<'; | 4254 | TEX_opgrp = '<'; |
| 3725 | TEX_clgrp = '>'; | 4255 | TEX_clgrp = '>'; |
| 3726 | } | 4256 | } |
| 4257 | /* If the input file is compressed, inf is a pipe, and rewind may fail. | ||
| 4258 | No attempt is made to correct the situation. */ | ||
| 3727 | rewind (inf); | 4259 | rewind (inf); |
| 3728 | } | 4260 | } |
| 3729 | 4261 | ||
| @@ -3751,7 +4283,7 @@ TEX_decode_env (evarname, defenv) | |||
| 3751 | 4283 | ||
| 3752 | /* Allocate a token table */ | 4284 | /* Allocate a token table */ |
| 3753 | for (size = 1, p = env; p;) | 4285 | for (size = 1, p = env; p;) |
| 3754 | if ((p = etags_strchr (p, ':')) && *(++p)) | 4286 | if ((p = etags_strchr (p, ':')) && *++p != '\0') |
| 3755 | size++; | 4287 | size++; |
| 3756 | /* Add 1 to leave room for null terminator. */ | 4288 | /* Add 1 to leave room for null terminator. */ |
| 3757 | tab = xnew (size + 1, struct TEX_tabent); | 4289 | tab = xnew (size + 1, struct TEX_tabent); |
| @@ -3784,7 +4316,7 @@ TEX_decode_env (evarname, defenv) | |||
| 3784 | /* If the text at CP matches one of the tag-defining TeX command names, | 4316 | /* If the text at CP matches one of the tag-defining TeX command names, |
| 3785 | return the pointer to the first occurrence of that command in TEX_toktab. | 4317 | return the pointer to the first occurrence of that command in TEX_toktab. |
| 3786 | Otherwise return -1. | 4318 | Otherwise return -1. |
| 3787 | Keep the capital `T' in `Token' for dumb truncating compilers | 4319 | Keep the capital `T' in `token' for dumb truncating compilers |
| 3788 | (this distinguishes it from `TEX_toktab' */ | 4320 | (this distinguishes it from `TEX_toktab' */ |
| 3789 | int | 4321 | int |
| 3790 | TEX_Token (cp) | 4322 | TEX_Token (cp) |
| @@ -3802,18 +4334,17 @@ TEX_Token (cp) | |||
| 3802 | * Prolog support (rewritten) by Anders Lindgren, Mar. 96 | 4334 | * Prolog support (rewritten) by Anders Lindgren, Mar. 96 |
| 3803 | * | 4335 | * |
| 3804 | * Assumes that the predicate starts at column 0. | 4336 | * Assumes that the predicate starts at column 0. |
| 3805 | * Only the first clause of a predicate is added. | 4337 | * Only the first clause of a predicate is added. |
| 3806 | */ | 4338 | */ |
| 3807 | int prolog_pred (); | 4339 | int prolog_pred (); |
| 3808 | void prolog_skip_comment (); | 4340 | void prolog_skip_comment (); |
| 3809 | int prolog_atom (); | 4341 | int prolog_atom (); |
| 3810 | int eat_white (); | ||
| 3811 | 4342 | ||
| 3812 | void | 4343 | void |
| 3813 | Prolog_functions (inf) | 4344 | Prolog_functions (inf) |
| 3814 | FILE *inf; | 4345 | FILE *inf; |
| 3815 | { | 4346 | { |
| 3816 | char * last; | 4347 | char *cp, *last; |
| 3817 | int len; | 4348 | int len; |
| 3818 | int allocated; | 4349 | int allocated; |
| 3819 | 4350 | ||
| @@ -3821,32 +4352,24 @@ Prolog_functions (inf) | |||
| 3821 | len = 0; | 4352 | len = 0; |
| 3822 | last = NULL; | 4353 | last = NULL; |
| 3823 | 4354 | ||
| 3824 | lineno = 0; | 4355 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 3825 | linecharno = 0; | ||
| 3826 | charno = 0; | ||
| 3827 | |||
| 3828 | while (!feof (inf)) | ||
| 3829 | { | 4356 | { |
| 3830 | lineno++; | 4357 | if (cp[0] == '\0') /* Empty line */ |
| 3831 | linecharno += charno; | ||
| 3832 | charno = readline (&lb, inf); | ||
| 3833 | dbp = lb.buffer; | ||
| 3834 | if (dbp[0] == '\0') /* Empty line */ | ||
| 3835 | continue; | 4358 | continue; |
| 3836 | else if (isspace (dbp[0])) /* Not a predicate */ | 4359 | else if (isspace (cp[0])) /* Not a predicate */ |
| 3837 | continue; | 4360 | continue; |
| 3838 | else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */ | 4361 | else if (cp[0] == '/' && cp[1] == '*') /* comment. */ |
| 3839 | prolog_skip_comment (&lb, inf); | 4362 | prolog_skip_comment (&lb, inf); |
| 3840 | else if (len = prolog_pred (dbp, last)) | 4363 | else if ((len = prolog_pred (cp, last)) > 0) |
| 3841 | { | 4364 | { |
| 3842 | /* Predicate. Store the function name so that we only | 4365 | /* Predicate. Store the function name so that we only |
| 3843 | generate a tag for the first clause. */ | 4366 | generate a tag for the first clause. */ |
| 3844 | if (last == NULL) | 4367 | if (last == NULL) |
| 3845 | last = xnew(len + 1, char); | 4368 | last = xnew(len + 1, char); |
| 3846 | else if (len + 1 > allocated) | 4369 | else if (len + 1 > allocated) |
| 3847 | last = (char *) xrealloc(last, len + 1); | 4370 | last = xrnew (last, len + 1, char); |
| 3848 | allocated = len + 1; | 4371 | allocated = len + 1; |
| 3849 | strncpy (last, dbp, len); | 4372 | strncpy (last, cp, len); |
| 3850 | last[len] = '\0'; | 4373 | last[len] = '\0'; |
| 3851 | } | 4374 | } |
| 3852 | } | 4375 | } |
| @@ -3855,7 +4378,7 @@ Prolog_functions (inf) | |||
| 3855 | 4378 | ||
| 3856 | void | 4379 | void |
| 3857 | prolog_skip_comment (plb, inf) | 4380 | prolog_skip_comment (plb, inf) |
| 3858 | struct linebuffer *plb; | 4381 | linebuffer *plb; |
| 3859 | FILE *inf; | 4382 | FILE *inf; |
| 3860 | { | 4383 | { |
| 3861 | char *cp; | 4384 | char *cp; |
| @@ -3894,7 +4417,7 @@ prolog_pred (s, last) | |||
| 3894 | return 0; | 4417 | return 0; |
| 3895 | 4418 | ||
| 3896 | len = pos; | 4419 | len = pos; |
| 3897 | pos += eat_white (s, pos); | 4420 | pos = skip_spaces (s + pos) - s; |
| 3898 | 4421 | ||
| 3899 | if ((s[pos] == '(') || (s[pos] == '.')) | 4422 | if ((s[pos] == '(') || (s[pos] == '.')) |
| 3900 | { | 4423 | { |
| @@ -3903,11 +4426,10 @@ prolog_pred (s, last) | |||
| 3903 | 4426 | ||
| 3904 | /* Save only the first clause. */ | 4427 | /* Save only the first clause. */ |
| 3905 | if (last == NULL | 4428 | if (last == NULL |
| 3906 | || len != strlen (last) | 4429 | || len != (int)strlen (last) |
| 3907 | || !strneq (s, last, len)) | 4430 | || !strneq (s, last, len)) |
| 3908 | { | 4431 | { |
| 3909 | pfnote (savenstr (s, len), TRUE, | 4432 | pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno); |
| 3910 | s, pos, lineno, linecharno); | ||
| 3911 | return len; | 4433 | return len; |
| 3912 | } | 4434 | } |
| 3913 | } | 4435 | } |
| @@ -3946,7 +4468,7 @@ prolog_atom (s, pos) | |||
| 3946 | { | 4468 | { |
| 3947 | pos++; | 4469 | pos++; |
| 3948 | 4470 | ||
| 3949 | while (1) | 4471 | while (1) |
| 3950 | { | 4472 | { |
| 3951 | if (s[pos] == '\'') | 4473 | if (s[pos] == '\'') |
| 3952 | { | 4474 | { |
| @@ -3972,24 +4494,8 @@ prolog_atom (s, pos) | |||
| 3972 | else | 4494 | else |
| 3973 | return -1; | 4495 | return -1; |
| 3974 | } | 4496 | } |
| 3975 | |||
| 3976 | /* Consume whitespace. Return the number of bytes eaten. */ | ||
| 3977 | int | ||
| 3978 | eat_white (s, pos) | ||
| 3979 | char *s; | ||
| 3980 | int pos; | ||
| 3981 | { | ||
| 3982 | int origpos = pos; | ||
| 3983 | |||
| 3984 | origpos = pos; | ||
| 3985 | |||
| 3986 | while (isspace (s[pos])) | ||
| 3987 | pos++; | ||
| 3988 | |||
| 3989 | return pos - origpos; | ||
| 3990 | } | ||
| 3991 | 4497 | ||
| 3992 | /* | 4498 | /* |
| 3993 | * Support for Erlang -- Anders Lindgren, Feb 1996. | 4499 | * Support for Erlang -- Anders Lindgren, Feb 1996. |
| 3994 | * | 4500 | * |
| 3995 | * Generates tags for functions, defines, and records. | 4501 | * Generates tags for functions, defines, and records. |
| @@ -4004,7 +4510,7 @@ void | |||
| 4004 | Erlang_functions (inf) | 4510 | Erlang_functions (inf) |
| 4005 | FILE *inf; | 4511 | FILE *inf; |
| 4006 | { | 4512 | { |
| 4007 | char * last; | 4513 | char *cp, *last; |
| 4008 | int len; | 4514 | int len; |
| 4009 | int allocated; | 4515 | int allocated; |
| 4010 | 4516 | ||
| @@ -4012,41 +4518,33 @@ Erlang_functions (inf) | |||
| 4012 | len = 0; | 4518 | len = 0; |
| 4013 | last = NULL; | 4519 | last = NULL; |
| 4014 | 4520 | ||
| 4015 | lineno = 0; | 4521 | LOOP_ON_INPUT_LINES (inf, lb, cp) |
| 4016 | linecharno = 0; | ||
| 4017 | charno = 0; | ||
| 4018 | |||
| 4019 | while (!feof (inf)) | ||
| 4020 | { | 4522 | { |
| 4021 | lineno++; | 4523 | if (cp[0] == '\0') /* Empty line */ |
| 4022 | linecharno += charno; | ||
| 4023 | charno = readline (&lb, inf); | ||
| 4024 | dbp = lb.buffer; | ||
| 4025 | if (dbp[0] == '\0') /* Empty line */ | ||
| 4026 | continue; | 4524 | continue; |
| 4027 | else if (isspace (dbp[0])) /* Not function nor attribute */ | 4525 | else if (isspace (cp[0])) /* Not function nor attribute */ |
| 4028 | continue; | 4526 | continue; |
| 4029 | else if (dbp[0] == '%') /* comment */ | 4527 | else if (cp[0] == '%') /* comment */ |
| 4030 | continue; | 4528 | continue; |
| 4031 | else if (dbp[0] == '"') /* Sometimes, strings start in column one */ | 4529 | else if (cp[0] == '"') /* Sometimes, strings start in column one */ |
| 4032 | continue; | 4530 | continue; |
| 4033 | else if (dbp[0] == '-') /* attribute, e.g. "-define" */ | 4531 | else if (cp[0] == '-') /* attribute, e.g. "-define" */ |
| 4034 | { | 4532 | { |
| 4035 | erlang_attribute (dbp); | 4533 | erlang_attribute (cp); |
| 4036 | last = NULL; | 4534 | last = NULL; |
| 4037 | } | 4535 | } |
| 4038 | else if (len = erlang_func (dbp, last)) | 4536 | else if ((len = erlang_func (cp, last)) > 0) |
| 4039 | { | 4537 | { |
| 4040 | /* | 4538 | /* |
| 4041 | * Function. Store the function name so that we only | 4539 | * Function. Store the function name so that we only |
| 4042 | * generates a tag for the first clause. | 4540 | * generates a tag for the first clause. |
| 4043 | */ | 4541 | */ |
| 4044 | if (last == NULL) | 4542 | if (last == NULL) |
| 4045 | last = xnew (len + 1, char); | 4543 | last = xnew (len + 1, char); |
| 4046 | else if (len + 1 > allocated) | 4544 | else if (len + 1 > allocated) |
| 4047 | last = (char *) xrealloc (last, len + 1); | 4545 | last = xrnew (last, len + 1, char); |
| 4048 | allocated = len + 1; | 4546 | allocated = len + 1; |
| 4049 | strncpy (last, dbp, len); | 4547 | strncpy (last, cp, len); |
| 4050 | last[len] = '\0'; | 4548 | last[len] = '\0'; |
| 4051 | } | 4549 | } |
| 4052 | } | 4550 | } |
| @@ -4076,16 +4574,15 @@ erlang_func (s, last) | |||
| 4076 | return 0; | 4574 | return 0; |
| 4077 | 4575 | ||
| 4078 | len = pos; | 4576 | len = pos; |
| 4079 | pos += eat_white (s, pos); | 4577 | pos = skip_spaces (s + pos) - s; |
| 4080 | 4578 | ||
| 4081 | /* Save only the first clause. */ | 4579 | /* Save only the first clause. */ |
| 4082 | if (s[pos++] == '(' | 4580 | if (s[pos++] == '(' |
| 4083 | && (last == NULL | 4581 | && (last == NULL |
| 4084 | || len != strlen (last) | 4582 | || len != (int)strlen (last) |
| 4085 | || !strneq (s, last, len))) | 4583 | || !strneq (s, last, len))) |
| 4086 | { | 4584 | { |
| 4087 | pfnote (savenstr (s, len), TRUE, | 4585 | pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno); |
| 4088 | s, pos, lineno, linecharno); | ||
| 4089 | return len; | 4586 | return len; |
| 4090 | } | 4587 | } |
| 4091 | 4588 | ||
| @@ -4094,7 +4591,7 @@ erlang_func (s, last) | |||
| 4094 | 4591 | ||
| 4095 | 4592 | ||
| 4096 | /* | 4593 | /* |
| 4097 | * Handle attributes. Currently, tags are generated for defines | 4594 | * Handle attributes. Currently, tags are generated for defines |
| 4098 | * and records. | 4595 | * and records. |
| 4099 | * | 4596 | * |
| 4100 | * They are on the form: | 4597 | * They are on the form: |
| @@ -4111,13 +4608,14 @@ erlang_attribute (s) | |||
| 4111 | 4608 | ||
| 4112 | if (strneq (s, "-define", 7) || strneq (s, "-record", 7)) | 4609 | if (strneq (s, "-define", 7) || strneq (s, "-record", 7)) |
| 4113 | { | 4610 | { |
| 4114 | pos = 7 + eat_white (s, 7); | 4611 | pos = skip_spaces (s + 7) - s; |
| 4115 | if (s[pos++] == '(') | 4612 | if (s[pos++] == '(') |
| 4116 | { | 4613 | { |
| 4117 | pos += eat_white (s, pos); | 4614 | pos = skip_spaces (s + pos) - s; |
| 4118 | if (len = erlang_atom (s, pos)) | 4615 | len = erlang_atom (s, pos); |
| 4119 | pfnote (savenstr (& s[pos], len), TRUE, | 4616 | if (len != 0) |
| 4120 | s, pos + len, lineno, linecharno); | 4617 | pfnote (savenstr (& s[pos], len), TRUE, |
| 4618 | s, pos + len, lineno, linecharno); | ||
| 4121 | } | 4619 | } |
| 4122 | } | 4620 | } |
| 4123 | return; | 4621 | return; |
| @@ -4149,7 +4647,7 @@ erlang_atom (s, pos) | |||
| 4149 | { | 4647 | { |
| 4150 | pos++; | 4648 | pos++; |
| 4151 | 4649 | ||
| 4152 | while (1) | 4650 | while (1) |
| 4153 | { | 4651 | { |
| 4154 | if (s[pos] == '\'') | 4652 | if (s[pos] == '\'') |
| 4155 | { | 4653 | { |
| @@ -4175,6 +4673,7 @@ erlang_atom (s, pos) | |||
| 4175 | } | 4673 | } |
| 4176 | 4674 | ||
| 4177 | #ifdef ETAGS_REGEXPS | 4675 | #ifdef ETAGS_REGEXPS |
| 4676 | |||
| 4178 | /* Take a string like "/blah/" and turn it into "blah", making sure | 4677 | /* Take a string like "/blah/" and turn it into "blah", making sure |
| 4179 | that the first and last characters are the same, and handling | 4678 | that the first and last characters are the same, and handling |
| 4180 | quoted separator characters. Actually, stops on the occurrence of | 4679 | quoted separator characters. Actually, stops on the occurrence of |
| @@ -4219,60 +4718,87 @@ scan_separators (name) | |||
| 4219 | } | 4718 | } |
| 4220 | 4719 | ||
| 4221 | /* Look at the argument of --regex or --no-regex and do the right | 4720 | /* Look at the argument of --regex or --no-regex and do the right |
| 4222 | thing. */ | 4721 | thing. Same for each line of a regexp file. */ |
| 4223 | void | 4722 | void |
| 4224 | analyse_regex (regex_arg) | 4723 | analyse_regex (regex_arg, ignore_case) |
| 4225 | char *regex_arg; | 4724 | char *regex_arg; |
| 4725 | bool ignore_case; | ||
| 4226 | { | 4726 | { |
| 4227 | struct stat stat_buf; | ||
| 4228 | |||
| 4229 | if (regex_arg == NULL) | 4727 | if (regex_arg == NULL) |
| 4728 | free_patterns (); /* --no-regex: remove existing regexps */ | ||
| 4729 | |||
| 4730 | /* A real --regexp option or a line in a regexp file. */ | ||
| 4731 | switch (regex_arg[0]) | ||
| 4230 | { | 4732 | { |
| 4231 | /* Remove existing regexps. */ | 4733 | /* Comments in regexp file or null arg to --regex. */ |
| 4232 | num_patterns = 0; | 4734 | case '\0': |
| 4233 | patterns = NULL; | 4735 | case ' ': |
| 4234 | return; | 4736 | case '\t': |
| 4235 | } | 4737 | break; |
| 4236 | if (regex_arg[0] == '\0') | ||
| 4237 | { | ||
| 4238 | error ("missing regexp", (char *)NULL); | ||
| 4239 | return; | ||
| 4240 | } | ||
| 4241 | if (regex_arg[0] == '@' | ||
| 4242 | && stat (regex_arg + 1, &stat_buf) == 0) | ||
| 4243 | { | ||
| 4244 | FILE *regexfp; | ||
| 4245 | struct linebuffer regexbuf; | ||
| 4246 | char *regexfile = regex_arg + 1; | ||
| 4247 | 4738 | ||
| 4248 | /* regexfile is a file containing regexps, one per line. */ | 4739 | /* Read a regex file. This is recursive and may result in a |
| 4249 | regexfp = fopen (regexfile, "r"); | 4740 | loop, which will stop when the file descriptors are exhausted. */ |
| 4250 | if (regexfp == NULL) | 4741 | case '@': |
| 4251 | { | 4742 | { |
| 4252 | perror (regexfile); | 4743 | FILE *regexfp; |
| 4744 | linebuffer regexbuf; | ||
| 4745 | char *regexfile = regex_arg + 1; | ||
| 4746 | |||
| 4747 | /* regexfile is a file containing regexps, one per line. */ | ||
| 4748 | regexfp = fopen (regexfile, "r"); | ||
| 4749 | if (regexfp == NULL) | ||
| 4750 | { | ||
| 4751 | pfatal (regexfile); | ||
| 4752 | return; | ||
| 4753 | } | ||
| 4754 | initbuffer (®exbuf); | ||
| 4755 | while (readline_internal (®exbuf, regexfp) > 0) | ||
| 4756 | analyse_regex (regexbuf.buffer, ignore_case); | ||
| 4757 | free (regexbuf.buffer); | ||
| 4758 | fclose (regexfp); | ||
| 4759 | } | ||
| 4760 | break; | ||
| 4761 | |||
| 4762 | /* Regexp to be used for a specific language only. */ | ||
| 4763 | case '{': | ||
| 4764 | { | ||
| 4765 | language *lang; | ||
| 4766 | char *lang_name = regex_arg + 1; | ||
| 4767 | char *cp; | ||
| 4768 | |||
| 4769 | for (cp = lang_name; *cp != '}'; cp++) | ||
| 4770 | if (*cp == '\0') | ||
| 4771 | { | ||
| 4772 | error ("unterminated language name in regex: %s", regex_arg); | ||
| 4773 | return; | ||
| 4774 | } | ||
| 4775 | *cp = '\0'; | ||
| 4776 | lang = get_language_from_name (lang_name); | ||
| 4777 | if (lang == NULL) | ||
| 4253 | return; | 4778 | return; |
| 4254 | } | 4779 | add_regex (cp + 1, ignore_case, lang); |
| 4255 | initbuffer (®exbuf); | 4780 | } |
| 4256 | while (readline_internal (®exbuf, regexfp)) | 4781 | break; |
| 4257 | add_regex (regexbuf.buffer); | 4782 | |
| 4258 | free (regexbuf.buffer); | 4783 | /* Regexp to be used for any language. */ |
| 4259 | fclose (regexfp); | 4784 | default: |
| 4260 | } | 4785 | add_regex (regex_arg, ignore_case, NULL); |
| 4261 | else | 4786 | break; |
| 4262 | { | ||
| 4263 | add_regex (regex_arg); | ||
| 4264 | } | 4787 | } |
| 4265 | } | 4788 | } |
| 4266 | 4789 | ||
| 4267 | /* Turn a name, which is an ed-style (but Emacs syntax) regular | 4790 | /* Turn a name, which is an ed-style (but Emacs syntax) regular |
| 4268 | expression, into a real regular expression by compiling it. */ | 4791 | expression, into a real regular expression by compiling it. */ |
| 4269 | void | 4792 | void |
| 4270 | add_regex (regexp_pattern) | 4793 | add_regex (regexp_pattern, ignore_case, lang) |
| 4271 | char *regexp_pattern; | 4794 | char *regexp_pattern; |
| 4795 | bool ignore_case; | ||
| 4796 | language *lang; | ||
| 4272 | { | 4797 | { |
| 4273 | char *name; | 4798 | char *name; |
| 4274 | const char *err; | 4799 | const char *err; |
| 4275 | struct re_pattern_buffer *patbuf; | 4800 | struct re_pattern_buffer *patbuf; |
| 4801 | pattern *pp; | ||
| 4276 | 4802 | ||
| 4277 | 4803 | ||
| 4278 | if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0]) | 4804 | if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0]) |
| @@ -4289,12 +4815,12 @@ add_regex (regexp_pattern) | |||
| 4289 | (void) scan_separators (name); | 4815 | (void) scan_separators (name); |
| 4290 | 4816 | ||
| 4291 | patbuf = xnew (1, struct re_pattern_buffer); | 4817 | patbuf = xnew (1, struct re_pattern_buffer); |
| 4292 | patbuf->translate = NULL; | 4818 | /* Translation table to fold case if appropriate. */ |
| 4819 | patbuf->translate = (ignore_case) ? lc_trans : NULL; | ||
| 4293 | patbuf->fastmap = NULL; | 4820 | patbuf->fastmap = NULL; |
| 4294 | patbuf->buffer = NULL; | 4821 | patbuf->buffer = NULL; |
| 4295 | patbuf->allocated = 0; | 4822 | patbuf->allocated = 0; |
| 4296 | 4823 | ||
| 4297 | re_syntax_options = RE_INTERVALS; | ||
| 4298 | err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); | 4824 | err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); |
| 4299 | if (err != NULL) | 4825 | if (err != NULL) |
| 4300 | { | 4826 | { |
| @@ -4302,16 +4828,14 @@ add_regex (regexp_pattern) | |||
| 4302 | return; | 4828 | return; |
| 4303 | } | 4829 | } |
| 4304 | 4830 | ||
| 4305 | num_patterns += 1; | 4831 | pp = p_head; |
| 4306 | if (num_patterns == 1) | 4832 | p_head = xnew (1, pattern); |
| 4307 | patterns = xnew (1, struct pattern); | 4833 | p_head->regex = savestr (regexp_pattern); |
| 4308 | else | 4834 | p_head->p_next = pp; |
| 4309 | patterns = ((struct pattern *) | 4835 | p_head->language = lang; |
| 4310 | xrealloc (patterns, | 4836 | p_head->pattern = patbuf; |
| 4311 | (num_patterns * sizeof (struct pattern)))); | 4837 | p_head->name_pattern = savestr (name); |
| 4312 | patterns[num_patterns - 1].pattern = patbuf; | 4838 | p_head->error_signaled = FALSE; |
| 4313 | patterns[num_patterns - 1].name_pattern = savestr (name); | ||
| 4314 | patterns[num_patterns - 1].error_signaled = FALSE; | ||
| 4315 | } | 4839 | } |
| 4316 | 4840 | ||
| 4317 | /* | 4841 | /* |
| @@ -4360,49 +4884,88 @@ substitute (in, out, regs) | |||
| 4360 | *t++ = *out; | 4884 | *t++ = *out; |
| 4361 | *t = '\0'; | 4885 | *t = '\0'; |
| 4362 | 4886 | ||
| 4363 | if (DEBUG && (t > result + size || t - result != strlen (result))) | 4887 | if (DEBUG && (t > result + size || t - result != (int)strlen (result))) |
| 4364 | abort (); | 4888 | abort (); |
| 4365 | 4889 | ||
| 4366 | return result; | 4890 | return result; |
| 4367 | } | 4891 | } |
| 4892 | |||
| 4893 | /* Deallocate all patterns. */ | ||
| 4894 | void | ||
| 4895 | free_patterns () | ||
| 4896 | { | ||
| 4897 | pattern *pp; | ||
| 4898 | while (p_head != NULL) | ||
| 4899 | { | ||
| 4900 | pp = p_head->p_next; | ||
| 4901 | free (p_head->regex); | ||
| 4902 | free (p_head->name_pattern); | ||
| 4903 | free (p_head); | ||
| 4904 | p_head = pp; | ||
| 4905 | } | ||
| 4906 | return; | ||
| 4907 | } | ||
| 4368 | 4908 | ||
| 4909 | void | ||
| 4910 | get_tag (bp) | ||
| 4911 | register char *bp; | ||
| 4912 | { | ||
| 4913 | register char *cp; | ||
| 4914 | |||
| 4915 | if (*bp == '\0') | ||
| 4916 | return; | ||
| 4917 | /* Go till you get to white space or a syntactic break */ | ||
| 4918 | for (cp = bp + 1; | ||
| 4919 | *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp); | ||
| 4920 | cp++) | ||
| 4921 | continue; | ||
| 4922 | pfnote (savenstr (bp, cp-bp), TRUE, | ||
| 4923 | lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | ||
| 4924 | } | ||
| 4925 | |||
| 4369 | #endif /* ETAGS_REGEXPS */ | 4926 | #endif /* ETAGS_REGEXPS */ |
| 4370 | /* Initialize a linebuffer for use */ | 4927 | /* Initialize a linebuffer for use */ |
| 4371 | void | 4928 | void |
| 4372 | initbuffer (linebuffer) | 4929 | initbuffer (lbp) |
| 4373 | struct linebuffer *linebuffer; | 4930 | linebuffer *lbp; |
| 4374 | { | 4931 | { |
| 4375 | linebuffer->size = 200; | 4932 | lbp->size = 200; |
| 4376 | linebuffer->buffer = xnew (200, char); | 4933 | lbp->buffer = xnew (200, char); |
| 4377 | } | 4934 | } |
| 4378 | 4935 | ||
| 4379 | /* | 4936 | /* |
| 4380 | * Read a line of text from `stream' into `linebuffer'. | 4937 | * Read a line of text from `stream' into `lbp', excluding the |
| 4381 | * Return the number of characters read from `stream', | 4938 | * newline or CR-NL, if any. Return the number of characters read from |
| 4382 | * which is the length of the line including the newline, if any. | 4939 | * `stream', which is the length of the line including the newline. |
| 4940 | * | ||
| 4941 | * On DOS or Windows we do not count the CR character, if any, before the | ||
| 4942 | * NL, in the returned length; this mirrors the behavior of emacs on those | ||
| 4943 | * platforms (for text files, it translates CR-NL to NL as it reads in the | ||
| 4944 | * file). | ||
| 4383 | */ | 4945 | */ |
| 4384 | long | 4946 | long |
| 4385 | readline_internal (linebuffer, stream) | 4947 | readline_internal (lbp, stream) |
| 4386 | struct linebuffer *linebuffer; | 4948 | linebuffer *lbp; |
| 4387 | register FILE *stream; | 4949 | register FILE *stream; |
| 4388 | { | 4950 | { |
| 4389 | char *buffer = linebuffer->buffer; | 4951 | char *buffer = lbp->buffer; |
| 4390 | register char *p = linebuffer->buffer; | 4952 | register char *p = lbp->buffer; |
| 4391 | register char *pend; | 4953 | register char *pend; |
| 4392 | int chars_deleted; | 4954 | int chars_deleted; |
| 4393 | 4955 | ||
| 4394 | pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */ | 4956 | pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */ |
| 4395 | 4957 | ||
| 4396 | while (1) | 4958 | while (1) |
| 4397 | { | 4959 | { |
| 4398 | register int c = getc (stream); | 4960 | register int c = getc (stream); |
| 4399 | if (p == pend) | 4961 | if (p == pend) |
| 4400 | { | 4962 | { |
| 4401 | linebuffer->size *= 2; | 4963 | /* We're at the end of linebuffer: expand it. */ |
| 4402 | buffer = (char *) xrealloc (buffer, linebuffer->size); | 4964 | lbp->size *= 2; |
| 4403 | p += buffer - linebuffer->buffer; | 4965 | buffer = xrnew (buffer, lbp->size, char); |
| 4404 | pend = buffer + linebuffer->size; | 4966 | p += buffer - lbp->buffer; |
| 4405 | linebuffer->buffer = buffer; | 4967 | pend = buffer + lbp->size; |
| 4968 | lbp->buffer = buffer; | ||
| 4406 | } | 4969 | } |
| 4407 | if (c == EOF) | 4970 | if (c == EOF) |
| 4408 | { | 4971 | { |
| @@ -4435,39 +4998,43 @@ readline_internal (linebuffer, stream) | |||
| 4435 | } | 4998 | } |
| 4436 | *p++ = c; | 4999 | *p++ = c; |
| 4437 | } | 5000 | } |
| 4438 | linebuffer->len = p - buffer; | 5001 | lbp->len = p - buffer; |
| 4439 | 5002 | ||
| 4440 | return linebuffer->len + chars_deleted; | 5003 | return lbp->len + chars_deleted; |
| 4441 | } | 5004 | } |
| 4442 | 5005 | ||
| 4443 | /* | 5006 | /* |
| 4444 | * Like readline_internal, above, but in addition try to match the | 5007 | * Like readline_internal, above, but in addition try to match the |
| 4445 | * input line against any existing regular expressions. | 5008 | * input line against relevant regular expressions. |
| 4446 | */ | 5009 | */ |
| 4447 | long | 5010 | long |
| 4448 | readline (linebuffer, stream) | 5011 | readline (lbp, stream) |
| 4449 | struct linebuffer *linebuffer; | 5012 | linebuffer *lbp; |
| 4450 | FILE *stream; | 5013 | FILE *stream; |
| 4451 | { | 5014 | { |
| 4452 | /* Read new line. */ | 5015 | /* Read new line. */ |
| 4453 | long result = readline_internal (linebuffer, stream); | 5016 | long result = readline_internal (lbp, stream); |
| 4454 | #ifdef ETAGS_REGEXPS | 5017 | #ifdef ETAGS_REGEXPS |
| 4455 | int i; | 5018 | int match; |
| 5019 | pattern *pp; | ||
| 4456 | 5020 | ||
| 4457 | /* Match against all listed patterns. */ | 5021 | /* Match against relevant patterns. */ |
| 4458 | if (linebuffer->len > 0) | 5022 | if (lbp->len > 0) |
| 4459 | for (i = 0; i < num_patterns; ++i) | 5023 | for (pp = p_head; pp != NULL; pp = pp->p_next) |
| 4460 | { | 5024 | { |
| 4461 | int match = re_match (patterns[i].pattern, linebuffer->buffer, | 5025 | /* Only use generic regexps or those for the current language. */ |
| 4462 | linebuffer->len, 0, &patterns[i].regs); | 5026 | if (pp->language != NULL && pp->language != curlang) |
| 5027 | continue; | ||
| 5028 | |||
| 5029 | match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs); | ||
| 4463 | switch (match) | 5030 | switch (match) |
| 4464 | { | 5031 | { |
| 4465 | case -2: | 5032 | case -2: |
| 4466 | /* Some error. */ | 5033 | /* Some error. */ |
| 4467 | if (!patterns[i].error_signaled) | 5034 | if (!pp->error_signaled) |
| 4468 | { | 5035 | { |
| 4469 | error ("error while matching pattern %d", i); | 5036 | error ("error while matching \"%s\"", pp->regex); |
| 4470 | patterns[i].error_signaled = TRUE; | 5037 | pp->error_signaled = TRUE; |
| 4471 | } | 5038 | } |
| 4472 | break; | 5039 | break; |
| 4473 | case -1: | 5040 | case -1: |
| @@ -4475,49 +5042,27 @@ readline (linebuffer, stream) | |||
| 4475 | break; | 5042 | break; |
| 4476 | default: | 5043 | default: |
| 4477 | /* Match occurred. Construct a tag. */ | 5044 | /* Match occurred. Construct a tag. */ |
| 4478 | if (patterns[i].name_pattern[0] != '\0') | 5045 | if (pp->name_pattern[0] != '\0') |
| 4479 | { | 5046 | { |
| 4480 | /* Make a named tag. */ | 5047 | /* Make a named tag. */ |
| 4481 | char *name = substitute (linebuffer->buffer, | 5048 | char *name = substitute (lbp->buffer, |
| 4482 | patterns[i].name_pattern, | 5049 | pp->name_pattern, &pp->regs); |
| 4483 | &patterns[i].regs); | ||
| 4484 | if (name != NULL) | 5050 | if (name != NULL) |
| 4485 | pfnote (name, TRUE, | 5051 | pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno); |
| 4486 | linebuffer->buffer, match, lineno, linecharno); | ||
| 4487 | } | 5052 | } |
| 4488 | else | 5053 | else |
| 4489 | { | 5054 | { |
| 4490 | /* Make an unnamed tag. */ | 5055 | /* Make an unnamed tag. */ |
| 4491 | pfnote ((char *)NULL, TRUE, | 5056 | pfnote ((char *)NULL, TRUE, |
| 4492 | linebuffer->buffer, match, lineno, linecharno); | 5057 | lbp->buffer, match, lineno, linecharno); |
| 4493 | } | 5058 | } |
| 4494 | break; | 5059 | break; |
| 4495 | } | 5060 | } |
| 4496 | } | 5061 | } |
| 4497 | #endif /* ETAGS_REGEXPS */ | 5062 | #endif /* ETAGS_REGEXPS */ |
| 4498 | |||
| 4499 | return result; | ||
| 4500 | } | ||
| 4501 | 5063 | ||
| 4502 | /* | 5064 | return result; |
| 4503 | * Read a file, but do no processing. This is used to do regexp | ||
| 4504 | * matching on files that have no language defined. | ||
| 4505 | */ | ||
| 4506 | void | ||
| 4507 | just_read_file (inf) | ||
| 4508 | FILE *inf; | ||
| 4509 | { | ||
| 4510 | lineno = 0; | ||
| 4511 | charno = 0; | ||
| 4512 | |||
| 4513 | while (!feof (inf)) | ||
| 4514 | { | ||
| 4515 | ++lineno; | ||
| 4516 | linecharno = charno; | ||
| 4517 | charno += readline (&lb, inf); | ||
| 4518 | } | ||
| 4519 | } | 5065 | } |
| 4520 | |||
| 4521 | 5066 | ||
| 4522 | /* | 5067 | /* |
| 4523 | * Return a pointer to a space of size strlen(cp)+1 allocated | 5068 | * Return a pointer to a space of size strlen(cp)+1 allocated |
| @@ -4587,6 +5132,26 @@ etags_strchr (sp, c) | |||
| 4587 | return NULL; | 5132 | return NULL; |
| 4588 | } | 5133 | } |
| 4589 | 5134 | ||
| 5135 | /* Skip spaces, return new pointer. */ | ||
| 5136 | char * | ||
| 5137 | skip_spaces (cp) | ||
| 5138 | char *cp; | ||
| 5139 | { | ||
| 5140 | while (isspace (*cp)) /* isspace('\0')==FALSE */ | ||
| 5141 | cp++; | ||
| 5142 | return cp; | ||
| 5143 | } | ||
| 5144 | |||
| 5145 | /* Skip non spaces, return new pointer. */ | ||
| 5146 | char * | ||
| 5147 | skip_non_spaces (cp) | ||
| 5148 | char *cp; | ||
| 5149 | { | ||
| 5150 | while (!iswhite (*cp)) /* iswhite('\0')==TRUE */ | ||
| 5151 | cp++; | ||
| 5152 | return cp; | ||
| 5153 | } | ||
| 5154 | |||
| 4590 | /* Print error message and exit. */ | 5155 | /* Print error message and exit. */ |
| 4591 | void | 5156 | void |
| 4592 | fatal (s1, s2) | 5157 | fatal (s1, s2) |
| @@ -4607,8 +5172,14 @@ pfatal (s1) | |||
| 4607 | void | 5172 | void |
| 4608 | suggest_asking_for_help () | 5173 | suggest_asking_for_help () |
| 4609 | { | 5174 | { |
| 4610 | fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n", | 5175 | fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n", |
| 4611 | progname); | 5176 | progname, |
| 5177 | #ifdef LONG_OPTIONS | ||
| 5178 | "--help" | ||
| 5179 | #else | ||
| 5180 | "-h" | ||
| 5181 | #endif | ||
| 5182 | ); | ||
| 4612 | exit (BAD); | 5183 | exit (BAD); |
| 4613 | } | 5184 | } |
| 4614 | 5185 | ||
| @@ -4644,7 +5215,7 @@ concat (s1, s2, s3) | |||
| 4644 | char * | 5215 | char * |
| 4645 | etags_getcwd () | 5216 | etags_getcwd () |
| 4646 | { | 5217 | { |
| 4647 | #if defined (HAVE_GETCWD) || defined (WINDOWSNT) | 5218 | #ifdef HAVE_GETCWD |
| 4648 | int bufsize = 200; | 5219 | int bufsize = 200; |
| 4649 | char *path = xnew (bufsize, char); | 5220 | char *path = xnew (bufsize, char); |
| 4650 | 5221 | ||
| @@ -4657,19 +5228,7 @@ etags_getcwd () | |||
| 4657 | path = xnew (bufsize, char); | 5228 | path = xnew (bufsize, char); |
| 4658 | } | 5229 | } |
| 4659 | 5230 | ||
| 4660 | #if WINDOWSNT | 5231 | canonicalize_filename (path); |
| 4661 | { | ||
| 4662 | /* Convert backslashes to slashes. */ | ||
| 4663 | char *p; | ||
| 4664 | for (p = path; *p != '\0'; p++) | ||
| 4665 | if (*p == '\\') | ||
| 4666 | *p = '/'; | ||
| 4667 | /* Canonicalize drive letter case. */ | ||
| 4668 | if (islower (path[0])) | ||
| 4669 | path[0] = toupper (path[0]); | ||
| 4670 | } | ||
| 4671 | #endif | ||
| 4672 | |||
| 4673 | return path; | 5232 | return path; |
| 4674 | 5233 | ||
| 4675 | #else /* not HAVE_GETCWD */ | 5234 | #else /* not HAVE_GETCWD */ |
| @@ -4686,7 +5245,7 @@ etags_getcwd () | |||
| 4686 | 5245 | ||
| 4687 | return strdup (path); | 5246 | return strdup (path); |
| 4688 | #else /* not MSDOS */ | 5247 | #else /* not MSDOS */ |
| 4689 | struct linebuffer path; | 5248 | linebuffer path; |
| 4690 | FILE *pipe; | 5249 | FILE *pipe; |
| 4691 | 5250 | ||
| 4692 | initbuffer (&path); | 5251 | initbuffer (&path); |
| @@ -4700,27 +5259,29 @@ etags_getcwd () | |||
| 4700 | #endif /* not HAVE_GETCWD */ | 5259 | #endif /* not HAVE_GETCWD */ |
| 4701 | } | 5260 | } |
| 4702 | 5261 | ||
| 4703 | /* Return a newly allocated string containing the file name | 5262 | /* Return a newly allocated string containing the file name of FILE |
| 4704 | of FILE relative to the absolute directory DIR (which | 5263 | relative to the absolute directory DIR (which should end with a slash). */ |
| 4705 | should end with a slash). */ | ||
| 4706 | char * | 5264 | char * |
| 4707 | relative_filename (file, dir) | 5265 | relative_filename (file, dir) |
| 4708 | char *file, *dir; | 5266 | char *file, *dir; |
| 4709 | { | 5267 | { |
| 4710 | char *fp, *dp, *abs, *res; | 5268 | char *fp, *dp, *afn, *res; |
| 4711 | int i; | 5269 | int i; |
| 4712 | 5270 | ||
| 4713 | /* Find the common root of file and dir (with a trailing slash). */ | 5271 | /* Find the common root of file and dir (with a trailing slash). */ |
| 4714 | abs = absolute_filename (file, cwd); | 5272 | afn = absolute_filename (file, cwd); |
| 4715 | fp = abs; | 5273 | fp = afn; |
| 4716 | dp = dir; | 5274 | dp = dir; |
| 4717 | while (*fp++ == *dp++) | 5275 | while (*fp++ == *dp++) |
| 4718 | continue; | 5276 | continue; |
| 4719 | fp--, dp--; /* back to the first differing char */ | 5277 | fp--, dp--; /* back to the first differing char */ |
| 4720 | do { /* look at the equal chars until '/' */ | 5278 | #ifdef DOS_NT |
| 4721 | if (fp == abs) return abs; /* first char differs, give up */ | 5279 | if (fp == afn && afn[0] != '/') /* cannot build a relative name */ |
| 5280 | return afn; | ||
| 5281 | #endif | ||
| 5282 | do /* look at the equal chars until '/' */ | ||
| 4722 | fp--, dp--; | 5283 | fp--, dp--; |
| 4723 | } while (*fp != '/'); | 5284 | while (*fp != '/'); |
| 4724 | 5285 | ||
| 4725 | /* Build a sequence of "../" strings for the resulting relative file name. */ | 5286 | /* Build a sequence of "../" strings for the resulting relative file name. */ |
| 4726 | i = 0; | 5287 | i = 0; |
| @@ -4733,21 +5294,20 @@ relative_filename (file, dir) | |||
| 4733 | 5294 | ||
| 4734 | /* Add the file name relative to the common root of file and dir. */ | 5295 | /* Add the file name relative to the common root of file and dir. */ |
| 4735 | strcat (res, fp + 1); | 5296 | strcat (res, fp + 1); |
| 4736 | free (abs); | 5297 | free (afn); |
| 4737 | 5298 | ||
| 4738 | return res; | 5299 | return res; |
| 4739 | } | 5300 | } |
| 4740 | 5301 | ||
| 4741 | /* Return a newly allocated string containing the | 5302 | /* Return a newly allocated string containing the absolute file name |
| 4742 | absolute file name of FILE given CWD (which should | 5303 | of FILE given DIR (which should end with a slash). */ |
| 4743 | end with a slash). */ | ||
| 4744 | char * | 5304 | char * |
| 4745 | absolute_filename (file, cwd) | 5305 | absolute_filename (file, dir) |
| 4746 | char *file, *cwd; | 5306 | char *file, *dir; |
| 4747 | { | 5307 | { |
| 4748 | char *slashp, *cp, *res; | 5308 | char *slashp, *cp, *res; |
| 4749 | 5309 | ||
| 4750 | if (absolutefn (file)) | 5310 | if (filename_is_absolute (file)) |
| 4751 | res = savestr (file); | 5311 | res = savestr (file); |
| 4752 | #ifdef DOS_NT | 5312 | #ifdef DOS_NT |
| 4753 | /* We don't support non-absolute file names with a drive | 5313 | /* We don't support non-absolute file names with a drive |
| @@ -4756,7 +5316,7 @@ absolute_filename (file, cwd) | |||
| 4756 | fatal ("%s: relative file names with drive letters not supported", file); | 5316 | fatal ("%s: relative file names with drive letters not supported", file); |
| 4757 | #endif | 5317 | #endif |
| 4758 | else | 5318 | else |
| 4759 | res = concat (cwd, file, ""); | 5319 | res = concat (dir, file, ""); |
| 4760 | 5320 | ||
| 4761 | /* Delete the "/dirname/.." and "/." substrings. */ | 5321 | /* Delete the "/dirname/.." and "/." substrings. */ |
| 4762 | slashp = etags_strchr (res, '/'); | 5322 | slashp = etags_strchr (res, '/'); |
| @@ -4770,7 +5330,7 @@ absolute_filename (file, cwd) | |||
| 4770 | cp = slashp; | 5330 | cp = slashp; |
| 4771 | do | 5331 | do |
| 4772 | cp--; | 5332 | cp--; |
| 4773 | while (cp >= res && !absolutefn (cp)); | 5333 | while (cp >= res && !filename_is_absolute (cp)); |
| 4774 | if (cp < res) | 5334 | if (cp < res) |
| 4775 | cp = slashp; /* the absolute name begins with "/.." */ | 5335 | cp = slashp; /* the absolute name begins with "/.." */ |
| 4776 | #ifdef DOS_NT | 5336 | #ifdef DOS_NT |
| @@ -4794,12 +5354,6 @@ absolute_filename (file, cwd) | |||
| 4794 | slashp = etags_strchr (slashp + 1, '/'); | 5354 | slashp = etags_strchr (slashp + 1, '/'); |
| 4795 | } | 5355 | } |
| 4796 | 5356 | ||
| 4797 | #ifdef DOS_NT | ||
| 4798 | /* Canonicalize drive letter case. */ | ||
| 4799 | if (res[0] && islower (res[0])) | ||
| 4800 | res[0] = toupper (res[0]); | ||
| 4801 | #endif | ||
| 4802 | |||
| 4803 | if (res[0] == '\0') | 5357 | if (res[0] == '\0') |
| 4804 | return savestr ("/"); | 5358 | return savestr ("/"); |
| 4805 | else | 5359 | else |
| @@ -4807,42 +5361,68 @@ absolute_filename (file, cwd) | |||
| 4807 | } | 5361 | } |
| 4808 | 5362 | ||
| 4809 | /* Return a newly allocated string containing the absolute | 5363 | /* Return a newly allocated string containing the absolute |
| 4810 | file name of dir where FILE resides given CWD (which should | 5364 | file name of dir where FILE resides given DIR (which should |
| 4811 | end with a slash). */ | 5365 | end with a slash). */ |
| 4812 | char * | 5366 | char * |
| 4813 | absolute_dirname (file, cwd) | 5367 | absolute_dirname (file, dir) |
| 4814 | char *file, *cwd; | 5368 | char *file, *dir; |
| 4815 | { | 5369 | { |
| 4816 | char *slashp, *res; | 5370 | char *slashp, *res; |
| 4817 | char save; | 5371 | char save; |
| 4818 | #ifdef DOS_NT | ||
| 4819 | char *p; | ||
| 4820 | |||
| 4821 | for (p = file; *p != '\0'; p++) | ||
| 4822 | if (*p == '\\') | ||
| 4823 | *p = '/'; | ||
| 4824 | #endif | ||
| 4825 | 5372 | ||
| 5373 | canonicalize_filename (file); | ||
| 4826 | slashp = etags_strrchr (file, '/'); | 5374 | slashp = etags_strrchr (file, '/'); |
| 4827 | if (slashp == NULL) | 5375 | if (slashp == NULL) |
| 4828 | return savestr (cwd); | 5376 | return savestr (dir); |
| 4829 | save = slashp[1]; | 5377 | save = slashp[1]; |
| 4830 | slashp[1] = '\0'; | 5378 | slashp[1] = '\0'; |
| 4831 | res = absolute_filename (file, cwd); | 5379 | res = absolute_filename (file, dir); |
| 4832 | slashp[1] = save; | 5380 | slashp[1] = save; |
| 4833 | 5381 | ||
| 4834 | return res; | 5382 | return res; |
| 4835 | } | 5383 | } |
| 4836 | 5384 | ||
| 5385 | /* Whether the argument string is an absolute file name. The argument | ||
| 5386 | string must have been canonicalized with canonicalize_filename. */ | ||
| 5387 | bool | ||
| 5388 | filename_is_absolute (fn) | ||
| 5389 | char *fn; | ||
| 5390 | { | ||
| 5391 | return (fn[0] == '/' | ||
| 5392 | #ifdef DOS_NT | ||
| 5393 | || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/') | ||
| 5394 | #endif | ||
| 5395 | ); | ||
| 5396 | } | ||
| 5397 | |||
| 5398 | /* Translate backslashes into slashes. Works in place. */ | ||
| 5399 | void | ||
| 5400 | canonicalize_filename (fn) | ||
| 5401 | register char *fn; | ||
| 5402 | { | ||
| 5403 | #ifdef DOS_NT | ||
| 5404 | /* Convert backslashes to slashes. */ | ||
| 5405 | for (; *fn != '\0'; fn++) | ||
| 5406 | if (*fn == '\\') | ||
| 5407 | *fn = '/'; | ||
| 5408 | /* Canonicalize drive letter case. */ | ||
| 5409 | if (islower (path[0])) | ||
| 5410 | path[0] = toupper (path[0]); | ||
| 5411 | #else | ||
| 5412 | /* No action. */ | ||
| 5413 | fn = NULL; /* shut up the compiler */ | ||
| 5414 | #endif | ||
| 5415 | } | ||
| 5416 | |||
| 4837 | /* Increase the size of a linebuffer. */ | 5417 | /* Increase the size of a linebuffer. */ |
| 4838 | void | 5418 | void |
| 4839 | grow_linebuffer (bufp, toksize) | 5419 | grow_linebuffer (lbp, toksize) |
| 4840 | struct linebuffer *bufp; | 5420 | linebuffer *lbp; |
| 4841 | int toksize; | 5421 | int toksize; |
| 4842 | { | 5422 | { |
| 4843 | while (bufp->size < toksize) | 5423 | while (lbp->size < toksize) |
| 4844 | bufp->size *= 2; | 5424 | lbp->size *= 2; |
| 4845 | bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size); | 5425 | lbp->buffer = xrnew (lbp->buffer, lbp->size, char); |
| 4846 | } | 5426 | } |
| 4847 | 5427 | ||
| 4848 | /* Like malloc but get fatal error if memory is exhausted. */ | 5428 | /* Like malloc but get fatal error if memory is exhausted. */ |