/[emacs]/emacs/lib-src/etags.c
ViewVC logotype

Diff of /emacs/lib-src/etags.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3.7 by pot, Wed Dec 26 22:11:21 2001 UTC revision 3.8 by pot, Tue Mar 5 11:28:26 2002 UTC
# Line 33  Inc., 59 Temple Place - Suite 330, Bosto Line 33  Inc., 59 Temple Place - Suite 330, Bosto
33   *      Francesco Potort́ <pot@gnu.org> has maintained it since 1993.   *      Francesco Potort́ <pot@gnu.org> has maintained it since 1993.
34   */   */
35    
36  char pot_etags_version[] = "@(#) pot revision number is 14.35";  char pot_etags_version[] = "@(#) pot revision number is 14.39";
37    
38  #define TRUE    1  #define TRUE    1
39  #define FALSE   0  #define FALSE   0
# Line 299  static void print_language_names __P((vo Line 299  static void print_language_names __P((vo
299  static void print_version __P((void));  static void print_version __P((void));
300  static void print_help __P((void));  static void print_help __P((void));
301  int main __P((int, char **));  int main __P((int, char **));
 static int number_len __P((long));  
302    
303  static compressor *get_compressor_from_suffix __P((char *, char **));  static compressor *get_compressor_from_suffix __P((char *, char **));
304  static language *get_language_from_langname __P((const char *));  static language *get_language_from_langname __P((const char *));
305  static language *get_language_from_interpreter __P((char *));  static language *get_language_from_interpreter __P((char *));
306  static language *get_language_from_filename __P((char *));  static language *get_language_from_filename __P((char *));
 static int total_size_of_entries __P((node *));  
307  static long readline __P((linebuffer *, FILE *));  static long readline __P((linebuffer *, FILE *));
308  static long readline_internal __P((linebuffer *, FILE *));  static long readline_internal __P((linebuffer *, FILE *));
309  static bool nocase_tail __P((char *));  static bool nocase_tail __P((char *));
# Line 345  static char *absolute_dirname __P((char Line 343  static char *absolute_dirname __P((char
343  static bool filename_is_absolute __P((char *f));  static bool filename_is_absolute __P((char *f));
344  static void canonicalize_filename __P((char *));  static void canonicalize_filename __P((char *));
345  static void linebuffer_setlen __P((linebuffer *, int));  static void linebuffer_setlen __P((linebuffer *, int));
346  PTR xmalloc __P((unsigned int));  static PTR xmalloc __P((unsigned int));
347  PTR xrealloc __P((char *, unsigned int));  static PTR xrealloc __P((char *, unsigned int));
348    
349    
350  char searchar = '/';            /* use /.../ searches */  static char searchar = '/';     /* use /.../ searches */
   
 char *tagfile;                  /* output file */  
 char *progname;                 /* name this program was invoked with */  
 char *cwd;                      /* current working directory */  
 char *tagfiledir;               /* directory of tagfile */  
 FILE *tagf;                     /* ioptr for tags file */  
351    
352  char *curfile;                  /* current input file name */  static char *tagfile;           /* output file */
353  language *curlang;              /* current language */  static char *progname;          /* name this program was invoked with */
354    static char *cwd;               /* current working directory */
355    static char *tagfiledir;        /* directory of tagfile */
356    static FILE *tagf;              /* ioptr for tags file */
357    
358    static char *curfile;           /* current input file name */
359    static language *curlang;       /* current language */
360    
361    static int lineno;              /* line number of current line */
362    static long charno;             /* current character number */
363    static long linecharno;         /* charno of start of current line */
364    static char *dbp;               /* pointer to start of current tag */
365    static bool nocharno;           /* only use line number when making tag  */
366    static const int invalidcharno = -1;
367    
368  int lineno;                     /* line number of current line */  static node *head;              /* the head of the binary tree of tags */
 long charno;                    /* current character number */  
 long linecharno;                /* charno of start of current line */  
 char *dbp;                      /* pointer to start of current tag */  
369    
370  node *head;                     /* the head of the binary tree of tags */  static linebuffer lb;           /* the current line */
   
 linebuffer lb;                  /* the current line */  
371    
372  /* boolean "functions" (see init)       */  /* boolean "functions" (see init)       */
373  bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];  static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
374  char  static char
375    /* white chars */    /* white chars */
376    *white = " \f\t\n\r\v",    *white = " \f\t\n\r\v",
377    /* not in a name */    /* not in a name */
# Line 383  char Line 383  char
383    /* valid in-token chars */    /* valid in-token chars */
384    *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";    *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
385    
386  bool append_to_tagfile;         /* -a: append to tags */  static bool append_to_tagfile;  /* -a: append to tags */
387  /* The following four default to TRUE for etags, but to FALSE for ctags.  */  /* The following four default to TRUE for etags, but to FALSE for ctags.  */
388  bool typedefs;                  /* -t: create tags for C and Ada typedefs */  static bool typedefs;           /* -t: create tags for C and Ada typedefs */
389  bool typedefs_or_cplusplus;     /* -T: create tags for C typedefs, level */  static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
390                                  /* 0 struct/enum/union decls, and C++ */                                  /* 0 struct/enum/union decls, and C++ */
391                                  /* member functions. */                                  /* member functions. */
392  bool constantypedefs;           /* -d: create tags for C #define, enum */  static bool constantypedefs;    /* -d: create tags for C #define, enum */
393                                  /* constants and variables. */                                  /* constants and variables. */
394                                  /* -D: opposite of -d.  Default under ctags. */                                  /* -D: opposite of -d.  Default under ctags. */
395  bool declarations;              /* --declarations: tag them and extern in C&Co*/  static bool declarations;       /* --declarations: tag them and extern in C&Co*/
396  bool globals;                   /* create tags for global variables */  static bool globals;            /* create tags for global variables */
397  bool members;                   /* create tags for C member variables */  static bool no_line_directive;  /* ignore #line directives */
398  bool update;                    /* -u: update tags */  static bool members;            /* create tags for C member variables */
399  bool vgrind_style;              /* -v: create vgrind style index output */  static bool update;             /* -u: update tags */
400  bool no_warnings;               /* -w: suppress warnings */  static bool vgrind_style;       /* -v: create vgrind style index output */
401  bool cxref_style;               /* -x: create cxref style output */  static bool no_warnings;        /* -w: suppress warnings */
402  bool cplusplus;                 /* .[hc] means C++, not C */  static bool cxref_style;        /* -x: create cxref style output */
403  bool noindentypedefs;           /* -I: ignore indentation in C */  static bool cplusplus;          /* .[hc] means C++, not C */
404  bool packages_only;             /* --packages-only: in Ada, only tag packages*/  static bool noindentypedefs;    /* -I: ignore indentation in C */
405    static bool packages_only;      /* --packages-only: in Ada, only tag packages*/
406    
407  #ifdef LONG_OPTIONS  #ifdef LONG_OPTIONS
408  struct option longopts[] =  static struct option longopts[] =
409  {  {
410    { "packages-only",      no_argument,       &packages_only, TRUE  },    { "packages-only",      no_argument,       &packages_only,     TRUE  },
411    { "append",             no_argument,       NULL,           'a'   },    { "append",             no_argument,       NULL,               'a'   },
412    { "backward-search",    no_argument,       NULL,           'B'   },    { "backward-search",    no_argument,       NULL,               'B'   },
413    { "c++",                no_argument,       NULL,           'C'   },    { "c++",                no_argument,       NULL,               'C'   },
414    { "cxref",              no_argument,       NULL,           'x'   },    { "cxref",              no_argument,       NULL,               'x'   },
415    { "defines",            no_argument,       NULL,           'd'   },    { "defines",            no_argument,       NULL,               'd'   },
416    { "declarations",       no_argument,       &declarations,  TRUE  },    { "declarations",       no_argument,       &declarations,      TRUE  },
417    { "no-defines",         no_argument,       NULL,           'D'   },    { "no-defines",         no_argument,       NULL,               'D'   },
418    { "globals",            no_argument,       &globals,       TRUE  },    { "globals",            no_argument,       &globals,           TRUE  },
419    { "no-globals",         no_argument,       &globals,       FALSE },    { "no-globals",         no_argument,       &globals,           FALSE },
420    { "help",               no_argument,       NULL,           'h'   },    { "no-line-directive",  no_argument,       &no_line_directive, TRUE  },
421    { "help",               no_argument,       NULL,           'H'   },    { "help",               no_argument,       NULL,               'h'   },
422    { "ignore-indentation", no_argument,       NULL,           'I'   },    { "help",               no_argument,       NULL,               'H'   },
423    { "include",            required_argument, NULL,           'i'   },    { "ignore-indentation", no_argument,       NULL,               'I'   },
424    { "language",           required_argument, NULL,           'l'   },    { "include",            required_argument, NULL,               'i'   },
425    { "members",            no_argument,       &members,       TRUE  },    { "language",           required_argument, NULL,               'l'   },
426    { "no-members",         no_argument,       &members,       FALSE },    { "members",            no_argument,       &members,           TRUE  },
427    { "no-warn",            no_argument,       NULL,           'w'   },    { "no-members",         no_argument,       &members,           FALSE },
428    { "output",             required_argument, NULL,           'o'   },    { "no-warn",            no_argument,       NULL,               'w'   },
429      { "output",             required_argument, NULL,               'o'   },
430  #ifdef ETAGS_REGEXPS  #ifdef ETAGS_REGEXPS
431    { "regex",              required_argument, NULL,           'r'   },    { "regex",              required_argument, NULL,               'r'   },
432    { "no-regex",           no_argument,       NULL,           'R'   },    { "no-regex",           no_argument,       NULL,               'R'   },
433    { "ignore-case-regex",  required_argument, NULL,           'c'   },    { "ignore-case-regex",  required_argument, NULL,               'c'   },
434  #endif /* ETAGS_REGEXPS */  #endif /* ETAGS_REGEXPS */
435    { "typedefs",           no_argument,       NULL,           't'   },    { "typedefs",           no_argument,       NULL,               't'   },
436    { "typedefs-and-c++",   no_argument,       NULL,           'T'   },    { "typedefs-and-c++",   no_argument,       NULL,               'T'   },
437    { "update",             no_argument,       NULL,           'u'   },    { "update",             no_argument,       NULL,               'u'   },
438    { "version",            no_argument,       NULL,           'V'   },    { "version",            no_argument,       NULL,               'V'   },
439    { "vgrind",             no_argument,       NULL,           'v'   },    { "vgrind",             no_argument,       NULL,               'v'   },
440    { NULL }    { NULL }
441  };  };
442  #endif /* LONG_OPTIONS */  #endif /* LONG_OPTIONS */
# Line 454  typedef struct pattern Line 456  typedef struct pattern
456  } pattern;  } pattern;
457    
458  /* List of all regexps. */  /* List of all regexps. */
459  pattern *p_head = NULL;  static pattern *p_head = NULL;
460    
461  /* How many characters in the character set.  (From regex.c.)  */  /* How many characters in the character set.  (From regex.c.)  */
462  #define CHAR_SET_SIZE 256  #define CHAR_SET_SIZE 256
463  /* Translation table for case-insensitive matching. */  /* Translation table for case-insensitive matching. */
464  char lc_trans[CHAR_SET_SIZE];  static char lc_trans[CHAR_SET_SIZE];
465  #endif /* ETAGS_REGEXPS */  #endif /* ETAGS_REGEXPS */
466    
467  compressor compressors[] =  static compressor compressors[] =
468  {  {
469    { "z", "gzip -d -c"},    { "z", "gzip -d -c"},
470    { "Z", "gzip -d -c"},    { "Z", "gzip -d -c"},
# Line 477  compressor compressors[] = Line 479  compressor compressors[] =
479   */   */
480    
481  /* Non-NULL if language fixed. */  /* Non-NULL if language fixed. */
482  language *forced_lang = NULL;  static language *forced_lang = NULL;
483    
484  /* Ada code */  /* Ada code */
485  char *Ada_suffixes [] =  static char *Ada_suffixes [] =
486    { "ads", "adb", "ada", NULL };    { "ads", "adb", "ada", NULL };
487    
488  /* Assembly code */  /* Assembly code */
489  char *Asm_suffixes [] = { "a",  /* Unix assembler */  static char *Asm_suffixes [] =
490                            "asm", /* Microcontroller assembly */    { "a",        /* Unix assembler */
491                            "def", /* BSO/Tasking definition includes  */      "asm", /* Microcontroller assembly */
492                            "inc", /* Microcontroller include files */      "def", /* BSO/Tasking definition includes  */
493                            "ins", /* Microcontroller include files */      "inc", /* Microcontroller include files */
494                            "s", "sa", /* Unix assembler */      "ins", /* Microcontroller include files */
495                            "S",   /* cpp-processed Unix assembler */      "s", "sa", /* Unix assembler */
496                            "src", /* BSO/Tasking C compiler output */      "S",   /* cpp-processed Unix assembler */
497                            NULL      "src", /* BSO/Tasking C compiler output */
498                          };      NULL
499      };
500    
501  /* Note that .c and .h can be considered C++, if the --c++ flag was  /* Note that .c and .h can be considered C++, if the --c++ flag was
502     given, or if the `class' keyowrd is met inside the file.     given, or if the `class' keyowrd is met inside the file.
503     That is why default_C_entries is called for these. */     That is why default_C_entries is called for these. */
504  char *default_C_suffixes [] =  static char *default_C_suffixes [] =
505    { "c", "h", NULL };    { "c", "h", NULL };
506    
507  char *Cplusplus_suffixes [] =  static char *Cplusplus_suffixes [] =
508    { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",    { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
509      "M",                        /* Objective C++ */      "M",                        /* Objective C++ */
510      "pdb",                      /* Postscript with C syntax */      "pdb",                      /* Postscript with C syntax */
511      NULL };      NULL };
512    
513  char *Cjava_suffixes [] =  static char *Cjava_suffixes [] =
514    { "java", NULL };    { "java", NULL };
515    
516  char *Cobol_suffixes [] =  static char *Cobol_suffixes [] =
517    { "COB", "cob", NULL };    { "COB", "cob", NULL };
518    
519  char *Cstar_suffixes [] =  static char *Cstar_suffixes [] =
520    { "cs", "hs", NULL };    { "cs", "hs", NULL };
521    
522  char *Erlang_suffixes [] =  static char *Erlang_suffixes [] =
523    { "erl", "hrl", NULL };    { "erl", "hrl", NULL };
524    
525  char *Fortran_suffixes [] =  static char *Fortran_suffixes [] =
526    { "F", "f", "f90", "for", NULL };    { "F", "f", "f90", "for", NULL };
527    
528  char *Lisp_suffixes [] =  static char *Lisp_suffixes [] =
529    { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };    { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
530    
531  char *Makefile_filenames [] =  static char *Makefile_filenames [] =
532    { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};    { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};
533    
534  char *Pascal_suffixes [] =  static char *Pascal_suffixes [] =
535    { "p", "pas", NULL };    { "p", "pas", NULL };
536    
537  char *Perl_suffixes [] =  static char *Perl_suffixes [] =
538    { "pl", "pm", NULL };    { "pl", "pm", NULL };
539  char *Perl_interpreters [] =  
540    static char *Perl_interpreters [] =
541    { "perl", "@PERL@", NULL };    { "perl", "@PERL@", NULL };
542    
543  char *PHP_suffixes [] =  static char *PHP_suffixes [] =
544    { "php", "php3", "php4", NULL };    { "php", "php3", "php4", NULL };
545    
546  char *plain_C_suffixes [] =  static char *plain_C_suffixes [] =
547    { "lm",                       /* Objective lex file */    { "lm",                       /* Objective lex file */
548      "m",                        /* Objective C file */      "m",                        /* Objective C file */
549      "pc",                       /* Pro*C file */      "pc",                       /* Pro*C file */
550       NULL };       NULL };
551    
552  char *Postscript_suffixes [] =  static char *Postscript_suffixes [] =
553    { "ps", "psw", NULL };        /* .psw is for PSWrap */    { "ps", "psw", NULL };        /* .psw is for PSWrap */
554    
555  char *Prolog_suffixes [] =  static char *Prolog_suffixes [] =
556    { "prolog", NULL };    { "prolog", NULL };
557    
558  char *Python_suffixes [] =  static char *Python_suffixes [] =
559    { "py", NULL };    { "py", NULL };
560    
561  /* Can't do the `SCM' or `scm' prefix with a version number. */  /* Can't do the `SCM' or `scm' prefix with a version number. */
562  char *Scheme_suffixes [] =  static char *Scheme_suffixes [] =
563    { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };    { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };
564    
565  char *TeX_suffixes [] =  static char *TeX_suffixes [] =
566    { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };    { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };
567    
568  char *Texinfo_suffixes [] =  static char *Texinfo_suffixes [] =
569    { "texi", "texinfo", "txi", NULL };    { "texi", "texinfo", "txi", NULL };
570    
571  char *Yacc_suffixes [] =  static char *Yacc_suffixes [] =
572    { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */    { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */
573    
574  /*  /*
# Line 574  char *Yacc_suffixes [] = Line 578  char *Yacc_suffixes [] =
578   * name.  I just didn't.   * name.  I just didn't.
579   */   */
580    
581  language lang_names [] =  static language lang_names [] =
582  {  {
583    { "ada",        Ada_funcs,            NULL, Ada_suffixes,             NULL },    { "ada",        Ada_funcs,            NULL, Ada_suffixes,             NULL },
584    { "asm",        Asm_labels,           NULL, Asm_suffixes,             NULL },    { "asm",        Asm_labels,           NULL, Asm_suffixes,             NULL },
# Line 1042  main (argc, argv) Line 1046  main (argc, argv)
1046                }                }
1047            }            }
1048            break;            break;
 #ifdef ETAGS_REGEXPS  
1049          case 'r':          case 'r':
1050            argbuffer[current_arg].arg_type = at_regexp;            argbuffer[current_arg].arg_type = at_regexp;
1051            argbuffer[current_arg].what = optarg;            argbuffer[current_arg].what = optarg;
# Line 1058  main (argc, argv) Line 1061  main (argc, argv)
1061            argbuffer[current_arg].what = optarg;            argbuffer[current_arg].what = optarg;
1062            ++current_arg;            ++current_arg;
1063            break;            break;
 #endif /* ETAGS_REGEXPS */  
1064          case 'V':          case 'V':
1065            print_version ();            print_version ();
1066            break;            break;
# Line 1072  main (argc, argv) Line 1074  main (argc, argv)
1074          case 'T':          case 'T':
1075            typedefs = typedefs_or_cplusplus = TRUE;            typedefs = typedefs_or_cplusplus = TRUE;
1076            break;            break;
 #if (!CTAGS)  
1077            /* Etags options */            /* Etags options */
1078          case 'i':          case 'i':
1079            included_files[nincluded_files++] = optarg;            included_files[nincluded_files++] = optarg;
1080            break;            break;
 #else /* CTAGS */  
1081            /* Ctags options. */            /* Ctags options. */
1082          case 'B': searchar = '?';       break;          case 'B': searchar = '?';       break;
1083          case 'u': update = TRUE;        break;          case 'u': update = TRUE;        break;
1084          case 'v': vgrind_style = TRUE;  /*FALLTHRU*/          case 'v': vgrind_style = TRUE;  /*FALLTHRU*/
1085          case 'x': cxref_style = TRUE;   break;          case 'x': cxref_style = TRUE;   break;
1086          case 'w': no_warnings = TRUE;   break;          case 'w': no_warnings = TRUE;   break;
 #endif /* CTAGS */  
1087          default:          default:
1088            suggest_asking_for_help ();            suggest_asking_for_help ();
1089          }          }
# Line 1193  main (argc, argv) Line 1192  main (argc, argv)
1192    free_patterns ();    free_patterns ();
1193  #endif /* ETAGS_REGEXPS */  #endif /* ETAGS_REGEXPS */
1194    
1195    if (!CTAGS)    if (!CTAGS || cxref_style)
     {  
       while (nincluded_files-- > 0)  
         fprintf (tagf, "\f\n%s,include\n", *included_files++);  
   
       fclose (tagf);  
       exit (GOOD);  
     }  
   
   /* If CTAGS, we are here.  process_file did not write the tags yet,  
      because we want them ordered.  Let's do it now. */  
   if (cxref_style)  
1196      {      {
1197        put_entries (head);        put_entries (head);
1198        free_tree (head);        free_tree (head);
1199        head = NULL;        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);
1206        exit (GOOD);        exit (GOOD);
1207      }      }
1208    
# Line 1234  main (argc, argv) Line 1228  main (argc, argv)
1228    put_entries (head);    put_entries (head);
1229    free_tree (head);    free_tree (head);
1230    head = NULL;    head = NULL;
1231    fclose (tagf);    if (fclose (tagf) == EOF)
1232        pfatal (tagfile);
1233    
1234    if (update)    if (update)
1235      {      {
# Line 1379  process_file (file) Line 1374  process_file (file)
1374    compressor *compr;    compressor *compr;
1375    char *compressed_name, *uncompressed_name;    char *compressed_name, *uncompressed_name;
1376    char *ext, *real_name;    char *ext, *real_name;
1377      int retval;
1378    
1379    
1380    canonicalize_filename (file);    canonicalize_filename (file);
# Line 1486  process_file (file) Line 1482  process_file (file)
1482        goto exit;        goto exit;
1483      }      }
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 */
1497    find_entries (uncompressed_name, inf);    find_entries (uncompressed_name, inf);
1498    
1499    if (real_name == compressed_name)    if (real_name == compressed_name)
1500      pclose (inf);      retval = pclose (inf);
1501    else    else
1502      fclose (inf);      retval = fclose (inf);
1503      if (retval < 0)
1504    if (!CTAGS)      pfatal (file);
     {  
       char *filename;  
   
       if (filename_is_absolute (uncompressed_name))  
         {  
           /* file is an absolute file name.  Canonicalise it. */  
           filename = absolute_filename (uncompressed_name, cwd);  
         }  
       else  
         {  
           /* file is a file name relative to cwd.  Make it relative  
              to the directory of the tags file. */  
           filename = relative_filename (uncompressed_name, tagfiledir);  
         }  
       fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));  
       free (filename);  
       put_entries (head);  
       free_tree (head);  
       head = NULL;  
     }  
1505    
1506   exit:   exit:
1507    if (compressed_name) free(compressed_name);    if (compressed_name) free(compressed_name);
# Line 1552  init () Line 1540  init ()
1540   * This routine opens the specified file and calls the function   * This routine opens the specified file and calls the function
1541   * which finds the function and type definitions.   * which finds the function and type definitions.
1542   */   */
1543  node *last_node = NULL;  static node *last_node = NULL;
1544    
1545  static void  static void
1546  find_entries (file, inf)  find_entries (file, inf)
# Line 1563  find_entries (file, inf) Line 1551  find_entries (file, inf)
1551    language *lang;    language *lang;
1552    node *old_last_node;    node *old_last_node;
1553    
   /* Memory leakage here: the string pointed by curfile is  
      never released, because curfile is copied into np->file  
      for each node, to be used in CTAGS mode.  The amount of  
      memory leaked here is the sum of the lengths of the  
      file names. */  
   curfile = savestr (file);  
   
1554    /* If user specified a language, use it. */    /* If user specified a language, use it. */
1555    lang = forced_lang;    lang = forced_lang;
1556    if (lang != NULL && lang->function != NULL)    if (lang != NULL && lang->function != NULL)
# Line 1673  pfnote (name, is_func, linestart, linele Line 1654  pfnote (name, is_func, linestart, linele
1654    np->file = curfile;    np->file = curfile;
1655    np->is_func = is_func;    np->is_func = is_func;
1656    np->lno = lno;    np->lno = lno;
1657    /* Our char numbers are 0-base, because of C language tradition?    if (nocharno)
1658       ctags compatibility?  old versions compatibility?   I don't know.      np->cno = invalidcharno;
1659       Anyway, since emacs's are 1-base we expect etags.el to take care    else
1660       of the difference.  If we wanted to have 1-based numbers, we would      /* Our char numbers are 0-base, because of C language tradition?
1661       uncomment the +1 below. */         ctags compatibility?  old versions compatibility?   I don't know.
1662    np->cno = cno /* + 1 */ ;         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 */ ;
1666    np->left = np->right = NULL;    np->left = np->right = NULL;
1667    if (CTAGS && !cxref_style)    if (CTAGS && !cxref_style)
1668      {      {
# Line 1771  free_tree (np) Line 1755  free_tree (np)
1755    
1756  /*  /*
1757   * add_node ()   * add_node ()
1758   *      Adds a node to the tree of nodes.  In etags mode, we don't keep   *      Adds a node to the tree of nodes.  In etags mode, sort by file
1759   *      it sorted; we just keep a linear list.  In ctags mode, maintain   *      name.  In ctags mode, sort by tag name.  Make no attempt at
1760   *      an ordered tree, with no attempt at balancing.   *      balancing.
1761   *   *
1762   *      add_node is the only function allowed to add nodes, so it can   *      add_node is the only function allowed to add nodes, so it can
1763   *      maintain state.   *      maintain state.
# Line 1795  add_node (np, cur_node_p) Line 1779  add_node (np, cur_node_p)
1779    if (!CTAGS)    if (!CTAGS)
1780      {      {
1781        /* Etags Mode */        /* Etags Mode */
1782        if (last_node == NULL)        assert (last_node != NULL);
1783          fatal ("internal error in add_node", (char *)NULL);        /* For each file name, tags are in a linked sublist on the right
1784        last_node->right = np;           pointer.  The first tags of different files are a linked list
1785        last_node = np;           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);
1803      }      }
1804    else    else
1805      {      {
# Line 1837  add_node (np, cur_node_p) Line 1838  add_node (np, cur_node_p)
1838  }  }
1839    
1840    
1841    #if !CTAGS
1842    static int total_size_of_entries __P((node *));
1843    static int number_len __P((long));
1844    
1845    /* Length of a number's decimal representation. */
1846    static int
1847    number_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     */
1862    static int
1863    total_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    
1883  static void  static void
1884  put_entries (np)  put_entries (np)
1885       register node *np;       register node *np;
1886  {  {
1887    register char *sp;    register char *sp;
1888      static char *file = NULL;
1889    
1890    if (np == NULL)    if (np == NULL)
1891      return;      return;
1892    
1893    /* Output subentries that precede this one */    /* Output subentries that precede this one */
1894    put_entries (np->left);    if (CTAGS)
1895        put_entries (np->left);
1896    
1897    /* Output this entry */    /* Output this entry */
   
1898    if (!CTAGS)    if (!CTAGS)
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);
1910        if (np->name != NULL)        if (np->name != NULL)
1911          fprintf (tagf, "%s\177%s\001%d,%ld\n",          {
1912                   np->pat, np->name, np->lno, np->cno);            fputs (np->name, tagf);
1913              fputc ('\001', tagf);
1914            }
1915          fprintf (tagf, "%d,", np->lno);
1916          if (np->cno == invalidcharno)
1917            fputc ('\n', tagf);
1918        else        else
1919          fprintf (tagf, "%s\177%d,%ld\n",          fprintf (tagf, "%ld\n", np->cno);
                  np->pat, np->lno, np->cno);  
1920      }      }
1921    else    else
1922      {      {
1923          /* Ctags mode */
1924        if (np->name == NULL)        if (np->name == NULL)
1925          error ("internal error: NULL name in ctags mode.", (char *)NULL);          error ("internal error: NULL name in ctags mode.", (char *)NULL);
1926    
# Line 1899  put_entries (np) Line 1958  put_entries (np)
1958          }          }
1959      }      }
1960    
1961    
1962    /* Output subentries that follow this one */    /* Output subentries that follow this one */
1963    put_entries (np->right);    put_entries (np->right);
1964  }    if (!CTAGS)
1965        put_entries (np->left);
 /* Length of a number's decimal representation. */  
 static int  
 number_len (num)  
      long num;  
 {  
   int len = 1;  
   while ((num /= 10) > 0)  
     len += 1;  
   return len;  
 }  
   
 /*  
  * Return total number of characters that put_entries will output for  
  * the nodes in the subtree of the specified node.  Works only if  
  * we are not ctags, but called only in that case.  This count  
  * is irrelevant with the new tags.el, but is still supplied for  
  * backward compatibility.  
  */  
 static int  
 total_size_of_entries (np)  
      register node *np;  
 {  
   register int total;  
   
   if (np == NULL)  
     return 0;  
   
   for (total = 0; np != NULL; np = np->right)  
     {  
       /* Count left subentries. */  
       total += total_size_of_entries (np->left);  
   
       /* Count this entry */  
       total += strlen (np->pat) + 1;  
       total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;  
       if (np->name != NULL)  
         total += 1 + strlen (np->name); /* \001name */  
     }  
   
   return total;  
1966  }  }
1967    
1968    
# Line 2033  PSEUDO,                0,      st_C_gnumacro Line 2053  PSEUDO,                0,      st_C_gnumacro
2053  #DEFVAR_,       0,      st_C_gnumacro  #DEFVAR_,       0,      st_C_gnumacro
2054  %]  %]
2055  and replace lines between %< and %> with its output,  and replace lines between %< and %> with its output,
2056  then make in_word_set static. */  then make in_word_set and C_stab_entry static. */
2057  /*%<*/  /*%<*/
2058  /* C code produced by gperf version 2.7.1 (19981006 egcs) */  /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2059  /* Command-line: gperf -c -k 1,3 -o -p -r -t  */  /* Command-line: gperf -c -k 1,3 -o -p -r -t  */
# Line 2218  C_symtype (str, len, c_ext) Line 2238  C_symtype (str, len, c_ext)
2238   * C functions and variables are recognized using a simple   * C functions and variables are recognized using a simple
2239   * finite automaton.  fvdef is its state variable.   * finite automaton.  fvdef is its state variable.
2240   */   */
2241  enum  static enum
2242  {  {
2243    fvnone,                       /* nothing seen */    fvnone,                       /* nothing seen */
2244    fdefunkey,                    /* Emacs DEFUN keyword seen */    fdefunkey,                    /* Emacs DEFUN keyword seen */
# Line 2232  enum Line 2252  enum
2252    vignore                       /* var-like: ignore until ';' */    vignore                       /* var-like: ignore until ';' */
2253  } fvdef;  } fvdef;
2254    
2255  bool fvextern;                  /* func or var: extern keyword seen; */  static bool fvextern;           /* func or var: extern keyword seen; */
2256    
2257  /*  /*
2258   * typedefs are recognized using a simple finite automaton.   * typedefs are recognized using a simple finite automaton.
2259   * typdef is its state variable.   * typdef is its state variable.
2260   */   */
2261  enum  static enum
2262  {  {
2263    tnone,                        /* nothing seen */    tnone,                        /* nothing seen */
2264    tkeyseen,                     /* typedef keyword seen */    tkeyseen,                     /* typedef keyword seen */
# Line 2253  enum Line 2273  enum
2273   * using another simple finite automaton.  `structdef' is its state   * using another simple finite automaton.  `structdef' is its state
2274   * variable.   * variable.
2275   */   */
2276  enum  static enum
2277  {  {
2278    snone,                        /* nothing seen yet,    snone,                        /* nothing seen yet,
2279                                     or in struct body if cblev > 0 */                                     or in struct body if cblev > 0 */
# Line 2266  enum Line 2286  enum
2286  /*  /*
2287   * When objdef is different from onone, objtag is the name of the class.   * When objdef is different from onone, objtag is the name of the class.
2288   */   */
2289  char *objtag = "<uninited>";  static char *objtag = "<uninited>";
2290    
2291  /*  /*
2292   * Yet another little state machine to deal with preprocessor lines.   * Yet another little state machine to deal with preprocessor lines.
2293   */   */
2294  enum  static enum
2295  {  {
2296    dnone,                        /* nothing seen */    dnone,                        /* nothing seen */
2297    dsharpseen,                   /* '#' seen as first char on line */    dsharpseen,                   /* '#' seen as first char on line */
# Line 2283  enum Line 2303  enum
2303   * State machine for Objective C protocols and implementations.   * State machine for Objective C protocols and implementations.
2304   * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)   * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2305   */   */
2306  enum  static enum
2307  {  {
2308    onone,                        /* nothing seen */    onone,                        /* nothing seen */
2309    oprotocol,                    /* @interface or @protocol seen */    oprotocol,                    /* @interface or @protocol seen */
# Line 2304  enum Line 2324  enum
2324   * Use this structure to keep info about the token read, and how it   * Use this structure to keep info about the token read, and how it
2325   * should be tagged.  Used by the make_C_tag function to build a tag.   * should be tagged.  Used by the make_C_tag function to build a tag.
2326   */   */
2327  struct tok  static struct tok
2328  {  {
2329    bool valid;    bool valid;
2330    bool named;    bool named;
# Line 2314  struct tok Line 2334  struct tok
2334    long linepos;    long linepos;
2335    char *line;    char *line;
2336  } token;                        /* latest token read */  } token;                        /* latest token read */
2337  linebuffer token_name;          /* its name */  static linebuffer token_name;   /* its name */
2338    
2339  /*  /*
2340   * Variables and functions for dealing with nested structures.   * Variables and functions for dealing with nested structures.
# Line 2324  static void pushclass_above __P((int, ch Line 2344  static void pushclass_above __P((int, ch
2344  static void popclass_above __P((int));  static void popclass_above __P((int));
2345  static void write_classname __P((linebuffer *, char *qualifier));  static void write_classname __P((linebuffer *, char *qualifier));
2346    
2347  struct {  static struct {
2348    char **cname;                 /* nested class names */    char **cname;                 /* nested class names */
2349    int *cblev;                   /* nested class curly brace level */    int *cblev;                   /* nested class curly brace level */
2350    int nl;                       /* class nesting level (elements used) */    int nl;                       /* class nesting level (elements used) */
# Line 2711  consider_token (str, len, c, c_extp, cbl Line 2731  consider_token (str, len, c, c_extp, cbl
2731   * the line currently read.  By keeping two line buffers, and switching   * the line currently read.  By keeping two line buffers, and switching
2732   * them at end of line, it is possible to use those pointers.   * them at end of line, it is possible to use those pointers.
2733   */   */
2734  struct  static struct
2735  {  {
2736    long linepos;    long linepos;
2737    linebuffer lb;    linebuffer lb;
# Line 4027  Perl_functions (inf) Line 4047  Perl_functions (inf)
4047    
4048            /* Perhaps I should back cp up one character, so the TAGS table            /* Perhaps I should back cp up one character, so the TAGS table
4049               doesn't mention (and so depend upon) the following char. */               doesn't mention (and so depend upon) the following char. */
4050            pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,            pfnote (varname, FALSE,
4051                    FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);                    lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4052          }          }
4053      }      }
4054  }  }
# Line 4507  struct TEX_tabent Line 4527  struct TEX_tabent
4527    int len;    int len;
4528  };  };
4529    
4530  struct TEX_tabent *TEX_toktab = NULL;   /* Table with tag tokens */  static struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4531    
4532  /* Default set of control sequences to put into TEX_toktab.  /* Default set of control sequences to put into TEX_toktab.
4533     The value of environment var TEXTAGS is prepended to this.  */     The value of environment var TEXTAGS is prepended to this.  */
4534    
4535  char *TEX_defenv = "\  static char *TEX_defenv = "\
4536  :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\  :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4537  :part:appendix:entry:index";  :part:appendix:entry:index";
4538    
# Line 4520  static void TEX_mode __P((FILE *)); Line 4540  static void TEX_mode __P((FILE *));
4540  static struct TEX_tabent *TEX_decode_env __P((char *, char *));  static struct TEX_tabent *TEX_decode_env __P((char *, char *));
4541  static int TEX_Token __P((char *));  static int TEX_Token __P((char *));
4542    
4543  char TEX_esc = '\\';  static char TEX_esc = '\\';
4544  char TEX_opgrp = '{';  static char TEX_opgrp = '{';
4545  char TEX_clgrp = '}';  static char TEX_clgrp = '}';
4546    
4547  /*  /*
4548   * TeX/LaTeX scanning loop.   * TeX/LaTeX scanning loop.
# Line 5406  readline (lbp, stream) Line 5426  readline (lbp, stream)
5426  {  {
5427    /* Read new line. */    /* Read new line. */
5428    long result = readline_internal (lbp, stream);    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        }
5454  #ifdef ETAGS_REGEXPS  #ifdef ETAGS_REGEXPS
5455    int match;    {
5456    pattern *pp;      int match;
5457        pattern *pp;
5458    
5459    /* Match against relevant patterns. */      /* Match against relevant patterns. */
5460    if (lbp->len > 0)      if (lbp->len > 0)
5461      for (pp = p_head; pp != NULL; pp = pp->p_next)        for (pp = p_head; pp != NULL; pp = pp->p_next)
5462        {          {
5463          /* Only use generic regexps or those for the current language. */            /* Only use generic regexps or those for the current language. */
5464          if (pp->lang != NULL && pp->lang != curlang)            if (pp->lang != NULL && pp->lang != curlang)
5465            continue;              continue;
5466    
5467          match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);            match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
5468          switch (match)            switch (match)
5469            {              {
5470            case -2:              case -2:
5471              /* Some error. */                /* Some error. */
5472              if (!pp->error_signaled)                if (!pp->error_signaled)
5473                {                  {
5474                  error ("error while matching \"%s\"", pp->regex);                    error ("error while matching \"%s\"", pp->regex);
5475                  pp->error_signaled = TRUE;                    pp->error_signaled = TRUE;
5476                }                  }
5477              break;                break;
5478            case -1:              case -1:
5479              /* No match. */                /* No match. */
5480              break;                break;
5481            default:              default:
5482              /* Match occurred.  Construct a tag. */                /* Match occurred.  Construct a tag. */
5483              if (pp->name_pattern[0] != '\0')                if (pp->name_pattern[0] != '\0')
5484                {                  {
5485                  /* Make a named tag. */                    /* Make a named tag. */
5486                  char *name = substitute (lbp->buffer,                    char *name = substitute (lbp->buffer,
5487                                           pp->name_pattern, &pp->regs);                                             pp->name_pattern, &pp->regs);
5488                  if (name != NULL)                    if (name != NULL)
5489                    pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);                      pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5490                }                  }
5491              else                else
5492                {                  {
5493                  /* Make an unnamed tag. */                    /* Make an unnamed tag. */
5494                  pfnote ((char *)NULL, TRUE,                    pfnote ((char *)NULL, TRUE,
5495                          lbp->buffer, match, lineno, linecharno);                            lbp->buffer, match, lineno, linecharno);
5496                }                  }
5497              break;                break;
5498            }              }
5499        }          }
5500      }
5501  #endif /* ETAGS_REGEXPS */  #endif /* ETAGS_REGEXPS */
5502    
5503    return result;    return result;
# Line 5826  linebuffer_setlen (lbp, toksize) Line 5873  linebuffer_setlen (lbp, toksize)
5873  }  }
5874    
5875  /* Like malloc but get fatal error if memory is exhausted.  */  /* Like malloc but get fatal error if memory is exhausted.  */
5876  PTR  static PTR
5877  xmalloc (size)  xmalloc (size)
5878       unsigned int size;       unsigned int size;
5879  {  {
# Line 5836  xmalloc (size) Line 5883  xmalloc (size)
5883    return result;    return result;
5884  }  }
5885    
5886  PTR  static PTR
5887  xrealloc (ptr, size)  xrealloc (ptr, size)
5888       char *ptr;       char *ptr;
5889       unsigned int size;       unsigned int size;

Legend:
Removed from v.3.7  
changed lines
  Added in v.3.8

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26