diff options
| author | Francesco Potortì | 2002-04-15 14:18:47 +0000 |
|---|---|---|
| committer | Francesco Potortì | 2002-04-15 14:18:47 +0000 |
| commit | 9e0a3f98766d3828cb08374e474fdfd5d7ec2188 (patch) | |
| tree | 63df83ab9c7e6c0c4126d12b26d26d1de3360b84 | |
| parent | c150db2349b25b552c6a5419e9dd21504a25e6b3 (diff) | |
| download | emacs-9e0a3f98766d3828cb08374e474fdfd5d7ec2188.tar.gz emacs-9e0a3f98766d3828cb08374e474fdfd5d7ec2188.zip | |
Avoid doubly tagging parse.y when both parse.c and parse.y are given on
the command line, in either order.
* etags.c (find_entries): Delete tags previously obtained from
file xxx.c's #line directives when parsing file xxx.y. This is
generally done for automatically generated files containing
#line directives. This handles the case when xxx.y is tagged
before xxx.c, and the entries of xxx.c pointing to xxx.y should
be discarded.
(language): Added the metasource member. Initializers changed.
(invalidate_nodes): New function.
(readline): Discard lines after having found a #line
directive pointing to an already tagged file. This handles the
case when xxx.y is tagged before xxx.c, and the entries of
xxx.c pointing to xxx.y should be discarded.
(fdesc): New structure for keeping track of input files.
(fdesc): Remove `file' member (a string) and use instead a pointer
to a file description structure.
(curfile, curfiledir, curtagfname, curlang, nocharno,
forced_lang): Global variables removed in favor of fdhead and
curfdp, pointers to file description strucures.
(longopts, main, print_help): Use the CTAGS conditional to include
or exclude options that work on etags or ctags only.
(process_file, find_entries, pfnote, add_node, put_entries,
readline): Use fdhead and curfdp.
(process_file, find_entries): Do not take an arg string, all
callers changed.
* etags.c (longopts, print_help, main): Test CTAGS to disallow
options that are not right for either etags or ctags.
* etags.c (number_len, total_size_of_entries): Define them also
in CTAGS mode, because gcc does not compile all refs away.
| -rw-r--r-- | lib-src/etags.c | 774 |
1 files changed, 465 insertions, 309 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c index 3632e230f2d..5fd45e21fab 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*- | 1 | /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*- |
| 2 | Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001 | 2 | Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002 |
| 3 | Free Software Foundation, Inc. and Ken Arnold | 3 | Free Software Foundation, Inc. and Ken Arnold |
| 4 | 4 | ||
| 5 | This file is not considered part of GNU Emacs. | 5 | This file is not considered part of GNU Emacs. |
| @@ -33,7 +33,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| 33 | * Francesco Potortì <pot@gnu.org> has maintained it since 1993. | 33 | * Francesco Potortì <pot@gnu.org> has maintained it since 1993. |
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | char pot_etags_version[] = "@(#) pot revision number is 15.2"; | 36 | char pot_etags_version[] = "@(#) pot revision number is 15.10"; |
| 37 | 37 | ||
| 38 | #define TRUE 1 | 38 | #define TRUE 1 |
| 39 | #define FALSE 0 | 39 | #define FALSE 0 |
| @@ -228,29 +228,43 @@ typedef void Lang_function __P((FILE *)); | |||
| 228 | 228 | ||
| 229 | typedef struct | 229 | typedef struct |
| 230 | { | 230 | { |
| 231 | char *suffix; | 231 | char *suffix; /* file name suffix for this compressor */ |
| 232 | char *command; /* Takes one arg and decompresses to stdout */ | 232 | char *command; /* takes one arg and decompresses to stdout */ |
| 233 | } compressor; | 233 | } compressor; |
| 234 | 234 | ||
| 235 | typedef struct | 235 | typedef struct |
| 236 | { | 236 | { |
| 237 | char *name; | 237 | char *name; /* language name */ |
| 238 | Lang_function *function; | 238 | bool metasource; /* source used to generate other sources */ |
| 239 | char **filenames; | 239 | Lang_function *function; /* parse function */ |
| 240 | char **suffixes; | 240 | char **filenames; /* names of this language's files */ |
| 241 | char **interpreters; | 241 | char **suffixes; /* name suffixes of this language's files */ |
| 242 | char **interpreters; /* interpreters for this language */ | ||
| 242 | } language; | 243 | } language; |
| 243 | 244 | ||
| 245 | typedef struct fdesc | ||
| 246 | { | ||
| 247 | struct fdesc *next; /* for the linked list */ | ||
| 248 | char *infname; /* uncompressed input file name */ | ||
| 249 | char *infabsname; /* absolute uncompressed input file name */ | ||
| 250 | char *infabsdir; /* absolute dir of input file */ | ||
| 251 | char *taggedfname; /* file name to write in tagfile */ | ||
| 252 | language *lang; /* language of file */ | ||
| 253 | char *prop; /* file properties to write in tagfile */ | ||
| 254 | bool usecharno; /* etags tags shall contain char number */ | ||
| 255 | } fdesc; | ||
| 256 | |||
| 244 | typedef struct node_st | 257 | typedef struct node_st |
| 245 | { /* sorting structure */ | 258 | { /* sorting structure */ |
| 246 | char *name; /* function or type name */ | 259 | struct node_st *left, *right; /* left and right sons */ |
| 247 | char *file; /* file name */ | 260 | fdesc *fdp; /* description of file to whom tag belongs */ |
| 248 | bool is_func; /* use pattern or line no */ | 261 | char *name; /* tag name */ |
| 249 | bool been_warned; /* set if noticed dup */ | 262 | char *pat; /* search pattern */ |
| 250 | int lno; /* line number tag is on */ | 263 | bool valid; /* write this tag on the tag file */ |
| 264 | bool is_func; /* function tag: use pattern in CTAGS mode */ | ||
| 265 | bool been_warned; /* warning already given for duplicated tag */ | ||
| 266 | int lno; /* line number tag is on */ | ||
| 251 | long cno; /* character number line starts on */ | 267 | long cno; /* character number line starts on */ |
| 252 | char *pat; /* search pattern */ | ||
| 253 | struct node_st *left, *right; /* left and right sons */ | ||
| 254 | } node; | 268 | } node; |
| 255 | 269 | ||
| 256 | /* | 270 | /* |
| @@ -267,6 +281,35 @@ typedef struct | |||
| 267 | char *buffer; | 281 | char *buffer; |
| 268 | } linebuffer; | 282 | } linebuffer; |
| 269 | 283 | ||
| 284 | /* Used to support mixing of --lang and file names. */ | ||
| 285 | typedef struct | ||
| 286 | { | ||
| 287 | enum { | ||
| 288 | at_language, /* a language specification */ | ||
| 289 | at_regexp, /* a regular expression */ | ||
| 290 | at_icregexp, /* same, but with case ignored */ | ||
| 291 | at_filename /* a file name */ | ||
| 292 | } arg_type; /* argument type */ | ||
| 293 | language *lang; /* language associated with the argument */ | ||
| 294 | char *what; /* the argument itself */ | ||
| 295 | } argument; | ||
| 296 | |||
| 297 | #ifdef ETAGS_REGEXPS | ||
| 298 | /* Structure defining a regular expression. */ | ||
| 299 | typedef struct pattern | ||
| 300 | { | ||
| 301 | struct pattern *p_next; | ||
| 302 | language *lang; | ||
| 303 | char *regex; | ||
| 304 | struct re_pattern_buffer *pat; | ||
| 305 | struct re_registers regs; | ||
| 306 | char *name_pattern; | ||
| 307 | bool error_signaled; | ||
| 308 | bool ignore_case; | ||
| 309 | } pattern; | ||
| 310 | #endif /* ETAGS_REGEXPS */ | ||
| 311 | |||
| 312 | |||
| 270 | /* Many compilers barf on this: | 313 | /* Many compilers barf on this: |
| 271 | Lang_function Ada_funcs; | 314 | Lang_function Ada_funcs; |
| 272 | so let's write it this way */ | 315 | so let's write it this way */ |
| @@ -322,11 +365,12 @@ static void add_node __P((node *, node **)); | |||
| 322 | 365 | ||
| 323 | static void init __P((void)); | 366 | static void init __P((void)); |
| 324 | static void initbuffer __P((linebuffer *)); | 367 | static void initbuffer __P((linebuffer *)); |
| 325 | static void find_entries __P((char *, FILE *)); | 368 | static void process_file __P((char *, language *)); |
| 369 | static void find_entries __P((FILE *)); | ||
| 326 | static void free_tree __P((node *)); | 370 | static void free_tree __P((node *)); |
| 327 | static void pfnote __P((char *, bool, char *, int, int, long)); | 371 | static void pfnote __P((char *, bool, char *, int, int, long)); |
| 328 | static void new_pfnote __P((char *, int, bool, char *, int, int, long)); | 372 | static void new_pfnote __P((char *, int, bool, char *, int, int, long)); |
| 329 | static void process_file __P((char *)); | 373 | static void invalidate_nodes __P((fdesc *, node *)); |
| 330 | static void put_entries __P((node *)); | 374 | static void put_entries __P((node *)); |
| 331 | 375 | ||
| 332 | static char *concat __P((char *, char *, char *)); | 376 | static char *concat __P((char *, char *, char *)); |
| @@ -355,19 +399,16 @@ static char *cwd; /* current working directory */ | |||
| 355 | static char *tagfiledir; /* directory of tagfile */ | 399 | static char *tagfiledir; /* directory of tagfile */ |
| 356 | static FILE *tagf; /* ioptr for tags file */ | 400 | static FILE *tagf; /* ioptr for tags file */ |
| 357 | 401 | ||
| 358 | static char *curfile; /* current input uncompressed file name */ | 402 | static fdesc *fdhead; /* head of file description list */ |
| 359 | static char *curfiledir; /* absolute dir of curfile */ | 403 | static fdesc *curfdp; /* current file description */ |
| 360 | static char *curtagfname; /* current file name to write in tagfile */ | ||
| 361 | static language *curlang; /* current language */ | ||
| 362 | |||
| 363 | static int lineno; /* line number of current line */ | 404 | static int lineno; /* line number of current line */ |
| 364 | static long charno; /* current character number */ | 405 | static long charno; /* current character number */ |
| 365 | static long linecharno; /* charno of start of current line */ | 406 | static long linecharno; /* charno of start of current line */ |
| 366 | static char *dbp; /* pointer to start of current tag */ | 407 | static char *dbp; /* pointer to start of current tag */ |
| 367 | static bool nocharno; /* only use line number when making tag */ | 408 | |
| 368 | static const int invalidcharno = -1; | 409 | static const int invalidcharno = -1; |
| 369 | 410 | ||
| 370 | static node *head; /* the head of the binary tree of tags */ | 411 | static node *nodehead; /* the head of the binary tree of tags */ |
| 371 | 412 | ||
| 372 | static linebuffer lb; /* the current line */ | 413 | static linebuffer lb; /* the current line */ |
| 373 | 414 | ||
| @@ -386,7 +427,7 @@ static char | |||
| 386 | *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; | 427 | *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; |
| 387 | 428 | ||
| 388 | static bool append_to_tagfile; /* -a: append to tags */ | 429 | static bool append_to_tagfile; /* -a: append to tags */ |
| 389 | /* The following four default to TRUE for etags, but to FALSE for ctags. */ | 430 | /* The next four default to TRUE for etags, but to FALSE for ctags. */ |
| 390 | static bool typedefs; /* -t: create tags for C and Ada typedefs */ | 431 | static bool typedefs; /* -t: create tags for C and Ada typedefs */ |
| 391 | static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ | 432 | static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ |
| 392 | /* 0 struct/enum/union decls, and C++ */ | 433 | /* 0 struct/enum/union decls, and C++ */ |
| @@ -394,10 +435,10 @@ static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ | |||
| 394 | static bool constantypedefs; /* -d: create tags for C #define, enum */ | 435 | static bool constantypedefs; /* -d: create tags for C #define, enum */ |
| 395 | /* constants and variables. */ | 436 | /* constants and variables. */ |
| 396 | /* -D: opposite of -d. Default under ctags. */ | 437 | /* -D: opposite of -d. Default under ctags. */ |
| 397 | static bool declarations; /* --declarations: tag them and extern in C&Co*/ | ||
| 398 | static bool globals; /* create tags for global variables */ | 438 | static bool globals; /* create tags for global variables */ |
| 399 | static bool no_line_directive; /* ignore #line directives */ | 439 | static bool declarations; /* --declarations: tag them and extern in C&Co*/ |
| 400 | static bool members; /* create tags for C member variables */ | 440 | static bool members; /* create tags for C member variables */ |
| 441 | static bool no_line_directive; /* ignore #line directives */ | ||
| 401 | static bool update; /* -u: update tags */ | 442 | static bool update; /* -u: update tags */ |
| 402 | static bool vgrind_style; /* -v: create vgrind style index output */ | 443 | static bool vgrind_style; /* -v: create vgrind style index output */ |
| 403 | static bool no_warnings; /* -w: suppress warnings */ | 444 | static bool no_warnings; /* -w: suppress warnings */ |
| @@ -406,66 +447,58 @@ static bool cplusplus; /* .[hc] means C++, not C */ | |||
| 406 | static bool noindentypedefs; /* -I: ignore indentation in C */ | 447 | static bool noindentypedefs; /* -I: ignore indentation in C */ |
| 407 | static bool packages_only; /* --packages-only: in Ada, only tag packages*/ | 448 | static bool packages_only; /* --packages-only: in Ada, only tag packages*/ |
| 408 | 449 | ||
| 450 | #ifdef ETAGS_REGEXPS | ||
| 451 | /* List of all regexps. */ | ||
| 452 | static pattern *p_head; | ||
| 453 | |||
| 454 | /* How many characters in the character set. (From regex.c.) */ | ||
| 455 | #define CHAR_SET_SIZE 256 | ||
| 456 | /* Translation table for case-insensitive matching. */ | ||
| 457 | static char lc_trans[CHAR_SET_SIZE]; | ||
| 458 | #endif /* ETAGS_REGEXPS */ | ||
| 459 | |||
| 409 | #ifdef LONG_OPTIONS | 460 | #ifdef LONG_OPTIONS |
| 410 | static struct option longopts[] = | 461 | static struct option longopts[] = |
| 411 | { | 462 | { |
| 412 | { "packages-only", no_argument, &packages_only, TRUE }, | 463 | { "packages-only", no_argument, &packages_only, TRUE }, |
| 413 | { "append", no_argument, NULL, 'a' }, | ||
| 414 | { "backward-search", no_argument, NULL, 'B' }, | ||
| 415 | { "c++", no_argument, NULL, 'C' }, | 464 | { "c++", no_argument, NULL, 'C' }, |
| 416 | { "cxref", no_argument, NULL, 'x' }, | ||
| 417 | { "defines", no_argument, NULL, 'd' }, | ||
| 418 | { "declarations", no_argument, &declarations, TRUE }, | 465 | { "declarations", no_argument, &declarations, TRUE }, |
| 419 | { "no-defines", no_argument, NULL, 'D' }, | ||
| 420 | { "globals", no_argument, &globals, TRUE }, | ||
| 421 | { "no-globals", no_argument, &globals, FALSE }, | ||
| 422 | { "no-line-directive", no_argument, &no_line_directive, TRUE }, | 466 | { "no-line-directive", no_argument, &no_line_directive, TRUE }, |
| 423 | { "help", no_argument, NULL, 'h' }, | 467 | { "help", no_argument, NULL, 'h' }, |
| 424 | { "help", no_argument, NULL, 'H' }, | 468 | { "help", no_argument, NULL, 'H' }, |
| 425 | { "ignore-indentation", no_argument, NULL, 'I' }, | 469 | { "ignore-indentation", no_argument, NULL, 'I' }, |
| 426 | { "include", required_argument, NULL, 'i' }, | ||
| 427 | { "language", required_argument, NULL, 'l' }, | 470 | { "language", required_argument, NULL, 'l' }, |
| 428 | { "members", no_argument, &members, TRUE }, | 471 | { "members", no_argument, &members, TRUE }, |
| 429 | { "no-members", no_argument, &members, FALSE }, | 472 | { "no-members", no_argument, &members, FALSE }, |
| 430 | { "no-warn", no_argument, NULL, 'w' }, | ||
| 431 | { "output", required_argument, NULL, 'o' }, | 473 | { "output", required_argument, NULL, 'o' }, |
| 432 | #ifdef ETAGS_REGEXPS | 474 | #ifdef ETAGS_REGEXPS |
| 433 | { "regex", required_argument, NULL, 'r' }, | 475 | { "regex", required_argument, NULL, 'r' }, |
| 434 | { "no-regex", no_argument, NULL, 'R' }, | 476 | { "no-regex", no_argument, NULL, 'R' }, |
| 435 | { "ignore-case-regex", required_argument, NULL, 'c' }, | 477 | { "ignore-case-regex", required_argument, NULL, 'c' }, |
| 436 | #endif /* ETAGS_REGEXPS */ | 478 | #endif /* ETAGS_REGEXPS */ |
| 479 | { "version", no_argument, NULL, 'V' }, | ||
| 480 | |||
| 481 | #if CTAGS /* Etags options */ | ||
| 482 | { "backward-search", no_argument, NULL, 'B' }, | ||
| 483 | { "cxref", no_argument, NULL, 'x' }, | ||
| 484 | { "defines", no_argument, NULL, 'd' }, | ||
| 485 | { "globals", no_argument, &globals, TRUE }, | ||
| 437 | { "typedefs", no_argument, NULL, 't' }, | 486 | { "typedefs", no_argument, NULL, 't' }, |
| 438 | { "typedefs-and-c++", no_argument, NULL, 'T' }, | 487 | { "typedefs-and-c++", no_argument, NULL, 'T' }, |
| 439 | { "update", no_argument, NULL, 'u' }, | 488 | { "update", no_argument, NULL, 'u' }, |
| 440 | { "version", no_argument, NULL, 'V' }, | ||
| 441 | { "vgrind", no_argument, NULL, 'v' }, | 489 | { "vgrind", no_argument, NULL, 'v' }, |
| 490 | { "no-warn", no_argument, NULL, 'w' }, | ||
| 491 | |||
| 492 | #else /* Ctags options */ | ||
| 493 | { "append", no_argument, NULL, 'a' }, | ||
| 494 | { "no-defines", no_argument, NULL, 'D' }, | ||
| 495 | { "no-globals", no_argument, &globals, FALSE }, | ||
| 496 | { "include", required_argument, NULL, 'i' }, | ||
| 497 | #endif | ||
| 442 | { NULL } | 498 | { NULL } |
| 443 | }; | 499 | }; |
| 444 | #endif /* LONG_OPTIONS */ | 500 | #endif /* LONG_OPTIONS */ |
| 445 | 501 | ||
| 446 | #ifdef ETAGS_REGEXPS | ||
| 447 | /* Structure defining a regular expression. Elements are | ||
| 448 | the compiled pattern, and the name string. */ | ||
| 449 | typedef struct pattern | ||
| 450 | { | ||
| 451 | struct pattern *p_next; | ||
| 452 | language *lang; | ||
| 453 | char *regex; | ||
| 454 | struct re_pattern_buffer *pat; | ||
| 455 | struct re_registers regs; | ||
| 456 | char *name_pattern; | ||
| 457 | bool error_signaled; | ||
| 458 | } pattern; | ||
| 459 | |||
| 460 | /* List of all regexps. */ | ||
| 461 | static pattern *p_head = NULL; | ||
| 462 | |||
| 463 | /* How many characters in the character set. (From regex.c.) */ | ||
| 464 | #define CHAR_SET_SIZE 256 | ||
| 465 | /* Translation table for case-insensitive matching. */ | ||
| 466 | static char lc_trans[CHAR_SET_SIZE]; | ||
| 467 | #endif /* ETAGS_REGEXPS */ | ||
| 468 | |||
| 469 | static compressor compressors[] = | 502 | static compressor compressors[] = |
| 470 | { | 503 | { |
| 471 | { "z", "gzip -d -c"}, | 504 | { "z", "gzip -d -c"}, |
| @@ -480,9 +513,6 @@ static compressor compressors[] = | |||
| 480 | * Language stuff. | 513 | * Language stuff. |
| 481 | */ | 514 | */ |
| 482 | 515 | ||
| 483 | /* Non-NULL if language fixed. */ | ||
| 484 | static language *forced_lang = NULL; | ||
| 485 | |||
| 486 | /* Ada code */ | 516 | /* Ada code */ |
| 487 | static char *Ada_suffixes [] = | 517 | static char *Ada_suffixes [] = |
| 488 | { "ads", "adb", "ada", NULL }; | 518 | { "ads", "adb", "ada", NULL }; |
| @@ -582,31 +612,31 @@ static char *Yacc_suffixes [] = | |||
| 582 | 612 | ||
| 583 | static language lang_names [] = | 613 | static language lang_names [] = |
| 584 | { | 614 | { |
| 585 | { "ada", Ada_funcs, NULL, Ada_suffixes, NULL }, | 615 | { "ada", FALSE, Ada_funcs, NULL, Ada_suffixes, NULL }, |
| 586 | { "asm", Asm_labels, NULL, Asm_suffixes, NULL }, | 616 | { "asm", FALSE, Asm_labels, NULL, Asm_suffixes, NULL }, |
| 587 | { "c", default_C_entries, NULL, default_C_suffixes, NULL }, | 617 | { "c", FALSE, default_C_entries, NULL, default_C_suffixes, NULL }, |
| 588 | { "c++", Cplusplus_entries, NULL, Cplusplus_suffixes, NULL }, | 618 | { "c++", FALSE, Cplusplus_entries, NULL, Cplusplus_suffixes, NULL }, |
| 589 | { "c*", Cstar_entries, NULL, Cstar_suffixes, NULL }, | 619 | { "c*", FALSE, Cstar_entries, NULL, Cstar_suffixes, NULL }, |
| 590 | { "cobol", Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, | 620 | { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, |
| 591 | { "erlang", Erlang_functions, NULL, Erlang_suffixes, NULL }, | 621 | { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL }, |
| 592 | { "fortran", Fortran_functions, NULL, Fortran_suffixes, NULL }, | 622 | { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL }, |
| 593 | { "java", Cjava_entries, NULL, Cjava_suffixes, NULL }, | 623 | { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL }, |
| 594 | { "lisp", Lisp_functions, NULL, Lisp_suffixes, NULL }, | 624 | { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL }, |
| 595 | { "makefile", Makefile_targets, Makefile_filenames, NULL, NULL }, | 625 | { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL }, |
| 596 | { "pascal", Pascal_functions, NULL, Pascal_suffixes, NULL }, | 626 | { "pascal", FALSE, Pascal_functions, NULL, Pascal_suffixes, NULL }, |
| 597 | { "perl", Perl_functions, NULL, Perl_suffixes, Perl_interpreters }, | 627 | { "perl", FALSE, Perl_functions,NULL, Perl_suffixes, Perl_interpreters }, |
| 598 | { "php", PHP_functions, NULL, PHP_suffixes, NULL }, | 628 | { "php", FALSE, PHP_functions, NULL, PHP_suffixes, NULL }, |
| 599 | { "postscript", Postscript_functions, NULL, Postscript_suffixes, NULL }, | 629 | { "postscript",FALSE, Postscript_functions,NULL, Postscript_suffixes, NULL }, |
| 600 | { "proc", plain_C_entries, NULL, plain_C_suffixes, NULL }, | 630 | { "proc", FALSE, plain_C_entries, NULL, plain_C_suffixes, NULL }, |
| 601 | { "prolog", Prolog_functions, NULL, Prolog_suffixes, NULL }, | 631 | { "prolog", FALSE, Prolog_functions, NULL, Prolog_suffixes, NULL }, |
| 602 | { "python", Python_functions, NULL, Python_suffixes, NULL }, | 632 | { "python", FALSE, Python_functions, NULL, Python_suffixes, NULL }, |
| 603 | { "scheme", Scheme_functions, NULL, Scheme_suffixes, NULL }, | 633 | { "scheme", FALSE, Scheme_functions, NULL, Scheme_suffixes, NULL }, |
| 604 | { "tex", TeX_commands, NULL, TeX_suffixes, NULL }, | 634 | { "tex", FALSE, TeX_commands, NULL, TeX_suffixes, NULL }, |
| 605 | { "texinfo", Texinfo_nodes, NULL, Texinfo_suffixes, NULL }, | 635 | { "texinfo", FALSE, Texinfo_nodes, NULL, Texinfo_suffixes, NULL }, |
| 606 | { "yacc", Yacc_entries, NULL, Yacc_suffixes, NULL }, | 636 | { "yacc", TRUE, Yacc_entries, NULL, Yacc_suffixes, NULL }, |
| 607 | { "auto", NULL }, /* default guessing scheme */ | 637 | { "auto", FALSE, NULL }, /* default guessing scheme */ |
| 608 | { "none", just_read_file }, /* regexp matching only */ | 638 | { "none", FALSE, just_read_file }, /* regexp matching only */ |
| 609 | { NULL, NULL } /* end of list */ | 639 | { NULL, FALSE, NULL } /* end of list */ |
| 610 | }; | 640 | }; |
| 611 | 641 | ||
| 612 | 642 | ||
| @@ -649,7 +679,7 @@ static void | |||
| 649 | print_version () | 679 | print_version () |
| 650 | { | 680 | { |
| 651 | printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION); | 681 | printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION); |
| 652 | puts ("Copyright (C) 1999 Free Software Foundation, Inc. and Ken Arnold"); | 682 | puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold"); |
| 653 | puts ("This program is distributed under the same terms as Emacs"); | 683 | puts ("This program is distributed under the same terms as Emacs"); |
| 654 | 684 | ||
| 655 | exit (GOOD); | 685 | exit (GOOD); |
| @@ -667,17 +697,16 @@ These are the options accepted by %s.\n", progname, progname); | |||
| 667 | puts ("Long option names do not work with this executable, as it is not\n\ | 697 | puts ("Long option names do not work with this executable, as it is not\n\ |
| 668 | linked with GNU getopt."); | 698 | linked with GNU getopt."); |
| 669 | #endif /* LONG_OPTIONS */ | 699 | #endif /* LONG_OPTIONS */ |
| 670 | puts ("A - as file name means read names from stdin (one per line)."); | 700 | puts (" A - as file name means read names from stdin (one per line).\n\ |
| 671 | if (!CTAGS) | 701 | Absolute names are stored in the output file as they are.\n\ |
| 672 | printf (" Absolute names are stored in the output file as they are.\n\ | 702 | Relative ones are stored relative to the output file's directory.\n"); |
| 673 | Relative ones are stored relative to the output file's directory."); | ||
| 674 | puts ("\n"); | ||
| 675 | 703 | ||
| 676 | puts ("-a, --append\n\ | 704 | if (!CTAGS) |
| 705 | puts ("-a, --append\n\ | ||
| 677 | Append tag entries to existing tags file."); | 706 | Append tag entries to existing tags file."); |
| 678 | 707 | ||
| 679 | puts ("--packages-only\n\ | 708 | puts ("--packages-only\n\ |
| 680 | For Ada files, only generate tags for packages ."); | 709 | For Ada files, only generate tags for packages."); |
| 681 | 710 | ||
| 682 | if (CTAGS) | 711 | if (CTAGS) |
| 683 | puts ("-B, --backward-search\n\ | 712 | puts ("-B, --backward-search\n\ |
| @@ -709,15 +738,14 @@ Relative ones are stored relative to the output file's directory."); | |||
| 709 | This makes the tags file smaller."); | 738 | This makes the tags file smaller."); |
| 710 | 739 | ||
| 711 | if (!CTAGS) | 740 | if (!CTAGS) |
| 712 | { | 741 | puts ("-i FILE, --include=FILE\n\ |
| 713 | puts ("-i FILE, --include=FILE\n\ | ||
| 714 | Include a note in tag file indicating that, when searching for\n\ | 742 | Include a note in tag file indicating that, when searching for\n\ |
| 715 | a tag, one should also consult the tags file FILE after\n\ | 743 | a tag, one should also consult the tags file FILE after\n\ |
| 716 | checking the current file."); | 744 | checking the current file."); |
| 717 | puts ("-l LANG, --language=LANG\n\ | 745 | |
| 746 | puts ("-l LANG, --language=LANG\n\ | ||
| 718 | Force the following files to be considered as written in the\n\ | 747 | Force the following files to be considered as written in the\n\ |
| 719 | named language up to the next --language=LANG option."); | 748 | named language up to the next --language=LANG option."); |
| 720 | } | ||
| 721 | 749 | ||
| 722 | if (CTAGS) | 750 | if (CTAGS) |
| 723 | puts ("--globals\n\ | 751 | puts ("--globals\n\ |
| @@ -758,13 +786,19 @@ Relative ones are stored relative to the output file's directory."); | |||
| 758 | puts ("-T, --typedefs-and-c++\n\ | 786 | puts ("-T, --typedefs-and-c++\n\ |
| 759 | Generate tag entries for C typedefs, C struct/enum/union tags,\n\ | 787 | Generate tag entries for C typedefs, C struct/enum/union tags,\n\ |
| 760 | and C++ member functions."); | 788 | and C++ member functions."); |
| 761 | puts ("-u, --update\n\ | 789 | } |
| 790 | |||
| 791 | if (CTAGS) | ||
| 792 | puts ("-u, --update\n\ | ||
| 762 | Update the tag entries for the given files, leaving tag\n\ | 793 | Update the tag entries for the given files, leaving tag\n\ |
| 763 | entries for other files in place. Currently, this is\n\ | 794 | entries for other files in place. Currently, this is\n\ |
| 764 | implemented by deleting the existing entries for the given\n\ | 795 | implemented by deleting the existing entries for the given\n\ |
| 765 | files and then rewriting the new entries at the end of the\n\ | 796 | files and then rewriting the new entries at the end of the\n\ |
| 766 | tags file. It is often faster to simply rebuild the entire\n\ | 797 | tags file. It is often faster to simply rebuild the entire\n\ |
| 767 | tag file than to use this."); | 798 | tag file than to use this."); |
| 799 | |||
| 800 | if (CTAGS) | ||
| 801 | { | ||
| 768 | puts ("-v, --vgrind\n\ | 802 | puts ("-v, --vgrind\n\ |
| 769 | Generates an index of items intended for human consumption,\n\ | 803 | Generates an index of items intended for human consumption,\n\ |
| 770 | similar to the output of vgrind. The index is sorted, and\n\ | 804 | similar to the output of vgrind. The index is sorted, and\n\ |
| @@ -793,22 +827,6 @@ Relative ones are stored relative to the output file's directory."); | |||
| 793 | } | 827 | } |
| 794 | 828 | ||
| 795 | 829 | ||
| 796 | enum argument_type | ||
| 797 | { | ||
| 798 | at_language, | ||
| 799 | at_regexp, | ||
| 800 | at_filename, | ||
| 801 | at_icregexp | ||
| 802 | }; | ||
| 803 | |||
| 804 | /* This structure helps us allow mixing of --lang and file names. */ | ||
| 805 | typedef struct | ||
| 806 | { | ||
| 807 | enum argument_type arg_type; | ||
| 808 | char *what; | ||
| 809 | language *lang; /* language of the regexp */ | ||
| 810 | } argument; | ||
| 811 | |||
| 812 | #ifdef VMS /* VMS specific functions */ | 830 | #ifdef VMS /* VMS specific functions */ |
| 813 | 831 | ||
| 814 | #define EOS '\0' | 832 | #define EOS '\0' |
| @@ -942,7 +960,6 @@ main (argc, argv) | |||
| 942 | int i; | 960 | int i; |
| 943 | unsigned int nincluded_files; | 961 | unsigned int nincluded_files; |
| 944 | char **included_files; | 962 | char **included_files; |
| 945 | char *this_file; | ||
| 946 | argument *argbuffer; | 963 | argument *argbuffer; |
| 947 | int current_arg, file_count; | 964 | int current_arg, file_count; |
| 948 | linebuffer filename_lb; | 965 | linebuffer filename_lb; |
| @@ -981,25 +998,25 @@ main (argc, argv) | |||
| 981 | { | 998 | { |
| 982 | typedefs = typedefs_or_cplusplus = constantypedefs = TRUE; | 999 | typedefs = typedefs_or_cplusplus = constantypedefs = TRUE; |
| 983 | globals = TRUE; | 1000 | globals = TRUE; |
| 984 | declarations = FALSE; | ||
| 985 | members = FALSE; | ||
| 986 | } | 1001 | } |
| 987 | 1002 | ||
| 988 | while (1) | 1003 | while (1) |
| 989 | { | 1004 | { |
| 990 | int opt; | 1005 | int opt; |
| 991 | char *optstring; | 1006 | char *optstring = "-"; |
| 992 | 1007 | ||
| 993 | #ifdef ETAGS_REGEXPS | 1008 | #ifdef ETAGS_REGEXPS |
| 994 | optstring = "-aCdDf:Il:o:r:c:RStTi:BuvxwVhH"; | 1009 | optstring = "-r:Rc:"; |
| 995 | #else | ||
| 996 | optstring = "-aCdDf:Il:o:StTi:BuvxwVhH"; | ||
| 997 | #endif /* ETAGS_REGEXPS */ | 1010 | #endif /* ETAGS_REGEXPS */ |
| 998 | 1011 | ||
| 999 | #ifndef LONG_OPTIONS | 1012 | #ifndef LONG_OPTIONS |
| 1000 | optstring = optstring + 1; | 1013 | optstring = optstring + 1; |
| 1001 | #endif /* LONG_OPTIONS */ | 1014 | #endif /* LONG_OPTIONS */ |
| 1002 | 1015 | ||
| 1016 | optstring = concat (optstring, | ||
| 1017 | "Cf:Il:o:SVhH", | ||
| 1018 | (CTAGS) ? "BxdtTuvw" : "aDi:"); | ||
| 1019 | |||
| 1003 | opt = getopt_long (argc, argv, optstring, longopts, 0); | 1020 | opt = getopt_long (argc, argv, optstring, longopts, 0); |
| 1004 | if (opt == EOF) | 1021 | if (opt == EOF) |
| 1005 | break; | 1022 | break; |
| @@ -1020,10 +1037,7 @@ main (argc, argv) | |||
| 1020 | break; | 1037 | break; |
| 1021 | 1038 | ||
| 1022 | /* Common options. */ | 1039 | /* Common options. */ |
| 1023 | case 'a': append_to_tagfile = TRUE; break; | ||
| 1024 | case 'C': cplusplus = TRUE; break; | 1040 | case 'C': cplusplus = TRUE; break; |
| 1025 | case 'd': constantypedefs = TRUE; break; | ||
| 1026 | case 'D': constantypedefs = FALSE; break; | ||
| 1027 | case 'f': /* for compatibility with old makefiles */ | 1041 | case 'f': /* for compatibility with old makefiles */ |
| 1028 | case 'o': | 1042 | case 'o': |
| 1029 | if (tagfile) | 1043 | if (tagfile) |
| @@ -1070,22 +1084,21 @@ main (argc, argv) | |||
| 1070 | case 'H': | 1084 | case 'H': |
| 1071 | print_help (); | 1085 | print_help (); |
| 1072 | break; | 1086 | break; |
| 1073 | case 't': | 1087 | |
| 1074 | typedefs = TRUE; | ||
| 1075 | break; | ||
| 1076 | case 'T': | ||
| 1077 | typedefs = typedefs_or_cplusplus = TRUE; | ||
| 1078 | break; | ||
| 1079 | /* Etags options */ | 1088 | /* Etags options */ |
| 1080 | case 'i': | 1089 | case 'a': append_to_tagfile = TRUE; break; |
| 1081 | included_files[nincluded_files++] = optarg; | 1090 | case 'D': constantypedefs = FALSE; break; |
| 1082 | break; | 1091 | case 'i': included_files[nincluded_files++] = optarg; break; |
| 1092 | |||
| 1083 | /* Ctags options. */ | 1093 | /* Ctags options. */ |
| 1084 | case 'B': searchar = '?'; break; | 1094 | case 'B': searchar = '?'; break; |
| 1085 | case 'u': update = TRUE; break; | 1095 | case 'd': constantypedefs = TRUE; break; |
| 1086 | case 'v': vgrind_style = TRUE; /*FALLTHRU*/ | 1096 | case 't': typedefs = TRUE; break; |
| 1087 | case 'x': cxref_style = TRUE; break; | 1097 | case 'T': typedefs = typedefs_or_cplusplus = TRUE; break; |
| 1088 | case 'w': no_warnings = TRUE; break; | 1098 | case 'u': update = TRUE; break; |
| 1099 | case 'v': vgrind_style = TRUE; /*FALLTHRU*/ | ||
| 1100 | case 'x': cxref_style = TRUE; break; | ||
| 1101 | case 'w': no_warnings = TRUE; break; | ||
| 1089 | default: | 1102 | default: |
| 1090 | suggest_asking_for_help (); | 1103 | suggest_asking_for_help (); |
| 1091 | } | 1104 | } |
| @@ -1147,10 +1160,13 @@ main (argc, argv) | |||
| 1147 | */ | 1160 | */ |
| 1148 | for (i = 0; i < current_arg; ++i) | 1161 | for (i = 0; i < current_arg; ++i) |
| 1149 | { | 1162 | { |
| 1163 | static language *lang; /* non-NULL if language is forced */ | ||
| 1164 | char *this_file; | ||
| 1165 | |||
| 1150 | switch (argbuffer[i].arg_type) | 1166 | switch (argbuffer[i].arg_type) |
| 1151 | { | 1167 | { |
| 1152 | case at_language: | 1168 | case at_language: |
| 1153 | forced_lang = argbuffer[i].lang; | 1169 | lang = argbuffer[i].lang; |
| 1154 | break; | 1170 | break; |
| 1155 | #ifdef ETAGS_REGEXPS | 1171 | #ifdef ETAGS_REGEXPS |
| 1156 | case at_regexp: | 1172 | case at_regexp: |
| @@ -1180,9 +1196,9 @@ main (argc, argv) | |||
| 1180 | (one per line) and use them. */ | 1196 | (one per line) and use them. */ |
| 1181 | if (streq (this_file, "-")) | 1197 | if (streq (this_file, "-")) |
| 1182 | while (readline_internal (&filename_lb, stdin) > 0) | 1198 | while (readline_internal (&filename_lb, stdin) > 0) |
| 1183 | process_file (filename_lb.buffer); | 1199 | process_file (filename_lb.buffer, lang); |
| 1184 | else | 1200 | else |
| 1185 | process_file (this_file); | 1201 | process_file (this_file, lang); |
| 1186 | #ifdef VMS | 1202 | #ifdef VMS |
| 1187 | } | 1203 | } |
| 1188 | #endif | 1204 | #endif |
| @@ -1196,9 +1212,9 @@ main (argc, argv) | |||
| 1196 | 1212 | ||
| 1197 | if (!CTAGS || cxref_style) | 1213 | if (!CTAGS || cxref_style) |
| 1198 | { | 1214 | { |
| 1199 | put_entries (head); | 1215 | put_entries (nodehead); |
| 1200 | free_tree (head); | 1216 | free_tree (nodehead); |
| 1201 | head = NULL; | 1217 | nodehead = NULL; |
| 1202 | if (!CTAGS) | 1218 | if (!CTAGS) |
| 1203 | while (nincluded_files-- > 0) | 1219 | while (nincluded_files-- > 0) |
| 1204 | fprintf (tagf, "\f\n%s,include\n", *included_files++); | 1220 | fprintf (tagf, "\f\n%s,include\n", *included_files++); |
| @@ -1227,23 +1243,22 @@ main (argc, argv) | |||
| 1227 | tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); | 1243 | tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); |
| 1228 | if (tagf == NULL) | 1244 | if (tagf == NULL) |
| 1229 | pfatal (tagfile); | 1245 | pfatal (tagfile); |
| 1230 | put_entries (head); | 1246 | put_entries (nodehead); |
| 1231 | free_tree (head); | 1247 | free_tree (nodehead); |
| 1232 | head = NULL; | 1248 | nodehead = NULL; |
| 1233 | if (fclose (tagf) == EOF) | 1249 | if (fclose (tagf) == EOF) |
| 1234 | pfatal (tagfile); | 1250 | pfatal (tagfile); |
| 1235 | 1251 | ||
| 1236 | if (update) | 1252 | if (update) |
| 1237 | { | 1253 | { |
| 1238 | char cmd[BUFSIZ]; | 1254 | char cmd[BUFSIZ]; |
| 1239 | sprintf (cmd, "sort -o %s %s", tagfile, tagfile); | 1255 | sprintf (cmd, "sort %s -o %s", tagfile, tagfile); |
| 1240 | exit (system (cmd)); | 1256 | exit (system (cmd)); |
| 1241 | } | 1257 | } |
| 1242 | return GOOD; | 1258 | return GOOD; |
| 1243 | } | 1259 | } |
| 1244 | 1260 | ||
| 1245 | 1261 | ||
| 1246 | |||
| 1247 | /* | 1262 | /* |
| 1248 | * Return a compressor given the file name. If EXTPTR is non-zero, | 1263 | * Return a compressor given the file name. If EXTPTR is non-zero, |
| 1249 | * return a pointer into FILE where the compressor-specific | 1264 | * return a pointer into FILE where the compressor-specific |
| @@ -1362,17 +1377,19 @@ get_language_from_filename (file) | |||
| 1362 | return NULL; | 1377 | return NULL; |
| 1363 | } | 1378 | } |
| 1364 | 1379 | ||
| 1365 | 1380 | ||
| 1366 | |||
| 1367 | /* | 1381 | /* |
| 1368 | * This routine is called on each file argument. | 1382 | * This routine is called on each file argument. |
| 1369 | */ | 1383 | */ |
| 1370 | static void | 1384 | static void |
| 1371 | process_file (file) | 1385 | process_file (file, lang) |
| 1372 | char *file; | 1386 | char *file; |
| 1387 | language *lang; | ||
| 1373 | { | 1388 | { |
| 1374 | struct stat stat_buf; | 1389 | struct stat stat_buf; |
| 1375 | FILE *inf; | 1390 | FILE *inf; |
| 1391 | static const fdesc emptyfdesc; | ||
| 1392 | fdesc *fdp; | ||
| 1376 | compressor *compr; | 1393 | compressor *compr; |
| 1377 | char *compressed_name, *uncompressed_name; | 1394 | char *compressed_name, *uncompressed_name; |
| 1378 | char *ext, *real_name; | 1395 | char *ext, *real_name; |
| @@ -1396,25 +1413,20 @@ process_file (file) | |||
| 1396 | uncompressed_name = savenstr (file, ext - file); | 1413 | uncompressed_name = savenstr (file, ext - file); |
| 1397 | } | 1414 | } |
| 1398 | 1415 | ||
| 1399 | /* If the canonicalized uncompressed name has already be dealt with, | 1416 | /* If the canonicalized uncompressed name |
| 1400 | skip it silently, else add it to the list. */ | 1417 | has already been dealt with, skip it silently. */ |
| 1401 | { | 1418 | for (fdp = fdhead; fdp != NULL; fdp = fdp->next) |
| 1402 | typedef struct processed_file | ||
| 1403 | { | 1419 | { |
| 1404 | char *filename; | 1420 | assert (fdp->infname != NULL); |
| 1405 | struct processed_file *next; | 1421 | if (streq (uncompressed_name, fdp->infname)) |
| 1406 | } processed_file; | 1422 | goto cleanup; |
| 1407 | static processed_file *pf_head = NULL; | 1423 | } |
| 1408 | register processed_file *fnp; | 1424 | |
| 1409 | 1425 | /* Create a new input file description entry. */ | |
| 1410 | for (fnp = pf_head; fnp != NULL; fnp = fnp->next) | 1426 | fdp = fdhead; |
| 1411 | if (streq (uncompressed_name, fnp->filename)) | 1427 | fdhead = xnew (1, fdesc); |
| 1412 | goto exit; | 1428 | *fdhead = emptyfdesc; |
| 1413 | fnp = pf_head; | 1429 | fdhead->next = fdp; |
| 1414 | pf_head = xnew (1, struct processed_file); | ||
| 1415 | pf_head->filename = savestr (uncompressed_name); | ||
| 1416 | pf_head->next = fnp; | ||
| 1417 | } | ||
| 1418 | 1430 | ||
| 1419 | if (stat (real_name, &stat_buf) != 0) | 1431 | if (stat (real_name, &stat_buf) != 0) |
| 1420 | { | 1432 | { |
| @@ -1461,14 +1473,14 @@ process_file (file) | |||
| 1461 | if (real_name == NULL) | 1473 | if (real_name == NULL) |
| 1462 | { | 1474 | { |
| 1463 | perror (file); | 1475 | perror (file); |
| 1464 | goto exit; | 1476 | goto cleanup; |
| 1465 | } | 1477 | } |
| 1466 | } /* try with a different name */ | 1478 | } /* try with a different name */ |
| 1467 | 1479 | ||
| 1468 | if (!S_ISREG (stat_buf.st_mode)) | 1480 | if (!S_ISREG (stat_buf.st_mode)) |
| 1469 | { | 1481 | { |
| 1470 | error ("skipping %s: it is not a regular file.", real_name); | 1482 | error ("skipping %s: it is not a regular file.", real_name); |
| 1471 | goto exit; | 1483 | goto cleanup; |
| 1472 | } | 1484 | } |
| 1473 | if (real_name == compressed_name) | 1485 | if (real_name == compressed_name) |
| 1474 | { | 1486 | { |
| @@ -1481,26 +1493,31 @@ process_file (file) | |||
| 1481 | if (inf == NULL) | 1493 | if (inf == NULL) |
| 1482 | { | 1494 | { |
| 1483 | perror (real_name); | 1495 | perror (real_name); |
| 1484 | goto exit; | 1496 | goto cleanup; |
| 1485 | } | 1497 | } |
| 1486 | 1498 | ||
| 1487 | curfile = uncompressed_name; | 1499 | fdhead->infname = savestr (uncompressed_name); |
| 1488 | curfiledir = absolute_dirname (curfile, cwd); | 1500 | fdhead->lang = lang; |
| 1489 | if (filename_is_absolute (curfile)) | 1501 | fdhead->infabsname = absolute_filename (uncompressed_name, cwd); |
| 1502 | fdhead->infabsdir = absolute_dirname (uncompressed_name, cwd); | ||
| 1503 | if (filename_is_absolute (uncompressed_name)) | ||
| 1490 | { | 1504 | { |
| 1491 | /* file is an absolute file name. Canonicalize it. */ | 1505 | /* file is an absolute file name. Canonicalize it. */ |
| 1492 | curtagfname = absolute_filename (curfile, NULL); | 1506 | fdhead->taggedfname = absolute_filename (uncompressed_name, NULL); |
| 1493 | } | 1507 | } |
| 1494 | else | 1508 | else |
| 1495 | { | 1509 | { |
| 1496 | /* file is a file name relative to cwd. Make it relative | 1510 | /* file is a file name relative to cwd. Make it relative |
| 1497 | to the directory of the tags file. */ | 1511 | to the directory of the tags file. */ |
| 1498 | curtagfname = relative_filename (curfile, tagfiledir); | 1512 | fdhead->taggedfname = relative_filename (uncompressed_name, tagfiledir); |
| 1499 | } | 1513 | } |
| 1500 | nocharno = FALSE; /* use char position when making tags */ | 1514 | fdhead->usecharno = TRUE; /* use char position when making tags */ |
| 1501 | find_entries (curfile, inf); | 1515 | fdhead->prop = NULL; |
| 1516 | |||
| 1517 | curfdp = fdhead; /* the current file description */ | ||
| 1518 | |||
| 1519 | find_entries (inf); | ||
| 1502 | 1520 | ||
| 1503 | free (curfiledir); | ||
| 1504 | if (real_name == compressed_name) | 1521 | if (real_name == compressed_name) |
| 1505 | retval = pclose (inf); | 1522 | retval = pclose (inf); |
| 1506 | else | 1523 | else |
| @@ -1508,9 +1525,10 @@ process_file (file) | |||
| 1508 | if (retval < 0) | 1525 | if (retval < 0) |
| 1509 | pfatal (file); | 1526 | pfatal (file); |
| 1510 | 1527 | ||
| 1511 | exit: | 1528 | cleanup: |
| 1512 | if (compressed_name) free(compressed_name); | 1529 | /* XXX if no more useful, delete head of file description list */ |
| 1513 | if (uncompressed_name) free(uncompressed_name); | 1530 | if (compressed_name) free (compressed_name); |
| 1531 | if (uncompressed_name) free (uncompressed_name); | ||
| 1514 | return; | 1532 | return; |
| 1515 | } | 1533 | } |
| 1516 | 1534 | ||
| @@ -1548,34 +1566,34 @@ init () | |||
| 1548 | static node *last_node = NULL; | 1566 | static node *last_node = NULL; |
| 1549 | 1567 | ||
| 1550 | static void | 1568 | static void |
| 1551 | find_entries (file, inf) | 1569 | find_entries (inf) |
| 1552 | char *file; | ||
| 1553 | FILE *inf; | 1570 | FILE *inf; |
| 1554 | { | 1571 | { |
| 1555 | char *cp; | 1572 | char *cp; |
| 1556 | language *lang; | ||
| 1557 | node *old_last_node; | 1573 | node *old_last_node; |
| 1574 | language *lang = curfdp->lang; | ||
| 1575 | Lang_function *parser = NULL; | ||
| 1558 | 1576 | ||
| 1559 | /* If user specified a language, use it. */ | 1577 | /* If user specified a language, use it. */ |
| 1560 | lang = forced_lang; | ||
| 1561 | if (lang != NULL && lang->function != NULL) | 1578 | if (lang != NULL && lang->function != NULL) |
| 1562 | { | 1579 | { |
| 1563 | curlang = lang; | 1580 | parser = lang->function; |
| 1564 | lang->function (inf); | ||
| 1565 | return; | ||
| 1566 | } | 1581 | } |
| 1567 | 1582 | ||
| 1568 | /* Try to guess the language given the file name. */ | 1583 | /* Else try to guess the language given the file name. */ |
| 1569 | lang = get_language_from_filename (file); | 1584 | if (parser == NULL) |
| 1570 | if (lang != NULL && lang->function != NULL) | ||
| 1571 | { | 1585 | { |
| 1572 | curlang = lang; | 1586 | lang = get_language_from_filename (curfdp->infname); |
| 1573 | lang->function (inf); | 1587 | if (lang != NULL && lang->function != NULL) |
| 1574 | return; | 1588 | { |
| 1589 | curfdp->lang = lang; | ||
| 1590 | parser = lang->function; | ||
| 1591 | } | ||
| 1575 | } | 1592 | } |
| 1576 | 1593 | ||
| 1577 | /* Look for sharp-bang as the first two characters. */ | 1594 | /* Else look for sharp-bang as the first two characters. */ |
| 1578 | if (readline_internal (&lb, inf) > 0 | 1595 | if (parser == NULL |
| 1596 | && readline_internal (&lb, inf) > 0 | ||
| 1579 | && lb.len >= 2 | 1597 | && lb.len >= 2 |
| 1580 | && lb.buffer[0] == '#' | 1598 | && lb.buffer[0] == '#' |
| 1581 | && lb.buffer[1] == '!') | 1599 | && lb.buffer[1] == '!') |
| @@ -1598,29 +1616,72 @@ find_entries (file, inf) | |||
| 1598 | lang = get_language_from_interpreter (lp); | 1616 | lang = get_language_from_interpreter (lp); |
| 1599 | if (lang != NULL && lang->function != NULL) | 1617 | if (lang != NULL && lang->function != NULL) |
| 1600 | { | 1618 | { |
| 1601 | curlang = lang; | 1619 | curfdp->lang = lang; |
| 1602 | lang->function (inf); | 1620 | parser = lang->function; |
| 1603 | return; | ||
| 1604 | } | 1621 | } |
| 1605 | } | 1622 | } |
| 1606 | } | 1623 | } |
| 1624 | |||
| 1625 | if (!no_line_directive | ||
| 1626 | && curfdp->lang != NULL && curfdp->lang->metasource) | ||
| 1627 | /* It may be that this is an xxx.y file, and we already parsed an xxx.c | ||
| 1628 | file, or anyway we parsed a file that is automatically generated from | ||
| 1629 | this one. If this is the case, the xxx.c file contained #line | ||
| 1630 | directives that generated tags pointing to this file. Let's delete | ||
| 1631 | them all before parsing this file, which is the real source. */ | ||
| 1632 | { | ||
| 1633 | fdesc **fdpp = &fdhead; | ||
| 1634 | while (*fdpp != NULL) | ||
| 1635 | if (*fdpp != curfdp | ||
| 1636 | && streq ((*fdpp)->taggedfname, curfdp->taggedfname)) | ||
| 1637 | /* We found one of those! We must delete both the file description | ||
| 1638 | and all tags referring to it. */ | ||
| 1639 | { | ||
| 1640 | fdesc *badfdp = *fdpp; | ||
| 1641 | |||
| 1642 | *fdpp = badfdp->next; /* remove the bad description from the list */ | ||
| 1643 | fdpp = &badfdp->next; /* advance the list pointer */ | ||
| 1644 | |||
| 1645 | fprintf (stderr, "Removing references to \"%s\" obtained from \"%s\"\n", | ||
| 1646 | badfdp->taggedfname, badfdp->infname); | ||
| 1647 | /* Delete the tags referring to badfdp. */ | ||
| 1648 | invalidate_nodes (badfdp, nodehead); | ||
| 1649 | |||
| 1650 | /* Delete badfdp. */ | ||
| 1651 | if (badfdp->infname != NULL) free (badfdp->infname); | ||
| 1652 | if (badfdp->infabsname != NULL) free (badfdp->infabsname); | ||
| 1653 | if (badfdp->infabsdir != NULL) free (badfdp->infabsdir); | ||
| 1654 | if (badfdp->taggedfname != NULL) free (badfdp->taggedfname); | ||
| 1655 | if (badfdp->prop != NULL) free (badfdp->prop); | ||
| 1656 | free (badfdp); | ||
| 1657 | } | ||
| 1658 | else | ||
| 1659 | fdpp = &(*fdpp)->next; /* advance the list pointer */ | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | if (parser != NULL) | ||
| 1663 | { | ||
| 1664 | parser (inf); | ||
| 1665 | return; | ||
| 1666 | } | ||
| 1667 | |||
| 1607 | /* We rewind here, even if inf may be a pipe. We fail if the | 1668 | /* We rewind here, even if inf may be a pipe. We fail if the |
| 1608 | length of the first line is longer than the pipe block size, | 1669 | length of the first line is longer than the pipe block size, |
| 1609 | which is unlikely. */ | 1670 | which is unlikely. */ |
| 1610 | rewind (inf); | 1671 | rewind (inf); |
| 1611 | 1672 | ||
| 1612 | /* Try Fortran. */ | 1673 | /* Else try Fortran. */ |
| 1613 | old_last_node = last_node; | 1674 | old_last_node = last_node; |
| 1614 | curlang = get_language_from_langname ("fortran"); | 1675 | curfdp->lang = get_language_from_langname ("fortran"); |
| 1615 | Fortran_functions (inf); | 1676 | Fortran_functions (inf); |
| 1616 | 1677 | ||
| 1617 | /* No Fortran entries found. Try C. */ | ||
| 1618 | if (old_last_node == last_node) | 1678 | if (old_last_node == last_node) |
| 1679 | /* No Fortran entries found. Try C. */ | ||
| 1619 | { | 1680 | { |
| 1620 | /* We do not tag if rewind fails. | 1681 | /* We do not tag if rewind fails. |
| 1621 | Only the file name will be recorded in the tags file. */ | 1682 | Only the file name will be recorded in the tags file. */ |
| 1622 | rewind (inf); | 1683 | rewind (inf); |
| 1623 | curlang = get_language_from_langname (cplusplus ? "c++" : "c"); | 1684 | curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c"); |
| 1624 | default_C_entries (inf); | 1685 | default_C_entries (inf); |
| 1625 | } | 1686 | } |
| 1626 | return; | 1687 | return; |
| @@ -1647,27 +1708,28 @@ pfnote (name, is_func, linestart, linelen, lno, cno) | |||
| 1647 | /* If ctags mode, change name "main" to M<thisfilename>. */ | 1708 | /* If ctags mode, change name "main" to M<thisfilename>. */ |
| 1648 | if (CTAGS && !cxref_style && streq (name, "main")) | 1709 | if (CTAGS && !cxref_style && streq (name, "main")) |
| 1649 | { | 1710 | { |
| 1650 | register char *fp = etags_strrchr (curtagfname, '/'); | 1711 | register char *fp = etags_strrchr (curfdp->taggedfname, '/'); |
| 1651 | np->name = concat ("M", fp == NULL ? curtagfname : fp + 1, ""); | 1712 | np->name = concat ("M", fp == NULL ? curfdp->taggedfname : fp + 1, ""); |
| 1652 | fp = etags_strrchr (np->name, '.'); | 1713 | fp = etags_strrchr (np->name, '.'); |
| 1653 | if (fp != NULL && fp[1] != '\0' && fp[2] == '\0') | 1714 | if (fp != NULL && fp[1] != '\0' && fp[2] == '\0') |
| 1654 | fp[0] = '\0'; | 1715 | fp[0] = '\0'; |
| 1655 | } | 1716 | } |
| 1656 | else | 1717 | else |
| 1657 | np->name = name; | 1718 | np->name = name; |
| 1719 | np->valid = TRUE; | ||
| 1658 | np->been_warned = FALSE; | 1720 | np->been_warned = FALSE; |
| 1659 | np->file = curtagfname; | 1721 | np->fdp = curfdp; |
| 1660 | np->is_func = is_func; | 1722 | np->is_func = is_func; |
| 1661 | np->lno = lno; | 1723 | np->lno = lno; |
| 1662 | if (nocharno) | 1724 | if (np->fdp->usecharno) |
| 1663 | np->cno = invalidcharno; | ||
| 1664 | else | ||
| 1665 | /* Our char numbers are 0-base, because of C language tradition? | 1725 | /* Our char numbers are 0-base, because of C language tradition? |
| 1666 | ctags compatibility? old versions compatibility? I don't know. | 1726 | ctags compatibility? old versions compatibility? I don't know. |
| 1667 | Anyway, since emacs's are 1-base we expect etags.el to take care | 1727 | Anyway, since emacs's are 1-base we expect etags.el to take care |
| 1668 | of the difference. If we wanted to have 1-based numbers, we would | 1728 | of the difference. If we wanted to have 1-based numbers, we would |
| 1669 | uncomment the +1 below. */ | 1729 | uncomment the +1 below. */ |
| 1670 | np->cno = cno /* + 1 */ ; | 1730 | np->cno = cno /* + 1 */ ; |
| 1731 | else | ||
| 1732 | np->cno = invalidcharno; | ||
| 1671 | np->left = np->right = NULL; | 1733 | np->left = np->right = NULL; |
| 1672 | if (CTAGS && !cxref_style) | 1734 | if (CTAGS && !cxref_style) |
| 1673 | { | 1735 | { |
| @@ -1679,7 +1741,7 @@ pfnote (name, is_func, linestart, linelen, lno, cno) | |||
| 1679 | else | 1741 | else |
| 1680 | np->pat = savenstr (linestart, linelen); | 1742 | np->pat = savenstr (linestart, linelen); |
| 1681 | 1743 | ||
| 1682 | add_node (np, &head); | 1744 | add_node (np, &nodehead); |
| 1683 | } | 1745 | } |
| 1684 | 1746 | ||
| 1685 | /* | 1747 | /* |
| @@ -1789,13 +1851,13 @@ add_node (np, cur_node_p) | |||
| 1789 | pointer. The first tags of different files are a linked list | 1851 | pointer. The first tags of different files are a linked list |
| 1790 | on the left pointer. last_node points to the end of the last | 1852 | on the left pointer. last_node points to the end of the last |
| 1791 | used sublist. */ | 1853 | used sublist. */ |
| 1792 | if (last_node->file == np->file) | 1854 | if (last_node->fdp == np->fdp) |
| 1793 | { | 1855 | { |
| 1794 | /* Let's use the same sublist as the last added node. */ | 1856 | /* Let's use the same sublist as the last added node. */ |
| 1795 | last_node->right = np; | 1857 | last_node->right = np; |
| 1796 | last_node = np; | 1858 | last_node = np; |
| 1797 | } | 1859 | } |
| 1798 | else if (streq (cur_node->file, np->file)) | 1860 | else if (cur_node->fdp == np->fdp) |
| 1799 | { | 1861 | { |
| 1800 | /* Scanning the list we found the head of a sublist which is | 1862 | /* Scanning the list we found the head of a sublist which is |
| 1801 | good for us. Let's scan this sublist. */ | 1863 | good for us. Let's scan this sublist. */ |
| @@ -1817,12 +1879,12 @@ add_node (np, cur_node_p) | |||
| 1817 | */ | 1879 | */ |
| 1818 | if (!dif) | 1880 | if (!dif) |
| 1819 | { | 1881 | { |
| 1820 | if (streq (np->file, cur_node->file)) | 1882 | if (np->fdp == cur_node->fdp) |
| 1821 | { | 1883 | { |
| 1822 | if (!no_warnings) | 1884 | if (!no_warnings) |
| 1823 | { | 1885 | { |
| 1824 | fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n", | 1886 | fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n", |
| 1825 | np->file, lineno, np->name); | 1887 | np->fdp->infname, lineno, np->name); |
| 1826 | fprintf (stderr, "Second entry ignored\n"); | 1888 | fprintf (stderr, "Second entry ignored\n"); |
| 1827 | } | 1889 | } |
| 1828 | } | 1890 | } |
| @@ -1831,7 +1893,7 @@ add_node (np, cur_node_p) | |||
| 1831 | fprintf | 1893 | fprintf |
| 1832 | (stderr, | 1894 | (stderr, |
| 1833 | "Duplicate entry in files %s and %s: %s (Warning only)\n", | 1895 | "Duplicate entry in files %s and %s: %s (Warning only)\n", |
| 1834 | np->file, cur_node->file, np->name); | 1896 | np->fdp->infname, cur_node->fdp->infname, np->name); |
| 1835 | cur_node->been_warned = TRUE; | 1897 | cur_node->been_warned = TRUE; |
| 1836 | } | 1898 | } |
| 1837 | return; | 1899 | return; |
| @@ -1842,11 +1904,29 @@ add_node (np, cur_node_p) | |||
| 1842 | } | 1904 | } |
| 1843 | } | 1905 | } |
| 1844 | 1906 | ||
| 1907 | /* | ||
| 1908 | * invalidate_nodes () | ||
| 1909 | * Scan the node tree and invalidate all nodes pointing to the | ||
| 1910 | * given file description. | ||
| 1911 | */ | ||
| 1912 | static void | ||
| 1913 | invalidate_nodes (badfdp, np) | ||
| 1914 | fdesc *badfdp; | ||
| 1915 | node *np; | ||
| 1916 | { | ||
| 1917 | if (np->left != NULL) | ||
| 1918 | invalidate_nodes (badfdp, np->left); | ||
| 1919 | if (np->fdp == badfdp) | ||
| 1920 | np-> valid = FALSE; | ||
| 1921 | if (np->right != NULL) | ||
| 1922 | invalidate_nodes (badfdp, np->right); | ||
| 1923 | } | ||
| 1924 | |||
| 1845 | 1925 | ||
| 1846 | static int total_size_of_entries __P((node *)); | 1926 | static int total_size_of_entries __P((node *)); |
| 1847 | static int number_len __P((long)); | 1927 | static int number_len __P((long)); |
| 1848 | 1928 | ||
| 1849 | /* Length of a number's decimal representation. */ | 1929 | /* Length of a non-negative number's decimal representation. */ |
| 1850 | static int | 1930 | static int |
| 1851 | number_len (num) | 1931 | number_len (num) |
| 1852 | long num; | 1932 | long num; |
| @@ -1888,7 +1968,7 @@ put_entries (np) | |||
| 1888 | register node *np; | 1968 | register node *np; |
| 1889 | { | 1969 | { |
| 1890 | register char *sp; | 1970 | register char *sp; |
| 1891 | static char *file = NULL; | 1971 | static fdesc *fdp = NULL; |
| 1892 | 1972 | ||
| 1893 | if (np == NULL) | 1973 | if (np == NULL) |
| 1894 | return; | 1974 | return; |
| @@ -1898,69 +1978,69 @@ put_entries (np) | |||
| 1898 | put_entries (np->left); | 1978 | put_entries (np->left); |
| 1899 | 1979 | ||
| 1900 | /* Output this entry */ | 1980 | /* Output this entry */ |
| 1901 | if (!CTAGS) | 1981 | if (np->valid) |
| 1902 | { | 1982 | { |
| 1903 | /* Etags mode */ | 1983 | if (!CTAGS) |
| 1904 | if (file != np->file | ||
| 1905 | && (file == NULL || !streq (file, np->file))) | ||
| 1906 | { | ||
| 1907 | file = np->file; | ||
| 1908 | fprintf (tagf, "\f\n%s,%d\n", | ||
| 1909 | file, total_size_of_entries (np)); | ||
| 1910 | } | ||
| 1911 | fputs (np->pat, tagf); | ||
| 1912 | fputc ('\177', tagf); | ||
| 1913 | if (np->name != NULL) | ||
| 1914 | { | 1984 | { |
| 1915 | fputs (np->name, tagf); | 1985 | /* Etags mode */ |
| 1916 | fputc ('\001', tagf); | 1986 | if (fdp != np->fdp) |
| 1987 | { | ||
| 1988 | fdp = np->fdp; | ||
| 1989 | fprintf (tagf, "\f\n%s,%d\n", | ||
| 1990 | fdp->taggedfname, total_size_of_entries (np)); | ||
| 1991 | } | ||
| 1992 | fputs (np->pat, tagf); | ||
| 1993 | fputc ('\177', tagf); | ||
| 1994 | if (np->name != NULL) | ||
| 1995 | { | ||
| 1996 | fputs (np->name, tagf); | ||
| 1997 | fputc ('\001', tagf); | ||
| 1998 | } | ||
| 1999 | fprintf (tagf, "%d,", np->lno); | ||
| 2000 | if (np->cno != invalidcharno) | ||
| 2001 | fprintf (tagf, "%ld", np->cno); | ||
| 2002 | fputs ("\n", tagf); | ||
| 1917 | } | 2003 | } |
| 1918 | fprintf (tagf, "%d,", np->lno); | ||
| 1919 | if (np->cno == invalidcharno) | ||
| 1920 | fputc ('\n', tagf); | ||
| 1921 | else | 2004 | else |
| 1922 | fprintf (tagf, "%ld\n", np->cno); | ||
| 1923 | } | ||
| 1924 | else | ||
| 1925 | { | ||
| 1926 | /* Ctags mode */ | ||
| 1927 | if (np->name == NULL) | ||
| 1928 | error ("internal error: NULL name in ctags mode.", (char *)NULL); | ||
| 1929 | |||
| 1930 | if (cxref_style) | ||
| 1931 | { | 2005 | { |
| 1932 | if (vgrind_style) | 2006 | /* Ctags mode */ |
| 1933 | fprintf (stdout, "%s %s %d\n", | 2007 | if (np->name == NULL) |
| 1934 | np->name, np->file, (np->lno + 63) / 64); | 2008 | error ("internal error: NULL name in ctags mode.", (char *)NULL); |
| 2009 | |||
| 2010 | if (cxref_style) | ||
| 2011 | { | ||
| 2012 | if (vgrind_style) | ||
| 2013 | fprintf (stdout, "%s %s %d\n", | ||
| 2014 | np->name, np->fdp->taggedfname, (np->lno + 63) / 64); | ||
| 2015 | else | ||
| 2016 | fprintf (stdout, "%-16s %3d %-16s %s\n", | ||
| 2017 | np->name, np->lno, np->fdp->taggedfname, np->pat); | ||
| 2018 | } | ||
| 1935 | else | 2019 | else |
| 1936 | fprintf (stdout, "%-16s %3d %-16s %s\n", | 2020 | { |
| 1937 | np->name, np->lno, np->file, np->pat); | 2021 | fprintf (tagf, "%s\t%s\t", np->name, np->fdp->taggedfname); |
| 1938 | } | ||
| 1939 | else | ||
| 1940 | { | ||
| 1941 | fprintf (tagf, "%s\t%s\t", np->name, np->file); | ||
| 1942 | 2022 | ||
| 1943 | if (np->is_func) | 2023 | if (np->is_func) |
| 1944 | { /* a function */ | 2024 | { /* function or #define macro with args */ |
| 1945 | putc (searchar, tagf); | 2025 | putc (searchar, tagf); |
| 1946 | putc ('^', tagf); | 2026 | putc ('^', tagf); |
| 1947 | 2027 | ||
| 1948 | for (sp = np->pat; *sp; sp++) | 2028 | for (sp = np->pat; *sp; sp++) |
| 1949 | { | 2029 | { |
| 1950 | if (*sp == '\\' || *sp == searchar) | 2030 | if (*sp == '\\' || *sp == searchar) |
| 1951 | putc ('\\', tagf); | 2031 | putc ('\\', tagf); |
| 1952 | putc (*sp, tagf); | 2032 | putc (*sp, tagf); |
| 2033 | } | ||
| 2034 | putc (searchar, tagf); | ||
| 1953 | } | 2035 | } |
| 1954 | putc (searchar, tagf); | 2036 | else |
| 1955 | } | 2037 | { /* anything else; text pattern inadequate */ |
| 1956 | else | 2038 | fprintf (tagf, "%d", np->lno); |
| 1957 | { /* a typedef; text pattern inadequate */ | 2039 | } |
| 1958 | fprintf (tagf, "%d", np->lno); | 2040 | putc ('\n', tagf); |
| 1959 | } | 2041 | } |
| 1960 | putc ('\n', tagf); | ||
| 1961 | } | 2042 | } |
| 1962 | } | 2043 | } /* if this node contains a valid tag */ |
| 1963 | |||
| 1964 | 2044 | ||
| 1965 | /* Output subentries that follow this one */ | 2045 | /* Output subentries that follow this one */ |
| 1966 | put_entries (np->right); | 2046 | put_entries (np->right); |
| @@ -5247,6 +5327,7 @@ add_regex (regexp_pattern, ignore_case, lang) | |||
| 5247 | p_head->pat = patbuf; | 5327 | p_head->pat = patbuf; |
| 5248 | p_head->name_pattern = savestr (name); | 5328 | p_head->name_pattern = savestr (name); |
| 5249 | p_head->error_signaled = FALSE; | 5329 | p_head->error_signaled = FALSE; |
| 5330 | p_head->ignore_case = ignore_case; | ||
| 5250 | } | 5331 | } |
| 5251 | 5332 | ||
| 5252 | /* | 5333 | /* |
| @@ -5444,44 +5525,118 @@ readline (lbp, stream) | |||
| 5444 | long result = readline_internal (lbp, stream); | 5525 | long result = readline_internal (lbp, stream); |
| 5445 | 5526 | ||
| 5446 | /* Honour #line directives. */ | 5527 | /* Honour #line directives. */ |
| 5447 | if (!no_line_directive | 5528 | if (!no_line_directive) |
| 5448 | && result > 12 && strneq (lbp->buffer, "#line ", 6)) | ||
| 5449 | { | 5529 | { |
| 5450 | int start, lno; | 5530 | static bool discard_until_line_directive; |
| 5451 | 5531 | ||
| 5452 | if (sscanf (lbp->buffer, "#line %d \"%n", &lno, &start) == 1) | 5532 | /* Check whether this is a #line directive. */ |
| 5533 | if (result > 12 && strneq (lbp->buffer, "#line ", 6)) | ||
| 5453 | { | 5534 | { |
| 5454 | char *endp = lbp->buffer + start; | 5535 | int start, lno; |
| 5455 | 5536 | ||
| 5456 | while ((endp = etags_strchr (endp, '"')) != NULL | 5537 | if (DEBUG) start = 0; /* shut up the compiler */ |
| 5457 | && endp[-1] == '\\') | 5538 | if (sscanf (lbp->buffer, "#line %d \"%n", &lno, &start) == 1) |
| 5458 | endp++; | ||
| 5459 | if (endp != NULL) | ||
| 5460 | { | 5539 | { |
| 5461 | char *absname, *name = lbp->buffer + start; | 5540 | char *endp = lbp->buffer + start; |
| 5462 | *endp = '\0'; | 5541 | |
| 5463 | 5542 | assert (start > 0); | |
| 5464 | canonicalize_filename(name); /* for DOS */ | 5543 | while ((endp = etags_strchr (endp, '"')) != NULL |
| 5465 | absname = absolute_filename (name, curfiledir); | 5544 | && endp[-1] == '\\') |
| 5466 | if (filename_is_absolute (name) | 5545 | endp++; |
| 5467 | || filename_is_absolute (curfile)) | 5546 | if (endp != NULL) |
| 5468 | name = absname; | 5547 | /* Ok, this is a real #line directive. Let's deal with it. */ |
| 5469 | else | ||
| 5470 | { | 5548 | { |
| 5471 | name = relative_filename (absname, tagfiledir); | 5549 | char *taggedabsname; /* absolute name of original file */ |
| 5472 | free (absname); | 5550 | char *taggedfname; /* name of original file as given */ |
| 5473 | } | 5551 | char *name; /* temp var */ |
| 5552 | |||
| 5553 | discard_until_line_directive = FALSE; /* found it */ | ||
| 5554 | name = lbp->buffer + start; | ||
| 5555 | *endp = '\0'; | ||
| 5556 | canonicalize_filename (name); /* for DOS */ | ||
| 5557 | taggedabsname = absolute_filename (name, curfdp->infabsdir); | ||
| 5558 | if (filename_is_absolute (name) | ||
| 5559 | || filename_is_absolute (curfdp->infname)) | ||
| 5560 | taggedfname = savestr (taggedabsname); | ||
| 5561 | else | ||
| 5562 | taggedfname = relative_filename (taggedabsname,tagfiledir); | ||
| 5474 | 5563 | ||
| 5475 | if (streq (curtagfname, name)) | 5564 | if (streq (curfdp->taggedfname, taggedfname)) |
| 5476 | free (name); | 5565 | /* The #line directive is only a line number change. We |
| 5477 | else | 5566 | deal with this afterwards. */ |
| 5478 | curtagfname = name; | 5567 | free (taggedfname); |
| 5479 | lineno = lno; | 5568 | else |
| 5480 | nocharno = TRUE; /* do not use char position for tags */ | 5569 | /* The tags following this #line directive should be |
| 5481 | return readline (lbp, stream); | 5570 | attributed to taggedfname. In order to do this, set |
| 5482 | } | 5571 | curfdp accordingly. */ |
| 5572 | { | ||
| 5573 | fdesc *fdp; /* file description pointer */ | ||
| 5574 | |||
| 5575 | /* Go look for a file description already set up for the | ||
| 5576 | file indicated in the #line directive. If there is | ||
| 5577 | one, use it from now until the next #line | ||
| 5578 | directive. */ | ||
| 5579 | for (fdp = fdhead; fdp != NULL; fdp = fdp->next) | ||
| 5580 | if (streq (fdp->infname, curfdp->infname) | ||
| 5581 | && streq (fdp->taggedfname, taggedfname)) | ||
| 5582 | /* If we remove the second test above (after the &&) | ||
| 5583 | then all entries pertaining to the same file are | ||
| 5584 | coalesced in the tags file. If we use it, then | ||
| 5585 | entries pertaining to the same file but generated | ||
| 5586 | from different files (via #line directives) will | ||
| 5587 | go into separate sections in the tags file. These | ||
| 5588 | alternatives look equivalent. The first one | ||
| 5589 | destroys some apparently useless information. */ | ||
| 5590 | { | ||
| 5591 | curfdp = fdp; | ||
| 5592 | free (taggedfname); | ||
| 5593 | break; | ||
| 5594 | } | ||
| 5595 | /* Else, if we already tagged the real file, skip all | ||
| 5596 | input lines until the next #line directive. */ | ||
| 5597 | if (fdp == NULL) /* not found */ | ||
| 5598 | for (fdp = fdhead; fdp != NULL; fdp = fdp->next) | ||
| 5599 | if (streq (fdp->infabsname, taggedabsname)) | ||
| 5600 | { | ||
| 5601 | discard_until_line_directive = TRUE; | ||
| 5602 | free (taggedfname); | ||
| 5603 | break; | ||
| 5604 | } | ||
| 5605 | /* Else create a new file description and use that from | ||
| 5606 | now on, until the next #line directive. */ | ||
| 5607 | if (fdp == NULL) /* not found */ | ||
| 5608 | { | ||
| 5609 | fdp = fdhead; | ||
| 5610 | fdhead = xnew (1, fdesc); | ||
| 5611 | *fdhead = *curfdp; /* copy curr. file description */ | ||
| 5612 | fdhead->next = fdp; | ||
| 5613 | fdhead->infname = savestr (curfdp->infname); | ||
| 5614 | fdhead->infabsname = savestr (curfdp->infabsname); | ||
| 5615 | fdhead->infabsdir = savestr (curfdp->infabsdir); | ||
| 5616 | fdhead->taggedfname = taggedfname; | ||
| 5617 | fdhead->usecharno = FALSE; | ||
| 5618 | curfdp = fdhead; | ||
| 5619 | } | ||
| 5620 | } | ||
| 5621 | free (taggedabsname); | ||
| 5622 | lineno = lno; | ||
| 5623 | return readline (lbp, stream); | ||
| 5624 | } /* if a real #line directive */ | ||
| 5625 | } /* if #line is followed by a a number */ | ||
| 5626 | } /* if line begins with "#line " */ | ||
| 5627 | |||
| 5628 | /* If we are here, no #line directive was found. */ | ||
| 5629 | if (discard_until_line_directive) | ||
| 5630 | { | ||
| 5631 | if (result > 0) | ||
| 5632 | /* Do a tail recursion on ourselves, thus discarding the contents | ||
| 5633 | of the line buffer. */ | ||
| 5634 | return readline (lbp, stream); | ||
| 5635 | /* End of file. */ | ||
| 5636 | discard_until_line_directive = FALSE; | ||
| 5637 | return 0; | ||
| 5483 | } | 5638 | } |
| 5484 | } | 5639 | } /* if #line directives should be considered */ |
| 5485 | 5640 | ||
| 5486 | #ifdef ETAGS_REGEXPS | 5641 | #ifdef ETAGS_REGEXPS |
| 5487 | { | 5642 | { |
| @@ -5493,7 +5648,7 @@ readline (lbp, stream) | |||
| 5493 | for (pp = p_head; pp != NULL; pp = pp->p_next) | 5648 | for (pp = p_head; pp != NULL; pp = pp->p_next) |
| 5494 | { | 5649 | { |
| 5495 | /* Only use generic regexps or those for the current language. */ | 5650 | /* Only use generic regexps or those for the current language. */ |
| 5496 | if (pp->lang != NULL && pp->lang != curlang) | 5651 | if (pp->lang != NULL && pp->lang != fdhead->lang) |
| 5497 | continue; | 5652 | continue; |
| 5498 | 5653 | ||
| 5499 | match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs); | 5654 | match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs); |
| @@ -5931,6 +6086,7 @@ xrealloc (ptr, size) | |||
| 5931 | * c-indentation-style: gnu | 6086 | * c-indentation-style: gnu |
| 5932 | * indent-tabs-mode: t | 6087 | * indent-tabs-mode: t |
| 5933 | * tab-width: 8 | 6088 | * tab-width: 8 |
| 5934 | * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer") | 6089 | * fill-column: 79 |
| 6090 | * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc") | ||
| 5935 | * End: | 6091 | * End: |
| 5936 | */ | 6092 | */ |