aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorFrancesco Potortì2002-04-15 14:18:47 +0000
committerFrancesco Potortì2002-04-15 14:18:47 +0000
commit9e0a3f98766d3828cb08374e474fdfd5d7ec2188 (patch)
tree63df83ab9c7e6c0c4126d12b26d26d1de3360b84 /lib-src
parentc150db2349b25b552c6a5419e9dd21504a25e6b3 (diff)
downloademacs-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.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c774
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
5This file is not considered part of GNU Emacs. 5This 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
36char pot_etags_version[] = "@(#) pot revision number is 15.2"; 36char 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
229typedef struct 229typedef 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
235typedef struct 235typedef 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
245typedef 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
244typedef struct node_st 257typedef 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. */
285typedef 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. */
299typedef 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
323static void init __P((void)); 366static void init __P((void));
324static void initbuffer __P((linebuffer *)); 367static void initbuffer __P((linebuffer *));
325static void find_entries __P((char *, FILE *)); 368static void process_file __P((char *, language *));
369static void find_entries __P((FILE *));
326static void free_tree __P((node *)); 370static void free_tree __P((node *));
327static void pfnote __P((char *, bool, char *, int, int, long)); 371static void pfnote __P((char *, bool, char *, int, int, long));
328static void new_pfnote __P((char *, int, bool, char *, int, int, long)); 372static void new_pfnote __P((char *, int, bool, char *, int, int, long));
329static void process_file __P((char *)); 373static void invalidate_nodes __P((fdesc *, node *));
330static void put_entries __P((node *)); 374static void put_entries __P((node *));
331 375
332static char *concat __P((char *, char *, char *)); 376static char *concat __P((char *, char *, char *));
@@ -355,19 +399,16 @@ static char *cwd; /* current working directory */
355static char *tagfiledir; /* directory of tagfile */ 399static char *tagfiledir; /* directory of tagfile */
356static FILE *tagf; /* ioptr for tags file */ 400static FILE *tagf; /* ioptr for tags file */
357 401
358static char *curfile; /* current input uncompressed file name */ 402static fdesc *fdhead; /* head of file description list */
359static char *curfiledir; /* absolute dir of curfile */ 403static fdesc *curfdp; /* current file description */
360static char *curtagfname; /* current file name to write in tagfile */
361static language *curlang; /* current language */
362
363static int lineno; /* line number of current line */ 404static int lineno; /* line number of current line */
364static long charno; /* current character number */ 405static long charno; /* current character number */
365static long linecharno; /* charno of start of current line */ 406static long linecharno; /* charno of start of current line */
366static char *dbp; /* pointer to start of current tag */ 407static char *dbp; /* pointer to start of current tag */
367static bool nocharno; /* only use line number when making tag */ 408
368static const int invalidcharno = -1; 409static const int invalidcharno = -1;
369 410
370static node *head; /* the head of the binary tree of tags */ 411static node *nodehead; /* the head of the binary tree of tags */
371 412
372static linebuffer lb; /* the current line */ 413static 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
388static bool append_to_tagfile; /* -a: append to tags */ 429static 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. */
390static bool typedefs; /* -t: create tags for C and Ada typedefs */ 431static bool typedefs; /* -t: create tags for C and Ada typedefs */
391static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ 432static 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 */
394static bool constantypedefs; /* -d: create tags for C #define, enum */ 435static 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. */
397static bool declarations; /* --declarations: tag them and extern in C&Co*/
398static bool globals; /* create tags for global variables */ 438static bool globals; /* create tags for global variables */
399static bool no_line_directive; /* ignore #line directives */ 439static bool declarations; /* --declarations: tag them and extern in C&Co*/
400static bool members; /* create tags for C member variables */ 440static bool members; /* create tags for C member variables */
441static bool no_line_directive; /* ignore #line directives */
401static bool update; /* -u: update tags */ 442static bool update; /* -u: update tags */
402static bool vgrind_style; /* -v: create vgrind style index output */ 443static bool vgrind_style; /* -v: create vgrind style index output */
403static bool no_warnings; /* -w: suppress warnings */ 444static bool no_warnings; /* -w: suppress warnings */
@@ -406,66 +447,58 @@ static bool cplusplus; /* .[hc] means C++, not C */
406static bool noindentypedefs; /* -I: ignore indentation in C */ 447static bool noindentypedefs; /* -I: ignore indentation in C */
407static bool packages_only; /* --packages-only: in Ada, only tag packages*/ 448static bool packages_only; /* --packages-only: in Ada, only tag packages*/
408 449
450#ifdef ETAGS_REGEXPS
451/* List of all regexps. */
452static 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. */
457static char lc_trans[CHAR_SET_SIZE];
458#endif /* ETAGS_REGEXPS */
459
409#ifdef LONG_OPTIONS 460#ifdef LONG_OPTIONS
410static struct option longopts[] = 461static 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. */
449typedef 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. */
461static 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. */
466static char lc_trans[CHAR_SET_SIZE];
467#endif /* ETAGS_REGEXPS */
468
469static compressor compressors[] = 502static 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. */
484static language *forced_lang = NULL;
485
486/* Ada code */ 516/* Ada code */
487static char *Ada_suffixes [] = 517static char *Ada_suffixes [] =
488 { "ads", "adb", "ada", NULL }; 518 { "ads", "adb", "ada", NULL };
@@ -582,31 +612,31 @@ static char *Yacc_suffixes [] =
582 612
583static language lang_names [] = 613static 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
649print_version () 679print_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\
668linked with GNU getopt."); 698linked 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) 701Absolute 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\ 702Relative ones are stored relative to the output file's directory.\n");
673Relative 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
796enum 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. */
805typedef 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 */
1370static void 1384static void
1371process_file (file) 1385process_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 ()
1548static node *last_node = NULL; 1566static node *last_node = NULL;
1549 1567
1550static void 1568static void
1551find_entries (file, inf) 1569find_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 */
1912static void
1913invalidate_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
1846static int total_size_of_entries __P((node *)); 1926static int total_size_of_entries __P((node *));
1847static int number_len __P((long)); 1927static 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. */
1850static int 1930static int
1851number_len (num) 1931number_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 */