aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancesco Potortì2002-03-05 11:28:26 +0000
committerFrancesco Potortì2002-03-05 11:28:26 +0000
commitdb59058201446a651dd28697590ad5fbc25383ea (patch)
tree01ab3cc8f038ed9e2be1be7e7f9c1be359607f6e
parent51aeded3e698e7908c47977152f80f87a0765e38 (diff)
downloademacs-db59058201446a651dd28697590ad5fbc25383ea.tar.gz
emacs-db59058201446a651dd28697590ad5fbc25383ea.zip
* etags.c: Honour #line directives.
(no_line_directive): New global var; set it for old behaviour. (main): Remove some #ifdef in the getopt switch. (add_node, put_entries): Code added to merge different chunks of nodes referring to the same file. Currently the tags are just appended, without any check for duplicates. (Perl_functions): Do not special case ctags. (readline): Identify #line directives and do the right thing. (nocharno, invalidcharno): New global vars. (process_file): Reset nocharno. (readline): Set nocharno. (pfnote): Read nocharno and maybe put invalidcharno in node. (total_size_of_entries, put_entries): Use invalidcharno. * etags.c: Keep the whole tag table in memory, even in etags mode. (main): Call put_entries here even in CTAGS mode. (main, process_file): Check the return values of fclose and pclose. (process_file): Do not call put_entries after parsing each file. (process_file): Canonicalise file names even for ctags. (process_file): Set curfile here... (find_entries): ... not here any more. (add_node): In etags mode, build a linked list of entries (on right pointer) for each file, and link the first entry of each file on left nodes. (put_entries): Print here the name of the file. (put_entries): Print the entries starting from the first file. (number_len, total_size_of_entries): Define these only iin etags mode, make the second work only on the right nodes. * etags.c: Make all global variables static.
-rw-r--r--lib-src/etags.c595
1 files changed, 321 insertions, 274 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 950389545ac..52e9d291d0e 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -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 14.35"; 36char pot_etags_version[] = "@(#) pot revision number is 14.39";
37 37
38#define TRUE 1 38#define TRUE 1
39#define FALSE 0 39#define FALSE 0
@@ -299,13 +299,11 @@ static void print_language_names __P((void));
299static void print_version __P((void)); 299static void print_version __P((void));
300static void print_help __P((void)); 300static void print_help __P((void));
301int main __P((int, char **)); 301int main __P((int, char **));
302static int number_len __P((long));
303 302
304static compressor *get_compressor_from_suffix __P((char *, char **)); 303static compressor *get_compressor_from_suffix __P((char *, char **));
305static language *get_language_from_langname __P((const char *)); 304static language *get_language_from_langname __P((const char *));
306static language *get_language_from_interpreter __P((char *)); 305static language *get_language_from_interpreter __P((char *));
307static language *get_language_from_filename __P((char *)); 306static language *get_language_from_filename __P((char *));
308static int total_size_of_entries __P((node *));
309static long readline __P((linebuffer *, FILE *)); 307static long readline __P((linebuffer *, FILE *));
310static long readline_internal __P((linebuffer *, FILE *)); 308static long readline_internal __P((linebuffer *, FILE *));
311static bool nocase_tail __P((char *)); 309static bool nocase_tail __P((char *));
@@ -345,33 +343,35 @@ static char *absolute_dirname __P((char *, char *));
345static bool filename_is_absolute __P((char *f)); 343static bool filename_is_absolute __P((char *f));
346static void canonicalize_filename __P((char *)); 344static void canonicalize_filename __P((char *));
347static void linebuffer_setlen __P((linebuffer *, int)); 345static void linebuffer_setlen __P((linebuffer *, int));
348PTR xmalloc __P((unsigned int)); 346static PTR xmalloc __P((unsigned int));
349PTR xrealloc __P((char *, unsigned int)); 347static PTR xrealloc __P((char *, unsigned int));
350 348
351 349
352char searchar = '/'; /* use /.../ searches */ 350static char searchar = '/'; /* use /.../ searches */
353 351
354char *tagfile; /* output file */ 352static char *tagfile; /* output file */
355char *progname; /* name this program was invoked with */ 353static char *progname; /* name this program was invoked with */
356char *cwd; /* current working directory */ 354static char *cwd; /* current working directory */
357char *tagfiledir; /* directory of tagfile */ 355static char *tagfiledir; /* directory of tagfile */
358FILE *tagf; /* ioptr for tags file */ 356static FILE *tagf; /* ioptr for tags file */
359 357
360char *curfile; /* current input file name */ 358static char *curfile; /* current input file name */
361language *curlang; /* current language */ 359static language *curlang; /* current language */
362 360
363int lineno; /* line number of current line */ 361static int lineno; /* line number of current line */
364long charno; /* current character number */ 362static long charno; /* current character number */
365long linecharno; /* charno of start of current line */ 363static long linecharno; /* charno of start of current line */
366char *dbp; /* pointer to start of current tag */ 364static char *dbp; /* pointer to start of current tag */
365static bool nocharno; /* only use line number when making tag */
366static const int invalidcharno = -1;
367 367
368node *head; /* the head of the binary tree of tags */ 368static node *head; /* the head of the binary tree of tags */
369 369
370linebuffer lb; /* the current line */ 370static linebuffer lb; /* the current line */
371 371
372/* boolean "functions" (see init) */ 372/* boolean "functions" (see init) */
373bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; 373static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
374char 374static char
375 /* white chars */ 375 /* white chars */
376 *white = " \f\t\n\r\v", 376 *white = " \f\t\n\r\v",
377 /* not in a name */ 377 /* not in a name */
@@ -383,58 +383,60 @@ char
383 /* valid in-token chars */ 383 /* valid in-token chars */
384 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; 384 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
385 385
386bool append_to_tagfile; /* -a: append to tags */ 386static bool append_to_tagfile; /* -a: append to tags */
387/* The following four default to TRUE for etags, but to FALSE for ctags. */ 387/* The following four default to TRUE for etags, but to FALSE for ctags. */
388bool typedefs; /* -t: create tags for C and Ada typedefs */ 388static bool typedefs; /* -t: create tags for C and Ada typedefs */
389bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */ 389static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
390 /* 0 struct/enum/union decls, and C++ */ 390 /* 0 struct/enum/union decls, and C++ */
391 /* member functions. */ 391 /* member functions. */
392bool constantypedefs; /* -d: create tags for C #define, enum */ 392static bool constantypedefs; /* -d: create tags for C #define, enum */
393 /* constants and variables. */ 393 /* constants and variables. */
394 /* -D: opposite of -d. Default under ctags. */ 394 /* -D: opposite of -d. Default under ctags. */
395bool declarations; /* --declarations: tag them and extern in C&Co*/ 395static bool declarations; /* --declarations: tag them and extern in C&Co*/
396bool globals; /* create tags for global variables */ 396static bool globals; /* create tags for global variables */
397bool members; /* create tags for C member variables */ 397static bool no_line_directive; /* ignore #line directives */
398bool update; /* -u: update tags */ 398static bool members; /* create tags for C member variables */
399bool vgrind_style; /* -v: create vgrind style index output */ 399static bool update; /* -u: update tags */
400bool no_warnings; /* -w: suppress warnings */ 400static bool vgrind_style; /* -v: create vgrind style index output */
401bool cxref_style; /* -x: create cxref style output */ 401static bool no_warnings; /* -w: suppress warnings */
402bool cplusplus; /* .[hc] means C++, not C */ 402static bool cxref_style; /* -x: create cxref style output */
403bool noindentypedefs; /* -I: ignore indentation in C */ 403static bool cplusplus; /* .[hc] means C++, not C */
404bool packages_only; /* --packages-only: in Ada, only tag packages*/ 404static bool noindentypedefs; /* -I: ignore indentation in C */
405static bool packages_only; /* --packages-only: in Ada, only tag packages*/
405 406
406#ifdef LONG_OPTIONS 407#ifdef LONG_OPTIONS
407struct option longopts[] = 408static struct option longopts[] =
408{ 409{
409 { "packages-only", no_argument, &packages_only, TRUE }, 410 { "packages-only", no_argument, &packages_only, TRUE },
410 { "append", no_argument, NULL, 'a' }, 411 { "append", no_argument, NULL, 'a' },
411 { "backward-search", no_argument, NULL, 'B' }, 412 { "backward-search", no_argument, NULL, 'B' },
412 { "c++", no_argument, NULL, 'C' }, 413 { "c++", no_argument, NULL, 'C' },
413 { "cxref", no_argument, NULL, 'x' }, 414 { "cxref", no_argument, NULL, 'x' },
414 { "defines", no_argument, NULL, 'd' }, 415 { "defines", no_argument, NULL, 'd' },
415 { "declarations", no_argument, &declarations, TRUE }, 416 { "declarations", no_argument, &declarations, TRUE },
416 { "no-defines", no_argument, NULL, 'D' }, 417 { "no-defines", no_argument, NULL, 'D' },
417 { "globals", no_argument, &globals, TRUE }, 418 { "globals", no_argument, &globals, TRUE },
418 { "no-globals", no_argument, &globals, FALSE }, 419 { "no-globals", no_argument, &globals, FALSE },
419 { "help", no_argument, NULL, 'h' }, 420 { "no-line-directive", no_argument, &no_line_directive, TRUE },
420 { "help", no_argument, NULL, 'H' }, 421 { "help", no_argument, NULL, 'h' },
421 { "ignore-indentation", no_argument, NULL, 'I' }, 422 { "help", no_argument, NULL, 'H' },
422 { "include", required_argument, NULL, 'i' }, 423 { "ignore-indentation", no_argument, NULL, 'I' },
423 { "language", required_argument, NULL, 'l' }, 424 { "include", required_argument, NULL, 'i' },
424 { "members", no_argument, &members, TRUE }, 425 { "language", required_argument, NULL, 'l' },
425 { "no-members", no_argument, &members, FALSE }, 426 { "members", no_argument, &members, TRUE },
426 { "no-warn", no_argument, NULL, 'w' }, 427 { "no-members", no_argument, &members, FALSE },
427 { "output", required_argument, NULL, 'o' }, 428 { "no-warn", no_argument, NULL, 'w' },
429 { "output", required_argument, NULL, 'o' },
428#ifdef ETAGS_REGEXPS 430#ifdef ETAGS_REGEXPS
429 { "regex", required_argument, NULL, 'r' }, 431 { "regex", required_argument, NULL, 'r' },
430 { "no-regex", no_argument, NULL, 'R' }, 432 { "no-regex", no_argument, NULL, 'R' },
431 { "ignore-case-regex", required_argument, NULL, 'c' }, 433 { "ignore-case-regex", required_argument, NULL, 'c' },
432#endif /* ETAGS_REGEXPS */ 434#endif /* ETAGS_REGEXPS */
433 { "typedefs", no_argument, NULL, 't' }, 435 { "typedefs", no_argument, NULL, 't' },
434 { "typedefs-and-c++", no_argument, NULL, 'T' }, 436 { "typedefs-and-c++", no_argument, NULL, 'T' },
435 { "update", no_argument, NULL, 'u' }, 437 { "update", no_argument, NULL, 'u' },
436 { "version", no_argument, NULL, 'V' }, 438 { "version", no_argument, NULL, 'V' },
437 { "vgrind", no_argument, NULL, 'v' }, 439 { "vgrind", no_argument, NULL, 'v' },
438 { NULL } 440 { NULL }
439}; 441};
440#endif /* LONG_OPTIONS */ 442#endif /* LONG_OPTIONS */
@@ -454,15 +456,15 @@ typedef struct pattern
454} pattern; 456} pattern;
455 457
456/* List of all regexps. */ 458/* List of all regexps. */
457pattern *p_head = NULL; 459static pattern *p_head = NULL;
458 460
459/* How many characters in the character set. (From regex.c.) */ 461/* How many characters in the character set. (From regex.c.) */
460#define CHAR_SET_SIZE 256 462#define CHAR_SET_SIZE 256
461/* Translation table for case-insensitive matching. */ 463/* Translation table for case-insensitive matching. */
462char lc_trans[CHAR_SET_SIZE]; 464static char lc_trans[CHAR_SET_SIZE];
463#endif /* ETAGS_REGEXPS */ 465#endif /* ETAGS_REGEXPS */
464 466
465compressor compressors[] = 467static compressor compressors[] =
466{ 468{
467 { "z", "gzip -d -c"}, 469 { "z", "gzip -d -c"},
468 { "Z", "gzip -d -c"}, 470 { "Z", "gzip -d -c"},
@@ -477,94 +479,96 @@ compressor compressors[] =
477 */ 479 */
478 480
479/* Non-NULL if language fixed. */ 481/* Non-NULL if language fixed. */
480language *forced_lang = NULL; 482static language *forced_lang = NULL;
481 483
482/* Ada code */ 484/* Ada code */
483char *Ada_suffixes [] = 485static char *Ada_suffixes [] =
484 { "ads", "adb", "ada", NULL }; 486 { "ads", "adb", "ada", NULL };
485 487
486/* Assembly code */ 488/* Assembly code */
487char *Asm_suffixes [] = { "a", /* Unix assembler */ 489static char *Asm_suffixes [] =
488 "asm", /* Microcontroller assembly */ 490 { "a", /* Unix assembler */
489 "def", /* BSO/Tasking definition includes */ 491 "asm", /* Microcontroller assembly */
490 "inc", /* Microcontroller include files */ 492 "def", /* BSO/Tasking definition includes */
491 "ins", /* Microcontroller include files */ 493 "inc", /* Microcontroller include files */
492 "s", "sa", /* Unix assembler */ 494 "ins", /* Microcontroller include files */
493 "S", /* cpp-processed Unix assembler */ 495 "s", "sa", /* Unix assembler */
494 "src", /* BSO/Tasking C compiler output */ 496 "S", /* cpp-processed Unix assembler */
495 NULL 497 "src", /* BSO/Tasking C compiler output */
496 }; 498 NULL
499 };
497 500
498/* Note that .c and .h can be considered C++, if the --c++ flag was 501/* Note that .c and .h can be considered C++, if the --c++ flag was
499 given, or if the `class' keyowrd is met inside the file. 502 given, or if the `class' keyowrd is met inside the file.
500 That is why default_C_entries is called for these. */ 503 That is why default_C_entries is called for these. */
501char *default_C_suffixes [] = 504static char *default_C_suffixes [] =
502 { "c", "h", NULL }; 505 { "c", "h", NULL };
503 506
504char *Cplusplus_suffixes [] = 507static char *Cplusplus_suffixes [] =
505 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx", 508 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
506 "M", /* Objective C++ */ 509 "M", /* Objective C++ */
507 "pdb", /* Postscript with C syntax */ 510 "pdb", /* Postscript with C syntax */
508 NULL }; 511 NULL };
509 512
510char *Cjava_suffixes [] = 513static char *Cjava_suffixes [] =
511 { "java", NULL }; 514 { "java", NULL };
512 515
513char *Cobol_suffixes [] = 516static char *Cobol_suffixes [] =
514 { "COB", "cob", NULL }; 517 { "COB", "cob", NULL };
515 518
516char *Cstar_suffixes [] = 519static char *Cstar_suffixes [] =
517 { "cs", "hs", NULL }; 520 { "cs", "hs", NULL };
518 521
519char *Erlang_suffixes [] = 522static char *Erlang_suffixes [] =
520 { "erl", "hrl", NULL }; 523 { "erl", "hrl", NULL };
521 524
522char *Fortran_suffixes [] = 525static char *Fortran_suffixes [] =
523 { "F", "f", "f90", "for", NULL }; 526 { "F", "f", "f90", "for", NULL };
524 527
525char *Lisp_suffixes [] = 528static char *Lisp_suffixes [] =
526 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL }; 529 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
527 530
528char *Makefile_filenames [] = 531static char *Makefile_filenames [] =
529 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL}; 532 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};
530 533
531char *Pascal_suffixes [] = 534static char *Pascal_suffixes [] =
532 { "p", "pas", NULL }; 535 { "p", "pas", NULL };
533 536
534char *Perl_suffixes [] = 537static char *Perl_suffixes [] =
535 { "pl", "pm", NULL }; 538 { "pl", "pm", NULL };
536char *Perl_interpreters [] = 539
540static char *Perl_interpreters [] =
537 { "perl", "@PERL@", NULL }; 541 { "perl", "@PERL@", NULL };
538 542
539char *PHP_suffixes [] = 543static char *PHP_suffixes [] =
540 { "php", "php3", "php4", NULL }; 544 { "php", "php3", "php4", NULL };
541 545
542char *plain_C_suffixes [] = 546static char *plain_C_suffixes [] =
543 { "lm", /* Objective lex file */ 547 { "lm", /* Objective lex file */
544 "m", /* Objective C file */ 548 "m", /* Objective C file */
545 "pc", /* Pro*C file */ 549 "pc", /* Pro*C file */
546 NULL }; 550 NULL };
547 551
548char *Postscript_suffixes [] = 552static char *Postscript_suffixes [] =
549 { "ps", "psw", NULL }; /* .psw is for PSWrap */ 553 { "ps", "psw", NULL }; /* .psw is for PSWrap */
550 554
551char *Prolog_suffixes [] = 555static char *Prolog_suffixes [] =
552 { "prolog", NULL }; 556 { "prolog", NULL };
553 557
554char *Python_suffixes [] = 558static char *Python_suffixes [] =
555 { "py", NULL }; 559 { "py", NULL };
556 560
557/* Can't do the `SCM' or `scm' prefix with a version number. */ 561/* Can't do the `SCM' or `scm' prefix with a version number. */
558char *Scheme_suffixes [] = 562static char *Scheme_suffixes [] =
559 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL }; 563 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };
560 564
561char *TeX_suffixes [] = 565static char *TeX_suffixes [] =
562 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL }; 566 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };
563 567
564char *Texinfo_suffixes [] = 568static char *Texinfo_suffixes [] =
565 { "texi", "texinfo", "txi", NULL }; 569 { "texi", "texinfo", "txi", NULL };
566 570
567char *Yacc_suffixes [] = 571static char *Yacc_suffixes [] =
568 { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */ 572 { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */
569 573
570/* 574/*
@@ -574,7 +578,7 @@ char *Yacc_suffixes [] =
574 * name. I just didn't. 578 * name. I just didn't.
575 */ 579 */
576 580
577language lang_names [] = 581static language lang_names [] =
578{ 582{
579 { "ada", Ada_funcs, NULL, Ada_suffixes, NULL }, 583 { "ada", Ada_funcs, NULL, Ada_suffixes, NULL },
580 { "asm", Asm_labels, NULL, Asm_suffixes, NULL }, 584 { "asm", Asm_labels, NULL, Asm_suffixes, NULL },
@@ -1042,7 +1046,6 @@ main (argc, argv)
1042 } 1046 }
1043 } 1047 }
1044 break; 1048 break;
1045#ifdef ETAGS_REGEXPS
1046 case 'r': 1049 case 'r':
1047 argbuffer[current_arg].arg_type = at_regexp; 1050 argbuffer[current_arg].arg_type = at_regexp;
1048 argbuffer[current_arg].what = optarg; 1051 argbuffer[current_arg].what = optarg;
@@ -1058,7 +1061,6 @@ main (argc, argv)
1058 argbuffer[current_arg].what = optarg; 1061 argbuffer[current_arg].what = optarg;
1059 ++current_arg; 1062 ++current_arg;
1060 break; 1063 break;
1061#endif /* ETAGS_REGEXPS */
1062 case 'V': 1064 case 'V':
1063 print_version (); 1065 print_version ();
1064 break; 1066 break;
@@ -1072,19 +1074,16 @@ main (argc, argv)
1072 case 'T': 1074 case 'T':
1073 typedefs = typedefs_or_cplusplus = TRUE; 1075 typedefs = typedefs_or_cplusplus = TRUE;
1074 break; 1076 break;
1075#if (!CTAGS)
1076 /* Etags options */ 1077 /* Etags options */
1077 case 'i': 1078 case 'i':
1078 included_files[nincluded_files++] = optarg; 1079 included_files[nincluded_files++] = optarg;
1079 break; 1080 break;
1080#else /* CTAGS */
1081 /* Ctags options. */ 1081 /* Ctags options. */
1082 case 'B': searchar = '?'; break; 1082 case 'B': searchar = '?'; break;
1083 case 'u': update = TRUE; break; 1083 case 'u': update = TRUE; break;
1084 case 'v': vgrind_style = TRUE; /*FALLTHRU*/ 1084 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1085 case 'x': cxref_style = TRUE; break; 1085 case 'x': cxref_style = TRUE; break;
1086 case 'w': no_warnings = TRUE; break; 1086 case 'w': no_warnings = TRUE; break;
1087#endif /* CTAGS */
1088 default: 1087 default:
1089 suggest_asking_for_help (); 1088 suggest_asking_for_help ();
1090 } 1089 }
@@ -1193,22 +1192,17 @@ main (argc, argv)
1193 free_patterns (); 1192 free_patterns ();
1194#endif /* ETAGS_REGEXPS */ 1193#endif /* ETAGS_REGEXPS */
1195 1194
1196 if (!CTAGS) 1195 if (!CTAGS || cxref_style)
1197 {
1198 while (nincluded_files-- > 0)
1199 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1200
1201 fclose (tagf);
1202 exit (GOOD);
1203 }
1204
1205 /* If CTAGS, we are here. process_file did not write the tags yet,
1206 because we want them ordered. Let's do it now. */
1207 if (cxref_style)
1208 { 1196 {
1209 put_entries (head); 1197 put_entries (head);
1210 free_tree (head); 1198 free_tree (head);
1211 head = NULL; 1199 head = NULL;
1200 if (!CTAGS)
1201 while (nincluded_files-- > 0)
1202 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1203
1204 if (fclose (tagf) == EOF)
1205 pfatal (tagfile);
1212 exit (GOOD); 1206 exit (GOOD);
1213 } 1207 }
1214 1208
@@ -1234,7 +1228,8 @@ main (argc, argv)
1234 put_entries (head); 1228 put_entries (head);
1235 free_tree (head); 1229 free_tree (head);
1236 head = NULL; 1230 head = NULL;
1237 fclose (tagf); 1231 if (fclose (tagf) == EOF)
1232 pfatal (tagfile);
1238 1233
1239 if (update) 1234 if (update)
1240 { 1235 {
@@ -1379,6 +1374,7 @@ process_file (file)
1379 compressor *compr; 1374 compressor *compr;
1380 char *compressed_name, *uncompressed_name; 1375 char *compressed_name, *uncompressed_name;
1381 char *ext, *real_name; 1376 char *ext, *real_name;
1377 int retval;
1382 1378
1383 1379
1384 canonicalize_filename (file); 1380 canonicalize_filename (file);
@@ -1486,34 +1482,26 @@ process_file (file)
1486 goto exit; 1482 goto exit;
1487 } 1483 }
1488 1484
1485 if (filename_is_absolute (uncompressed_name))
1486 {
1487 /* file is an absolute file name. Canonicalise it. */
1488 curfile = absolute_filename (uncompressed_name, cwd);
1489 }
1490 else
1491 {
1492 /* file is a file name relative to cwd. Make it relative
1493 to the directory of the tags file. */
1494 curfile = relative_filename (uncompressed_name, tagfiledir);
1495 }
1496 nocharno = FALSE; /* use char position when making tags */
1489 find_entries (uncompressed_name, inf); 1497 find_entries (uncompressed_name, inf);
1490 1498
1491 if (real_name == compressed_name) 1499 if (real_name == compressed_name)
1492 pclose (inf); 1500 retval = pclose (inf);
1493 else 1501 else
1494 fclose (inf); 1502 retval = fclose (inf);
1495 1503 if (retval < 0)
1496 if (!CTAGS) 1504 pfatal (file);
1497 {
1498 char *filename;
1499
1500 if (filename_is_absolute (uncompressed_name))
1501 {
1502 /* file is an absolute file name. Canonicalise it. */
1503 filename = absolute_filename (uncompressed_name, cwd);
1504 }
1505 else
1506 {
1507 /* file is a file name relative to cwd. Make it relative
1508 to the directory of the tags file. */
1509 filename = relative_filename (uncompressed_name, tagfiledir);
1510 }
1511 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1512 free (filename);
1513 put_entries (head);
1514 free_tree (head);
1515 head = NULL;
1516 }
1517 1505
1518 exit: 1506 exit:
1519 if (compressed_name) free(compressed_name); 1507 if (compressed_name) free(compressed_name);
@@ -1552,7 +1540,7 @@ init ()
1552 * This routine opens the specified file and calls the function 1540 * This routine opens the specified file and calls the function
1553 * which finds the function and type definitions. 1541 * which finds the function and type definitions.
1554 */ 1542 */
1555node *last_node = NULL; 1543static node *last_node = NULL;
1556 1544
1557static void 1545static void
1558find_entries (file, inf) 1546find_entries (file, inf)
@@ -1563,13 +1551,6 @@ find_entries (file, inf)
1563 language *lang; 1551 language *lang;
1564 node *old_last_node; 1552 node *old_last_node;
1565 1553
1566 /* Memory leakage here: the string pointed by curfile is
1567 never released, because curfile is copied into np->file
1568 for each node, to be used in CTAGS mode. The amount of
1569 memory leaked here is the sum of the lengths of the
1570 file names. */
1571 curfile = savestr (file);
1572
1573 /* If user specified a language, use it. */ 1554 /* If user specified a language, use it. */
1574 lang = forced_lang; 1555 lang = forced_lang;
1575 if (lang != NULL && lang->function != NULL) 1556 if (lang != NULL && lang->function != NULL)
@@ -1673,12 +1654,15 @@ pfnote (name, is_func, linestart, linelen, lno, cno)
1673 np->file = curfile; 1654 np->file = curfile;
1674 np->is_func = is_func; 1655 np->is_func = is_func;
1675 np->lno = lno; 1656 np->lno = lno;
1676 /* Our char numbers are 0-base, because of C language tradition? 1657 if (nocharno)
1677 ctags compatibility? old versions compatibility? I don't know. 1658 np->cno = invalidcharno;
1678 Anyway, since emacs's are 1-base we expect etags.el to take care 1659 else
1679 of the difference. If we wanted to have 1-based numbers, we would 1660 /* Our char numbers are 0-base, because of C language tradition?
1680 uncomment the +1 below. */ 1661 ctags compatibility? old versions compatibility? I don't know.
1681 np->cno = cno /* + 1 */ ; 1662 Anyway, since emacs's are 1-base we expect etags.el to take care
1663 of the difference. If we wanted to have 1-based numbers, we would
1664 uncomment the +1 below. */
1665 np->cno = cno /* + 1 */ ;
1682 np->left = np->right = NULL; 1666 np->left = np->right = NULL;
1683 if (CTAGS && !cxref_style) 1667 if (CTAGS && !cxref_style)
1684 { 1668 {
@@ -1771,9 +1755,9 @@ free_tree (np)
1771 1755
1772/* 1756/*
1773 * add_node () 1757 * add_node ()
1774 * Adds a node to the tree of nodes. In etags mode, we don't keep 1758 * Adds a node to the tree of nodes. In etags mode, sort by file
1775 * it sorted; we just keep a linear list. In ctags mode, maintain 1759 * name. In ctags mode, sort by tag name. Make no attempt at
1776 * an ordered tree, with no attempt at balancing. 1760 * balancing.
1777 * 1761 *
1778 * add_node is the only function allowed to add nodes, so it can 1762 * add_node is the only function allowed to add nodes, so it can
1779 * maintain state. 1763 * maintain state.
@@ -1795,10 +1779,27 @@ add_node (np, cur_node_p)
1795 if (!CTAGS) 1779 if (!CTAGS)
1796 { 1780 {
1797 /* Etags Mode */ 1781 /* Etags Mode */
1798 if (last_node == NULL) 1782 assert (last_node != NULL);
1799 fatal ("internal error in add_node", (char *)NULL); 1783 /* For each file name, tags are in a linked sublist on the right
1800 last_node->right = np; 1784 pointer. The first tags of different files are a linked list
1801 last_node = np; 1785 on the left pointer. last_node points to the end of the last
1786 used sublist. */
1787 if (last_node->file == np->file)
1788 {
1789 /* Let's use the same sublist as the last added node. */
1790 last_node->right = np;
1791 last_node = np;
1792 }
1793 else if (streq (cur_node->file, np->file))
1794 {
1795 /* Scanning the list we found the head of a sublist which is
1796 good for us. Let's scan this sublist. */
1797 add_node (np, &cur_node->right);
1798 }
1799 else
1800 /* The head of this sublist is not good for us. Let's try the
1801 next one. */
1802 add_node (np, &cur_node->left);
1802 } 1803 }
1803 else 1804 else
1804 { 1805 {
@@ -1837,31 +1838,89 @@ add_node (np, cur_node_p)
1837} 1838}
1838 1839
1839 1840
1841#if !CTAGS
1842static int total_size_of_entries __P((node *));
1843static int number_len __P((long));
1844
1845/* Length of a number's decimal representation. */
1846static int
1847number_len (num)
1848 long num;
1849{
1850 int len = 1;
1851 while ((num /= 10) > 0)
1852 len += 1;
1853 return len;
1854}
1855
1856/*
1857 * Return total number of characters that put_entries will output for
1858 * the nodes in the linked list at the right of the specified node.
1859 * This count is irrelevant with etags.el since emacs 19.34 at least,
1860 * but is still supplied for backward compatibility.
1861 */
1862static int
1863total_size_of_entries (np)
1864 register node *np;
1865{
1866 register int total = 0;
1867
1868 for (; np != NULL; np = np->right)
1869 {
1870 total += strlen (np->pat) + 1; /* pat\177 */
1871 if (np->name != NULL)
1872 total += strlen (np->name) + 1; /* name\001 */
1873 total += number_len ((long) np->lno) + 1; /* lno, */
1874 if (np->cno != invalidcharno) /* cno */
1875 total += number_len (np->cno);
1876 total += 1; /* newline */
1877 }
1878
1879 return total;
1880}
1881#endif
1882
1840static void 1883static void
1841put_entries (np) 1884put_entries (np)
1842 register node *np; 1885 register node *np;
1843{ 1886{
1844 register char *sp; 1887 register char *sp;
1888 static char *file = NULL;
1845 1889
1846 if (np == NULL) 1890 if (np == NULL)
1847 return; 1891 return;
1848 1892
1849 /* Output subentries that precede this one */ 1893 /* Output subentries that precede this one */
1850 put_entries (np->left); 1894 if (CTAGS)
1895 put_entries (np->left);
1851 1896
1852 /* Output this entry */ 1897 /* Output this entry */
1853
1854 if (!CTAGS) 1898 if (!CTAGS)
1855 { 1899 {
1900 /* Etags mode */
1901 if (file != np->file
1902 && (file == NULL || !streq (file, np->file)))
1903 {
1904 file = np->file;
1905 fprintf (tagf, "\f\n%s,%d\n",
1906 file, total_size_of_entries (np));
1907 }
1908 fputs (np->pat, tagf);
1909 fputc ('\177', tagf);
1856 if (np->name != NULL) 1910 if (np->name != NULL)
1857 fprintf (tagf, "%s\177%s\001%d,%ld\n", 1911 {
1858 np->pat, np->name, np->lno, np->cno); 1912 fputs (np->name, tagf);
1913 fputc ('\001', tagf);
1914 }
1915 fprintf (tagf, "%d,", np->lno);
1916 if (np->cno == invalidcharno)
1917 fputc ('\n', tagf);
1859 else 1918 else
1860 fprintf (tagf, "%s\177%d,%ld\n", 1919 fprintf (tagf, "%ld\n", np->cno);
1861 np->pat, np->lno, np->cno);
1862 } 1920 }
1863 else 1921 else
1864 { 1922 {
1923 /* Ctags mode */
1865 if (np->name == NULL) 1924 if (np->name == NULL)
1866 error ("internal error: NULL name in ctags mode.", (char *)NULL); 1925 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1867 1926
@@ -1899,50 +1958,11 @@ put_entries (np)
1899 } 1958 }
1900 } 1959 }
1901 1960
1961
1902 /* Output subentries that follow this one */ 1962 /* Output subentries that follow this one */
1903 put_entries (np->right); 1963 put_entries (np->right);
1904} 1964 if (!CTAGS)
1905 1965 put_entries (np->left);
1906/* Length of a number's decimal representation. */
1907static int
1908number_len (num)
1909 long num;
1910{
1911 int len = 1;
1912 while ((num /= 10) > 0)
1913 len += 1;
1914 return len;
1915}
1916
1917/*
1918 * Return total number of characters that put_entries will output for
1919 * the nodes in the subtree of the specified node. Works only if
1920 * we are not ctags, but called only in that case. This count
1921 * is irrelevant with the new tags.el, but is still supplied for
1922 * backward compatibility.
1923 */
1924static int
1925total_size_of_entries (np)
1926 register node *np;
1927{
1928 register int total;
1929
1930 if (np == NULL)
1931 return 0;
1932
1933 for (total = 0; np != NULL; np = np->right)
1934 {
1935 /* Count left subentries. */
1936 total += total_size_of_entries (np->left);
1937
1938 /* Count this entry */
1939 total += strlen (np->pat) + 1;
1940 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1941 if (np->name != NULL)
1942 total += 1 + strlen (np->name); /* \001name */
1943 }
1944
1945 return total;
1946} 1966}
1947 1967
1948 1968
@@ -2033,7 +2053,7 @@ PSEUDO, 0, st_C_gnumacro
2033#DEFVAR_, 0, st_C_gnumacro 2053#DEFVAR_, 0, st_C_gnumacro
2034%] 2054%]
2035and replace lines between %< and %> with its output, 2055and replace lines between %< and %> with its output,
2036then make in_word_set static. */ 2056then make in_word_set and C_stab_entry static. */
2037/*%<*/ 2057/*%<*/
2038/* C code produced by gperf version 2.7.1 (19981006 egcs) */ 2058/* C code produced by gperf version 2.7.1 (19981006 egcs) */
2039/* Command-line: gperf -c -k 1,3 -o -p -r -t */ 2059/* Command-line: gperf -c -k 1,3 -o -p -r -t */
@@ -2218,7 +2238,7 @@ C_symtype (str, len, c_ext)
2218 * C functions and variables are recognized using a simple 2238 * C functions and variables are recognized using a simple
2219 * finite automaton. fvdef is its state variable. 2239 * finite automaton. fvdef is its state variable.
2220 */ 2240 */
2221enum 2241static enum
2222{ 2242{
2223 fvnone, /* nothing seen */ 2243 fvnone, /* nothing seen */
2224 fdefunkey, /* Emacs DEFUN keyword seen */ 2244 fdefunkey, /* Emacs DEFUN keyword seen */
@@ -2232,13 +2252,13 @@ enum
2232 vignore /* var-like: ignore until ';' */ 2252 vignore /* var-like: ignore until ';' */
2233} fvdef; 2253} fvdef;
2234 2254
2235bool fvextern; /* func or var: extern keyword seen; */ 2255static bool fvextern; /* func or var: extern keyword seen; */
2236 2256
2237/* 2257/*
2238 * typedefs are recognized using a simple finite automaton. 2258 * typedefs are recognized using a simple finite automaton.
2239 * typdef is its state variable. 2259 * typdef is its state variable.
2240 */ 2260 */
2241enum 2261static enum
2242{ 2262{
2243 tnone, /* nothing seen */ 2263 tnone, /* nothing seen */
2244 tkeyseen, /* typedef keyword seen */ 2264 tkeyseen, /* typedef keyword seen */
@@ -2253,7 +2273,7 @@ enum
2253 * using another simple finite automaton. `structdef' is its state 2273 * using another simple finite automaton. `structdef' is its state
2254 * variable. 2274 * variable.
2255 */ 2275 */
2256enum 2276static enum
2257{ 2277{
2258 snone, /* nothing seen yet, 2278 snone, /* nothing seen yet,
2259 or in struct body if cblev > 0 */ 2279 or in struct body if cblev > 0 */
@@ -2266,12 +2286,12 @@ enum
2266/* 2286/*
2267 * When objdef is different from onone, objtag is the name of the class. 2287 * When objdef is different from onone, objtag is the name of the class.
2268 */ 2288 */
2269char *objtag = "<uninited>"; 2289static char *objtag = "<uninited>";
2270 2290
2271/* 2291/*
2272 * Yet another little state machine to deal with preprocessor lines. 2292 * Yet another little state machine to deal with preprocessor lines.
2273 */ 2293 */
2274enum 2294static enum
2275{ 2295{
2276 dnone, /* nothing seen */ 2296 dnone, /* nothing seen */
2277 dsharpseen, /* '#' seen as first char on line */ 2297 dsharpseen, /* '#' seen as first char on line */
@@ -2283,7 +2303,7 @@ enum
2283 * State machine for Objective C protocols and implementations. 2303 * State machine for Objective C protocols and implementations.
2284 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995) 2304 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2285 */ 2305 */
2286enum 2306static enum
2287{ 2307{
2288 onone, /* nothing seen */ 2308 onone, /* nothing seen */
2289 oprotocol, /* @interface or @protocol seen */ 2309 oprotocol, /* @interface or @protocol seen */
@@ -2304,7 +2324,7 @@ enum
2304 * Use this structure to keep info about the token read, and how it 2324 * Use this structure to keep info about the token read, and how it
2305 * should be tagged. Used by the make_C_tag function to build a tag. 2325 * should be tagged. Used by the make_C_tag function to build a tag.
2306 */ 2326 */
2307struct tok 2327static struct tok
2308{ 2328{
2309 bool valid; 2329 bool valid;
2310 bool named; 2330 bool named;
@@ -2314,7 +2334,7 @@ struct tok
2314 long linepos; 2334 long linepos;
2315 char *line; 2335 char *line;
2316} token; /* latest token read */ 2336} token; /* latest token read */
2317linebuffer token_name; /* its name */ 2337static linebuffer token_name; /* its name */
2318 2338
2319/* 2339/*
2320 * Variables and functions for dealing with nested structures. 2340 * Variables and functions for dealing with nested structures.
@@ -2324,7 +2344,7 @@ static void pushclass_above __P((int, char *, int));
2324static void popclass_above __P((int)); 2344static void popclass_above __P((int));
2325static void write_classname __P((linebuffer *, char *qualifier)); 2345static void write_classname __P((linebuffer *, char *qualifier));
2326 2346
2327struct { 2347static struct {
2328 char **cname; /* nested class names */ 2348 char **cname; /* nested class names */
2329 int *cblev; /* nested class curly brace level */ 2349 int *cblev; /* nested class curly brace level */
2330 int nl; /* class nesting level (elements used) */ 2350 int nl; /* class nesting level (elements used) */
@@ -2711,7 +2731,7 @@ consider_token (str, len, c, c_extp, cblev, parlev, is_func_or_var)
2711 * the line currently read. By keeping two line buffers, and switching 2731 * the line currently read. By keeping two line buffers, and switching
2712 * them at end of line, it is possible to use those pointers. 2732 * them at end of line, it is possible to use those pointers.
2713 */ 2733 */
2714struct 2734static struct
2715{ 2735{
2716 long linepos; 2736 long linepos;
2717 linebuffer lb; 2737 linebuffer lb;
@@ -4027,8 +4047,8 @@ Perl_functions (inf)
4027 4047
4028 /* Perhaps I should back cp up one character, so the TAGS table 4048 /* Perhaps I should back cp up one character, so the TAGS table
4029 doesn't mention (and so depend upon) the following char. */ 4049 doesn't mention (and so depend upon) the following char. */
4030 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname, 4050 pfnote (varname, FALSE,
4031 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4051 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4032 } 4052 }
4033 } 4053 }
4034} 4054}
@@ -4507,12 +4527,12 @@ struct TEX_tabent
4507 int len; 4527 int len;
4508}; 4528};
4509 4529
4510struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */ 4530static struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4511 4531
4512/* Default set of control sequences to put into TEX_toktab. 4532/* Default set of control sequences to put into TEX_toktab.
4513 The value of environment var TEXTAGS is prepended to this. */ 4533 The value of environment var TEXTAGS is prepended to this. */
4514 4534
4515char *TEX_defenv = "\ 4535static char *TEX_defenv = "\
4516:chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\ 4536:chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4517:part:appendix:entry:index"; 4537:part:appendix:entry:index";
4518 4538
@@ -4520,9 +4540,9 @@ static void TEX_mode __P((FILE *));
4520static struct TEX_tabent *TEX_decode_env __P((char *, char *)); 4540static struct TEX_tabent *TEX_decode_env __P((char *, char *));
4521static int TEX_Token __P((char *)); 4541static int TEX_Token __P((char *));
4522 4542
4523char TEX_esc = '\\'; 4543static char TEX_esc = '\\';
4524char TEX_opgrp = '{'; 4544static char TEX_opgrp = '{';
4525char TEX_clgrp = '}'; 4545static char TEX_clgrp = '}';
4526 4546
4527/* 4547/*
4528 * TeX/LaTeX scanning loop. 4548 * TeX/LaTeX scanning loop.
@@ -5406,51 +5426,78 @@ readline (lbp, stream)
5406{ 5426{
5407 /* Read new line. */ 5427 /* Read new line. */
5408 long result = readline_internal (lbp, stream); 5428 long result = readline_internal (lbp, stream);
5429
5430 if (!no_line_directive
5431 && result > 12 && strneq (lbp->buffer, "#line ", 6))
5432 {
5433 int start, lno;
5434
5435 if (sscanf (lbp->buffer, "#line %d \"%n", &lno, &start) == 1)
5436 {
5437 char *endp = lbp->buffer + start;
5438
5439 while ((endp = etags_strchr (endp, '"')) != NULL
5440 && endp[-1] == '\\')
5441 endp++;
5442 if (endp != NULL)
5443 {
5444 int len = endp - (lbp->buffer + start);
5445
5446 if (!strneq (curfile, lbp->buffer + start, len))
5447 curfile = savenstr (lbp->buffer + start, len);
5448 lineno = lno;
5449 nocharno = TRUE; /* do not use char position for tags */
5450 return readline (lbp, stream);
5451 }
5452 }
5453 }
5409#ifdef ETAGS_REGEXPS 5454#ifdef ETAGS_REGEXPS
5410 int match; 5455 {
5411 pattern *pp; 5456 int match;
5457 pattern *pp;
5412 5458
5413 /* Match against relevant patterns. */ 5459 /* Match against relevant patterns. */
5414 if (lbp->len > 0) 5460 if (lbp->len > 0)
5415 for (pp = p_head; pp != NULL; pp = pp->p_next) 5461 for (pp = p_head; pp != NULL; pp = pp->p_next)
5416 { 5462 {
5417 /* Only use generic regexps or those for the current language. */ 5463 /* Only use generic regexps or those for the current language. */
5418 if (pp->lang != NULL && pp->lang != curlang) 5464 if (pp->lang != NULL && pp->lang != curlang)
5419 continue; 5465 continue;
5420 5466
5421 match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs); 5467 match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
5422 switch (match) 5468 switch (match)
5423 { 5469 {
5424 case -2: 5470 case -2:
5425 /* Some error. */ 5471 /* Some error. */
5426 if (!pp->error_signaled) 5472 if (!pp->error_signaled)
5427 { 5473 {
5428 error ("error while matching \"%s\"", pp->regex); 5474 error ("error while matching \"%s\"", pp->regex);
5429 pp->error_signaled = TRUE; 5475 pp->error_signaled = TRUE;
5430 } 5476 }
5431 break; 5477 break;
5432 case -1: 5478 case -1:
5433 /* No match. */ 5479 /* No match. */
5434 break; 5480 break;
5435 default: 5481 default:
5436 /* Match occurred. Construct a tag. */ 5482 /* Match occurred. Construct a tag. */
5437 if (pp->name_pattern[0] != '\0') 5483 if (pp->name_pattern[0] != '\0')
5438 { 5484 {
5439 /* Make a named tag. */ 5485 /* Make a named tag. */
5440 char *name = substitute (lbp->buffer, 5486 char *name = substitute (lbp->buffer,
5441 pp->name_pattern, &pp->regs); 5487 pp->name_pattern, &pp->regs);
5442 if (name != NULL) 5488 if (name != NULL)
5443 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno); 5489 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5444 } 5490 }
5445 else 5491 else
5446 { 5492 {
5447 /* Make an unnamed tag. */ 5493 /* Make an unnamed tag. */
5448 pfnote ((char *)NULL, TRUE, 5494 pfnote ((char *)NULL, TRUE,
5449 lbp->buffer, match, lineno, linecharno); 5495 lbp->buffer, match, lineno, linecharno);
5450 } 5496 }
5451 break; 5497 break;
5452 } 5498 }
5453 } 5499 }
5500 }
5454#endif /* ETAGS_REGEXPS */ 5501#endif /* ETAGS_REGEXPS */
5455 5502
5456 return result; 5503 return result;
@@ -5826,7 +5873,7 @@ linebuffer_setlen (lbp, toksize)
5826} 5873}
5827 5874
5828/* Like malloc but get fatal error if memory is exhausted. */ 5875/* Like malloc but get fatal error if memory is exhausted. */
5829PTR 5876static PTR
5830xmalloc (size) 5877xmalloc (size)
5831 unsigned int size; 5878 unsigned int size;
5832{ 5879{
@@ -5836,7 +5883,7 @@ xmalloc (size)
5836 return result; 5883 return result;
5837} 5884}
5838 5885
5839PTR 5886static PTR
5840xrealloc (ptr, size) 5887xrealloc (ptr, size)
5841 char *ptr; 5888 char *ptr;
5842 unsigned int size; 5889 unsigned int size;