diff options
| author | Francesco Potortì | 2002-08-28 10:35:51 +0000 |
|---|---|---|
| committer | Francesco Potortì | 2002-08-28 10:35:51 +0000 |
| commit | 61a1f6fa606ddaeec05718b8d96244f7bac97232 (patch) | |
| tree | 0caab0edce648b84f4522ec34a2d072a4e369847 | |
| parent | 87046df8c763660ac9c81307de5195b6761e2329 (diff) | |
| download | emacs-61a1f6fa606ddaeec05718b8d96244f7bac97232.tar.gz emacs-61a1f6fa606ddaeec05718b8d96244f7bac97232.zip | |
Two bug corrections and one new feature.
(Ada_funcs): Do not tag "use type Xxxx;".
New language HTML.
(make_tag): Never generate null length tag names.
(linebuffer_init): Renamed from initbuffer. All callers changed.
(pattern): Structure renamed to `regexp', member regex renamed to
pattern.
(node_st): Member pat renamed to regex.
(pattern); New member force_explicit_name, for future use. Now
always set to true, cannot be reset.
(add_regex, regex_tag_multiline, readline): Use it.
(main): Free some global structures.
(fdesc): New member `written'.
(readline, process_file): Initialise it.
(put_entries): Set it.
(main): Use it to create entries for files without tags.
(total_size_of_entries): Do not count invalid tags.
(etags_strcasecmp): Like BSD's, for compatibility.
(strcaseeq): Make it into a macro.
| -rw-r--r-- | lib-src/etags.c | 501 |
1 files changed, 345 insertions, 156 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c index e6ca44d968e..2e3ac148379 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | * | 35 | * |
| 36 | */ | 36 | */ |
| 37 | 37 | ||
| 38 | char pot_etags_version[] = "@(#) pot revision number is 16.32"; | 38 | char pot_etags_version[] = "@(#) pot revision number is 16.42"; |
| 39 | 39 | ||
| 40 | #define TRUE 1 | 40 | #define TRUE 1 |
| 41 | #define FALSE 0 | 41 | #define FALSE 0 |
| @@ -187,15 +187,17 @@ If you want regular expression support, you should delete this notice and | |||
| 187 | #endif | 187 | #endif |
| 188 | 188 | ||
| 189 | #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t)) | 189 | #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t)) |
| 190 | #define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t)) | ||
| 190 | #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n)) | 191 | #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n)) |
| 192 | #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n)) | ||
| 191 | 193 | ||
| 192 | #define CHARS 256 /* 2^sizeof(char) */ | 194 | #define CHARS 256 /* 2^sizeof(char) */ |
| 193 | #define CHAR(x) ((unsigned int)(x) & (CHARS - 1)) | 195 | #define CHAR(x) ((unsigned int)(x) & (CHARS - 1)) |
| 194 | #define iswhite(c) (_wht[CHAR(c)]) /* c is white */ | 196 | #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */ |
| 195 | #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ | 197 | #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */ |
| 196 | #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ | 198 | #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */ |
| 197 | #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ | 199 | #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */ |
| 198 | #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ | 200 | #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */ |
| 199 | 201 | ||
| 200 | #define ISALNUM(c) isalnum (CHAR(c)) | 202 | #define ISALNUM(c) isalnum (CHAR(c)) |
| 201 | #define ISALPHA(c) isalpha (CHAR(c)) | 203 | #define ISALPHA(c) isalpha (CHAR(c)) |
| @@ -254,6 +256,7 @@ typedef struct fdesc | |||
| 254 | language *lang; /* language of file */ | 256 | language *lang; /* language of file */ |
| 255 | char *prop; /* file properties to write in tagfile */ | 257 | char *prop; /* file properties to write in tagfile */ |
| 256 | bool usecharno; /* etags tags shall contain char number */ | 258 | bool usecharno; /* etags tags shall contain char number */ |
| 259 | bool written; /* entry written in the tags file */ | ||
| 257 | } fdesc; | 260 | } fdesc; |
| 258 | 261 | ||
| 259 | typedef struct node_st | 262 | typedef struct node_st |
| @@ -261,9 +264,9 @@ typedef struct node_st | |||
| 261 | struct node_st *left, *right; /* left and right sons */ | 264 | struct node_st *left, *right; /* left and right sons */ |
| 262 | fdesc *fdp; /* description of file to whom tag belongs */ | 265 | fdesc *fdp; /* description of file to whom tag belongs */ |
| 263 | char *name; /* tag name */ | 266 | char *name; /* tag name */ |
| 264 | char *pat; /* search pattern */ | 267 | char *regex; /* search regexp */ |
| 265 | bool valid; /* write this tag on the tag file */ | 268 | bool valid; /* write this tag on the tag file */ |
| 266 | bool is_func; /* function tag: use pattern in CTAGS mode */ | 269 | bool is_func; /* function tag: use regexp in CTAGS mode */ |
| 267 | bool been_warned; /* warning already given for duplicated tag */ | 270 | bool been_warned; /* warning already given for duplicated tag */ |
| 268 | int lno; /* line number tag is on */ | 271 | int lno; /* line number tag is on */ |
| 269 | long cno; /* character number line starts on */ | 272 | long cno; /* character number line starts on */ |
| @@ -298,18 +301,19 @@ typedef struct | |||
| 298 | 301 | ||
| 299 | #ifdef ETAGS_REGEXPS | 302 | #ifdef ETAGS_REGEXPS |
| 300 | /* Structure defining a regular expression. */ | 303 | /* Structure defining a regular expression. */ |
| 301 | typedef struct pattern | 304 | typedef struct regexp |
| 302 | { | 305 | { |
| 303 | struct pattern *p_next; | 306 | struct regexp *p_next; /* pointer to next in list */ |
| 304 | language *lang; | 307 | language *lang; /* if set, use only for this language */ |
| 305 | char *regex; | 308 | char *pattern; /* the regexp pattern */ |
| 306 | struct re_pattern_buffer *pat; | 309 | char *name; /* tag name */ |
| 307 | struct re_registers regs; | 310 | struct re_pattern_buffer *pat; /* the compiled pattern */ |
| 308 | char *name_pattern; | 311 | struct re_registers regs; /* re registers */ |
| 309 | bool error_signaled; | 312 | bool error_signaled; /* already signaled for this regexp */ |
| 310 | bool ignore_case; | 313 | bool force_explicit_name; /* do not allow implict tag name */ |
| 311 | bool multi_line; | 314 | bool ignore_case; /* ignore case when matching */ |
| 312 | } pattern; | 315 | bool multi_line; /* do a multi-line match on the whole file */ |
| 316 | } regexp; | ||
| 313 | #endif /* ETAGS_REGEXPS */ | 317 | #endif /* ETAGS_REGEXPS */ |
| 314 | 318 | ||
| 315 | 319 | ||
| @@ -327,7 +331,7 @@ static void Cplusplus_entries __P((FILE *)); | |||
| 327 | static void Cstar_entries __P((FILE *)); | 331 | static void Cstar_entries __P((FILE *)); |
| 328 | static void Erlang_functions __P((FILE *)); | 332 | static void Erlang_functions __P((FILE *)); |
| 329 | static void Fortran_functions __P((FILE *)); | 333 | static void Fortran_functions __P((FILE *)); |
| 330 | static void Yacc_entries __P((FILE *)); | 334 | static void HTML_labels __P((FILE *)); |
| 331 | static void Lisp_functions __P((FILE *)); | 335 | static void Lisp_functions __P((FILE *)); |
| 332 | static void Makefile_targets __P((FILE *)); | 336 | static void Makefile_targets __P((FILE *)); |
| 333 | static void Pascal_functions __P((FILE *)); | 337 | static void Pascal_functions __P((FILE *)); |
| @@ -339,6 +343,7 @@ static void Python_functions __P((FILE *)); | |||
| 339 | static void Scheme_functions __P((FILE *)); | 343 | static void Scheme_functions __P((FILE *)); |
| 340 | static void TeX_commands __P((FILE *)); | 344 | static void TeX_commands __P((FILE *)); |
| 341 | static void Texinfo_nodes __P((FILE *)); | 345 | static void Texinfo_nodes __P((FILE *)); |
| 346 | static void Yacc_entries __P((FILE *)); | ||
| 342 | static void just_read_file __P((FILE *)); | 347 | static void just_read_file __P((FILE *)); |
| 343 | 348 | ||
| 344 | static void print_language_names __P((void)); | 349 | static void print_language_names __P((void)); |
| @@ -357,7 +362,7 @@ static void get_tag __P((char *, char **)); | |||
| 357 | 362 | ||
| 358 | #ifdef ETAGS_REGEXPS | 363 | #ifdef ETAGS_REGEXPS |
| 359 | static void analyse_regex __P((char *)); | 364 | static void analyse_regex __P((char *)); |
| 360 | static void free_patterns __P((void)); | 365 | static void free_regexps __P((void)); |
| 361 | static void regex_tag_multiline __P((void)); | 366 | static void regex_tag_multiline __P((void)); |
| 362 | #endif /* ETAGS_REGEXPS */ | 367 | #endif /* ETAGS_REGEXPS */ |
| 363 | static void error __P((const char *, const char *)); | 368 | static void error __P((const char *, const char *)); |
| @@ -367,7 +372,6 @@ static void pfatal __P((char *)); | |||
| 367 | static void add_node __P((node *, node **)); | 372 | static void add_node __P((node *, node **)); |
| 368 | 373 | ||
| 369 | static void init __P((void)); | 374 | static void init __P((void)); |
| 370 | static void initbuffer __P((linebuffer *)); | ||
| 371 | static void process_file_name __P((char *, language *)); | 375 | static void process_file_name __P((char *, language *)); |
| 372 | static void process_file __P((FILE *, char *, language *)); | 376 | static void process_file __P((FILE *, char *, language *)); |
| 373 | static void find_entries __P((FILE *)); | 377 | static void find_entries __P((FILE *)); |
| @@ -385,13 +389,15 @@ static char *savenstr __P((char *, int)); | |||
| 385 | static char *savestr __P((char *)); | 389 | static char *savestr __P((char *)); |
| 386 | static char *etags_strchr __P((const char *, int)); | 390 | static char *etags_strchr __P((const char *, int)); |
| 387 | static char *etags_strrchr __P((const char *, int)); | 391 | static char *etags_strrchr __P((const char *, int)); |
| 388 | static bool strcaseeq __P((const char *, const char *)); | 392 | static int etags_strcasecmp __P((const char *, const char *)); |
| 393 | static int etags_strncasecmp __P((const char *, const char *, int)); | ||
| 389 | static char *etags_getcwd __P((void)); | 394 | static char *etags_getcwd __P((void)); |
| 390 | static char *relative_filename __P((char *, char *)); | 395 | static char *relative_filename __P((char *, char *)); |
| 391 | static char *absolute_filename __P((char *, char *)); | 396 | static char *absolute_filename __P((char *, char *)); |
| 392 | static char *absolute_dirname __P((char *, char *)); | 397 | static char *absolute_dirname __P((char *, char *)); |
| 393 | static bool filename_is_absolute __P((char *f)); | 398 | static bool filename_is_absolute __P((char *f)); |
| 394 | static void canonicalize_filename __P((char *)); | 399 | static void canonicalize_filename __P((char *)); |
| 400 | static void linebuffer_init __P((linebuffer *)); | ||
| 395 | static void linebuffer_setlen __P((linebuffer *, int)); | 401 | static void linebuffer_setlen __P((linebuffer *, int)); |
| 396 | static PTR xmalloc __P((unsigned int)); | 402 | static PTR xmalloc __P((unsigned int)); |
| 397 | static PTR xrealloc __P((char *, unsigned int)); | 403 | static PTR xrealloc __P((char *, unsigned int)); |
| @@ -419,6 +425,7 @@ static node *last_node; /* the last node created */ | |||
| 419 | 425 | ||
| 420 | static linebuffer lb; /* the current line */ | 426 | static linebuffer lb; /* the current line */ |
| 421 | static linebuffer filebuf; /* a buffer containing the whole file */ | 427 | static linebuffer filebuf; /* a buffer containing the whole file */ |
| 428 | static linebuffer token_name; /* a buffer containing a tag name */ | ||
| 422 | 429 | ||
| 423 | /* boolean "functions" (see init) */ | 430 | /* boolean "functions" (see init) */ |
| 424 | static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; | 431 | static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; |
| @@ -459,7 +466,7 @@ static bool packages_only; /* --packages-only: in Ada, only tag packages*/ | |||
| 459 | static bool parsing_stdin; /* --parse-stdin used */ | 466 | static bool parsing_stdin; /* --parse-stdin used */ |
| 460 | 467 | ||
| 461 | #ifdef ETAGS_REGEXPS | 468 | #ifdef ETAGS_REGEXPS |
| 462 | static pattern *p_head; /* list of all regexps */ | 469 | static regexp *p_head; /* list of all regexps */ |
| 463 | static bool need_filebuf; /* some regexes are multi-line */ | 470 | static bool need_filebuf; /* some regexes are multi-line */ |
| 464 | #else | 471 | #else |
| 465 | # define need_filebuf FALSE | 472 | # define need_filebuf FALSE |
| @@ -566,6 +573,9 @@ static char *Erlang_suffixes [] = | |||
| 566 | static char *Fortran_suffixes [] = | 573 | static char *Fortran_suffixes [] = |
| 567 | { "F", "f", "f90", "for", NULL }; | 574 | { "F", "f", "f90", "for", NULL }; |
| 568 | 575 | ||
| 576 | static char *HTML_suffixes [] = | ||
| 577 | { "htm", "html", "shtml", NULL }; | ||
| 578 | |||
| 569 | static char *Lisp_suffixes [] = | 579 | static char *Lisp_suffixes [] = |
| 570 | { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL }; | 580 | { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL }; |
| 571 | 581 | ||
| @@ -629,6 +639,7 @@ static language lang_names [] = | |||
| 629 | { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, | 639 | { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, |
| 630 | { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL }, | 640 | { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL }, |
| 631 | { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL }, | 641 | { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL }, |
| 642 | { "html", FALSE, HTML_labels, NULL, HTML_suffixes, NULL }, | ||
| 632 | { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL }, | 643 | { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL }, |
| 633 | { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL }, | 644 | { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL }, |
| 634 | { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL }, | 645 | { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL }, |
| @@ -1142,9 +1153,10 @@ main (argc, argv) | |||
| 1142 | 1153 | ||
| 1143 | init (); /* set up boolean "functions" */ | 1154 | init (); /* set up boolean "functions" */ |
| 1144 | 1155 | ||
| 1145 | initbuffer (&lb); | 1156 | linebuffer_init (&lb); |
| 1146 | initbuffer (&filename_lb); | 1157 | linebuffer_init (&filename_lb); |
| 1147 | initbuffer (&filebuf); | 1158 | linebuffer_init (&filebuf); |
| 1159 | linebuffer_init (&token_name); | ||
| 1148 | 1160 | ||
| 1149 | if (!CTAGS) | 1161 | if (!CTAGS) |
| 1150 | { | 1162 | { |
| @@ -1222,9 +1234,11 @@ main (argc, argv) | |||
| 1222 | } | 1234 | } |
| 1223 | 1235 | ||
| 1224 | #ifdef ETAGS_REGEXPS | 1236 | #ifdef ETAGS_REGEXPS |
| 1225 | free_patterns (); | 1237 | free_regexps (); |
| 1226 | #endif /* ETAGS_REGEXPS */ | 1238 | #endif /* ETAGS_REGEXPS */ |
| 1239 | free (lb.buffer); | ||
| 1227 | free (filebuf.buffer); | 1240 | free (filebuf.buffer); |
| 1241 | free (token_name.buffer); | ||
| 1228 | 1242 | ||
| 1229 | if (!CTAGS || cxref_style) | 1243 | if (!CTAGS || cxref_style) |
| 1230 | { | 1244 | { |
| @@ -1232,8 +1246,17 @@ main (argc, argv) | |||
| 1232 | free_tree (nodehead); | 1246 | free_tree (nodehead); |
| 1233 | nodehead = NULL; | 1247 | nodehead = NULL; |
| 1234 | if (!CTAGS) | 1248 | if (!CTAGS) |
| 1235 | while (nincluded_files-- > 0) | 1249 | { |
| 1236 | fprintf (tagf, "\f\n%s,include\n", *included_files++); | 1250 | fdesc *fdp; |
| 1251 | |||
| 1252 | /* Output file entries that have no tags. */ | ||
| 1253 | for (fdp = fdhead; fdp != NULL; fdp = fdp->next) | ||
| 1254 | if (!fdp->written) | ||
| 1255 | fprintf (tagf, "\f\n%s,0\n", fdp->taggedfname); | ||
| 1256 | |||
| 1257 | while (nincluded_files-- > 0) | ||
| 1258 | fprintf (tagf, "\f\n%s,include\n", *included_files++); | ||
| 1259 | } | ||
| 1237 | 1260 | ||
| 1238 | if (fclose (tagf) == EOF) | 1261 | if (fclose (tagf) == EOF) |
| 1239 | pfatal (tagfile); | 1262 | pfatal (tagfile); |
| @@ -1562,6 +1585,7 @@ process_file (fh, fn, lang) | |||
| 1562 | } | 1585 | } |
| 1563 | fdp->usecharno = TRUE; /* use char position when making tags */ | 1586 | fdp->usecharno = TRUE; /* use char position when making tags */ |
| 1564 | fdp->prop = NULL; | 1587 | fdp->prop = NULL; |
| 1588 | fdp->written = FALSE; /* not written on tags file yet */ | ||
| 1565 | 1589 | ||
| 1566 | fdhead = fdp; | 1590 | fdhead = fdp; |
| 1567 | curfdp = fdhead; /* the current file description */ | 1591 | curfdp = fdhead; /* the current file description */ |
| @@ -1761,7 +1785,7 @@ find_entries (inf) | |||
| 1761 | assert (parser != NULL); | 1785 | assert (parser != NULL); |
| 1762 | 1786 | ||
| 1763 | /* Generic initialisations before reading from file. */ | 1787 | /* Generic initialisations before reading from file. */ |
| 1764 | filebuf.len = 0; /* reset the file buffer */ | 1788 | linebuffer_setlen (&filebuf, 0); /* reset the file buffer */ |
| 1765 | 1789 | ||
| 1766 | /* Generic initialisations before parsing file with readline. */ | 1790 | /* Generic initialisations before parsing file with readline. */ |
| 1767 | lineno = 0; /* reset global line number */ | 1791 | lineno = 0; /* reset global line number */ |
| @@ -1809,9 +1833,11 @@ make_tag (name, namelen, is_func, linestart, linelen, lno, cno) | |||
| 1809 | int lno; /* line number */ | 1833 | int lno; /* line number */ |
| 1810 | long cno; /* character number */ | 1834 | long cno; /* character number */ |
| 1811 | { | 1835 | { |
| 1812 | bool named = TRUE; | 1836 | bool named = (name != NULL && namelen > 0); |
| 1813 | 1837 | ||
| 1814 | if (!CTAGS && name != NULL && namelen > 0) | 1838 | if (!CTAGS && named) /* maybe set named to false */ |
| 1839 | /* Let's try to make an implicit tag name, that is, create an unnamed tag | ||
| 1840 | such that etags.el can guess a name from it. */ | ||
| 1815 | { | 1841 | { |
| 1816 | int i; | 1842 | int i; |
| 1817 | register char *cp = name; | 1843 | register char *cp = name; |
| @@ -1885,12 +1911,12 @@ pfnote (name, is_func, linestart, linelen, lno, cno) | |||
| 1885 | if (CTAGS && !cxref_style) | 1911 | if (CTAGS && !cxref_style) |
| 1886 | { | 1912 | { |
| 1887 | if (strlen (linestart) < 50) | 1913 | if (strlen (linestart) < 50) |
| 1888 | np->pat = concat (linestart, "$", ""); | 1914 | np->regex = concat (linestart, "$", ""); |
| 1889 | else | 1915 | else |
| 1890 | np->pat = savenstr (linestart, 50); | 1916 | np->regex = savenstr (linestart, 50); |
| 1891 | } | 1917 | } |
| 1892 | else | 1918 | else |
| 1893 | np->pat = savenstr (linestart, linelen); | 1919 | np->regex = savenstr (linestart, linelen); |
| 1894 | 1920 | ||
| 1895 | add_node (np, &nodehead); | 1921 | add_node (np, &nodehead); |
| 1896 | } | 1922 | } |
| @@ -1909,7 +1935,7 @@ free_tree (np) | |||
| 1909 | free_tree (np->left); | 1935 | free_tree (np->left); |
| 1910 | if (np->name != NULL) | 1936 | if (np->name != NULL) |
| 1911 | free (np->name); | 1937 | free (np->name); |
| 1912 | free (np->pat); | 1938 | free (np->regex); |
| 1913 | free (np); | 1939 | free (np); |
| 1914 | np = node_right; | 1940 | np = node_right; |
| 1915 | } | 1941 | } |
| @@ -2083,15 +2109,16 @@ total_size_of_entries (np) | |||
| 2083 | register int total = 0; | 2109 | register int total = 0; |
| 2084 | 2110 | ||
| 2085 | for (; np != NULL; np = np->right) | 2111 | for (; np != NULL; np = np->right) |
| 2086 | { | 2112 | if (np->valid) |
| 2087 | total += strlen (np->pat) + 1; /* pat\177 */ | 2113 | { |
| 2088 | if (np->name != NULL) | 2114 | total += strlen (np->regex) + 1; /* pat\177 */ |
| 2089 | total += strlen (np->name) + 1; /* name\001 */ | 2115 | if (np->name != NULL) |
| 2090 | total += number_len ((long) np->lno) + 1; /* lno, */ | 2116 | total += strlen (np->name) + 1; /* name\001 */ |
| 2091 | if (np->cno != invalidcharno) /* cno */ | 2117 | total += number_len ((long) np->lno) + 1; /* lno, */ |
| 2092 | total += number_len (np->cno); | 2118 | if (np->cno != invalidcharno) /* cno */ |
| 2093 | total += 1; /* newline */ | 2119 | total += number_len (np->cno); |
| 2094 | } | 2120 | total += 1; /* newline */ |
| 2121 | } | ||
| 2095 | 2122 | ||
| 2096 | return total; | 2123 | return total; |
| 2097 | } | 2124 | } |
| @@ -2121,8 +2148,9 @@ put_entries (np) | |||
| 2121 | fdp = np->fdp; | 2148 | fdp = np->fdp; |
| 2122 | fprintf (tagf, "\f\n%s,%d\n", | 2149 | fprintf (tagf, "\f\n%s,%d\n", |
| 2123 | fdp->taggedfname, total_size_of_entries (np)); | 2150 | fdp->taggedfname, total_size_of_entries (np)); |
| 2151 | fdp->written = TRUE; | ||
| 2124 | } | 2152 | } |
| 2125 | fputs (np->pat, tagf); | 2153 | fputs (np->regex, tagf); |
| 2126 | fputc ('\177', tagf); | 2154 | fputc ('\177', tagf); |
| 2127 | if (np->name != NULL) | 2155 | if (np->name != NULL) |
| 2128 | { | 2156 | { |
| @@ -2147,7 +2175,7 @@ put_entries (np) | |||
| 2147 | np->name, np->fdp->taggedfname, (np->lno + 63) / 64); | 2175 | np->name, np->fdp->taggedfname, (np->lno + 63) / 64); |
| 2148 | else | 2176 | else |
| 2149 | fprintf (stdout, "%-16s %3d %-16s %s\n", | 2177 | fprintf (stdout, "%-16s %3d %-16s %s\n", |
| 2150 | np->name, np->lno, np->fdp->taggedfname, np->pat); | 2178 | np->name, np->lno, np->fdp->taggedfname, np->regex); |
| 2151 | } | 2179 | } |
| 2152 | else | 2180 | else |
| 2153 | { | 2181 | { |
| @@ -2158,7 +2186,7 @@ put_entries (np) | |||
| 2158 | putc (searchar, tagf); | 2186 | putc (searchar, tagf); |
| 2159 | putc ('^', tagf); | 2187 | putc ('^', tagf); |
| 2160 | 2188 | ||
| 2161 | for (sp = np->pat; *sp; sp++) | 2189 | for (sp = np->regex; *sp; sp++) |
| 2162 | { | 2190 | { |
| 2163 | if (*sp == '\\' || *sp == searchar) | 2191 | if (*sp == '\\' || *sp == searchar) |
| 2164 | putc ('\\', tagf); | 2192 | putc ('\\', tagf); |
| @@ -2550,7 +2578,6 @@ static struct tok | |||
| 2550 | long linepos; | 2578 | long linepos; |
| 2551 | char *line; | 2579 | char *line; |
| 2552 | } token; /* latest token read */ | 2580 | } token; /* latest token read */ |
| 2553 | static linebuffer token_name; /* its name */ | ||
| 2554 | 2581 | ||
| 2555 | /* | 2582 | /* |
| 2556 | * Variables and functions for dealing with nested structures. | 2583 | * Variables and functions for dealing with nested structures. |
| @@ -3030,9 +3057,8 @@ C_entries (c_ext, inf) | |||
| 3030 | struct tok savetoken; /* token saved during preprocessor handling */ | 3057 | struct tok savetoken; /* token saved during preprocessor handling */ |
| 3031 | 3058 | ||
| 3032 | 3059 | ||
| 3033 | initbuffer (&token_name); | 3060 | linebuffer_init (&lbs[0].lb); |
| 3034 | initbuffer (&lbs[0].lb); | 3061 | linebuffer_init (&lbs[1].lb); |
| 3035 | initbuffer (&lbs[1].lb); | ||
| 3036 | if (cstack.size == 0) | 3062 | if (cstack.size == 0) |
| 3037 | { | 3063 | { |
| 3038 | cstack.size = (DEBUG) ? 1 : 4; | 3064 | cstack.size = (DEBUG) ? 1 : 4; |
| @@ -3765,7 +3791,6 @@ C_entries (c_ext, inf) | |||
| 3765 | 3791 | ||
| 3766 | } /* while not eof */ | 3792 | } /* while not eof */ |
| 3767 | 3793 | ||
| 3768 | free (token_name.buffer); | ||
| 3769 | free (lbs[0].lb.buffer); | 3794 | free (lbs[0].lb.buffer); |
| 3770 | free (lbs[1].lb.buffer); | 3795 | free (lbs[1].lb.buffer); |
| 3771 | } | 3796 | } |
| @@ -3981,7 +4006,7 @@ Fortran_functions (inf) | |||
| 3981 | /* | 4006 | /* |
| 3982 | * Ada parsing | 4007 | * Ada parsing |
| 3983 | * Original code by | 4008 | * Original code by |
| 3984 | * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998) | 4009 | * Philippe Waroquiers <philippe.waroquiers@eurocontrol.int> (1998) |
| 3985 | */ | 4010 | */ |
| 3986 | 4011 | ||
| 3987 | static void Ada_getit __P((FILE *, char *)); | 4012 | static void Ada_getit __P((FILE *, char *)); |
| @@ -4058,6 +4083,7 @@ Ada_funcs (inf) | |||
| 4058 | FILE *inf; | 4083 | FILE *inf; |
| 4059 | { | 4084 | { |
| 4060 | bool inquote = FALSE; | 4085 | bool inquote = FALSE; |
| 4086 | bool skip_till_semicolumn = FALSE; | ||
| 4061 | 4087 | ||
| 4062 | LOOP_ON_INPUT_LINES (inf, lb, dbp) | 4088 | LOOP_ON_INPUT_LINES (inf, lb, dbp) |
| 4063 | { | 4089 | { |
| @@ -4094,6 +4120,14 @@ Ada_funcs (inf) | |||
| 4094 | continue; | 4120 | continue; |
| 4095 | } | 4121 | } |
| 4096 | 4122 | ||
| 4123 | if (skip_till_semicolumn) | ||
| 4124 | { | ||
| 4125 | if (*dbp == ';') | ||
| 4126 | skip_till_semicolumn = FALSE; | ||
| 4127 | dbp++; | ||
| 4128 | continue; /* advance char */ | ||
| 4129 | } | ||
| 4130 | |||
| 4097 | /* Search for beginning of a token. */ | 4131 | /* Search for beginning of a token. */ |
| 4098 | if (!begtoken (*dbp)) | 4132 | if (!begtoken (*dbp)) |
| 4099 | { | 4133 | { |
| @@ -4120,6 +4154,16 @@ Ada_funcs (inf) | |||
| 4120 | else | 4154 | else |
| 4121 | break; /* from switch */ | 4155 | break; /* from switch */ |
| 4122 | continue; /* advance char */ | 4156 | continue; /* advance char */ |
| 4157 | |||
| 4158 | case 'u': | ||
| 4159 | if (typedefs && !packages_only && nocase_tail ("use")) | ||
| 4160 | { | ||
| 4161 | /* when tagging types, avoid tagging use type Pack.Typename; | ||
| 4162 | for this, we will skip everything till a ; */ | ||
| 4163 | skip_till_semicolumn = TRUE; | ||
| 4164 | continue; /* advance char */ | ||
| 4165 | } | ||
| 4166 | |||
| 4123 | case 't': | 4167 | case 't': |
| 4124 | if (!packages_only && nocase_tail ("task")) | 4168 | if (!packages_only && nocase_tail ("task")) |
| 4125 | Ada_getit (inf, "/k"); | 4169 | Ada_getit (inf, "/k"); |
| @@ -4456,7 +4500,7 @@ Pascal_functions (inf) | |||
| 4456 | name = NULL; /* keep compiler quiet */ | 4500 | name = NULL; /* keep compiler quiet */ |
| 4457 | dbp = lb.buffer; | 4501 | dbp = lb.buffer; |
| 4458 | *dbp = '\0'; | 4502 | *dbp = '\0'; |
| 4459 | initbuffer (&tline); | 4503 | linebuffer_init (&tline); |
| 4460 | 4504 | ||
| 4461 | incomment = inquote = FALSE; | 4505 | incomment = inquote = FALSE; |
| 4462 | found_tag = FALSE; /* have a proc name; check if extern */ | 4506 | found_tag = FALSE; /* have a proc name; check if extern */ |
| @@ -4542,7 +4586,7 @@ Pascal_functions (inf) | |||
| 4542 | } | 4586 | } |
| 4543 | else if (lowcase (*dbp) == 'f') | 4587 | else if (lowcase (*dbp) == 'f') |
| 4544 | { | 4588 | { |
| 4545 | if (nocase_tail ("forward")) /* check for forward reference */ | 4589 | if (nocase_tail ("forward")) /* check for forward reference */ |
| 4546 | { | 4590 | { |
| 4547 | found_tag = FALSE; | 4591 | found_tag = FALSE; |
| 4548 | verify_tag = FALSE; | 4592 | verify_tag = FALSE; |
| @@ -4925,6 +4969,127 @@ Texinfo_nodes (inf) | |||
| 4925 | } | 4969 | } |
| 4926 | 4970 | ||
| 4927 | 4971 | ||
| 4972 | /* Similar to LOOKING_AT but does not use notinname, does not skip */ | ||
| 4973 | #define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \ | ||
| 4974 | (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ | ||
| 4975 | && ((cp) += sizeof(kw)-1)) /* skip spaces */ | ||
| 4976 | |||
| 4977 | /* | ||
| 4978 | * HTML support. | ||
| 4979 | * Contents of <title>, <h1>, <h2>, <h3> are tags. | ||
| 4980 | * Contents of <a name=xxx> are tags with name xxx. | ||
| 4981 | * | ||
| 4982 | * Francesco Potortì, 2002. | ||
| 4983 | */ | ||
| 4984 | static void | ||
| 4985 | HTML_labels (inf) | ||
| 4986 | FILE * inf; | ||
| 4987 | { | ||
| 4988 | bool getnext = FALSE; /* next text outside of HTML tags is a tag */ | ||
| 4989 | bool ignoretag = FALSE; /* skip to the end of the current HTML tag */ | ||
| 4990 | bool inanchor = FALSE; /* inside an A HTML tag, looking for NAME= */ | ||
| 4991 | char *end; | ||
| 4992 | |||
| 4993 | |||
| 4994 | linebuffer_setlen (&token_name, 0); /* no name in buffer */ | ||
| 4995 | |||
| 4996 | LOOP_ON_INPUT_LINES (inf, lb, dbp) | ||
| 4997 | { | ||
| 4998 | for (;;) /* loop on the same line */ | ||
| 4999 | |||
| 5000 | if (ignoretag) /* skip HTML tag */ | ||
| 5001 | { | ||
| 5002 | while (*dbp != '\0' && *dbp != '>') | ||
| 5003 | dbp++; | ||
| 5004 | if (*dbp == '>') | ||
| 5005 | { | ||
| 5006 | dbp += 1; | ||
| 5007 | ignoretag = FALSE; | ||
| 5008 | continue; /* look on the same line */ | ||
| 5009 | } | ||
| 5010 | break; /* go to next line */ | ||
| 5011 | } | ||
| 5012 | |||
| 5013 | else if (inanchor) /* look for "name=" */ | ||
| 5014 | { | ||
| 5015 | while (*dbp != '\0' && *dbp != '>' && lowcase (*dbp) != 'n') | ||
| 5016 | dbp++; | ||
| 5017 | if (*dbp == '\0') | ||
| 5018 | break; /* go to next line */ | ||
| 5019 | if (*dbp == '>') | ||
| 5020 | { | ||
| 5021 | dbp += 1; | ||
| 5022 | inanchor = FALSE; | ||
| 5023 | continue; /* look on the same line */ | ||
| 5024 | } | ||
| 5025 | dbp += 1; | ||
| 5026 | if (LOOKING_AT_NOCASE (dbp, "ame=")) | ||
| 5027 | { | ||
| 5028 | bool quoted = (dbp[0] == '"'); | ||
| 5029 | |||
| 5030 | if (quoted) | ||
| 5031 | for (end = ++dbp; *end != '\0' && *end != '"'; end++) | ||
| 5032 | continue; | ||
| 5033 | else | ||
| 5034 | for (end = dbp; *end != '\0' && intoken (*end); end++) | ||
| 5035 | continue; | ||
| 5036 | linebuffer_setlen (&token_name, end - dbp); | ||
| 5037 | strncpy (token_name.buffer, dbp, end - dbp); | ||
| 5038 | token_name.buffer[end - dbp] = '\0'; | ||
| 5039 | |||
| 5040 | dbp = end; | ||
| 5041 | inanchor = FALSE; /* we found what we looked for */ | ||
| 5042 | ignoretag = TRUE; /* skip to the end of the anchor */ | ||
| 5043 | getnext = TRUE; /* then grab the text */ | ||
| 5044 | continue; /* look on the same line */ | ||
| 5045 | } | ||
| 5046 | } | ||
| 5047 | |||
| 5048 | else if (getnext) /* grab next tokens and tag them */ | ||
| 5049 | { | ||
| 5050 | dbp = skip_spaces (dbp); | ||
| 5051 | if (*dbp == '\0') | ||
| 5052 | break; /* go to next line */ | ||
| 5053 | if (*dbp == '<') | ||
| 5054 | { | ||
| 5055 | if (lowcase (dbp[1]) == 'a' && !intoken (dbp[2])) | ||
| 5056 | inanchor = TRUE; | ||
| 5057 | else | ||
| 5058 | ignoretag = TRUE; | ||
| 5059 | continue; /* look on the same line */ | ||
| 5060 | } | ||
| 5061 | |||
| 5062 | for (end = dbp + 1; *end != '\0' && *end != '<'; end++) | ||
| 5063 | continue; | ||
| 5064 | make_tag (token_name.buffer, token_name.len, TRUE, | ||
| 5065 | dbp, end - dbp, lineno, linecharno); | ||
| 5066 | linebuffer_setlen (&token_name, 0); /* no name in buffer */ | ||
| 5067 | getnext = FALSE; | ||
| 5068 | break; /* go to next line */ | ||
| 5069 | } | ||
| 5070 | |||
| 5071 | else /* look for an interesting HTML tag */ | ||
| 5072 | { | ||
| 5073 | while (*dbp != '\0' && *dbp != '<') | ||
| 5074 | dbp++; | ||
| 5075 | if (*dbp == '\0') | ||
| 5076 | break; /* go to next line */ | ||
| 5077 | dbp += 1; | ||
| 5078 | if (lowcase (dbp[0]) == 'a' && !intoken (dbp[1])) | ||
| 5079 | inanchor = TRUE; | ||
| 5080 | else if (LOOKING_AT_NOCASE (dbp, "title>") | ||
| 5081 | || LOOKING_AT_NOCASE (dbp, "h1>") | ||
| 5082 | || LOOKING_AT_NOCASE (dbp, "h2>") | ||
| 5083 | || LOOKING_AT_NOCASE (dbp, "h3>")) | ||
| 5084 | { | ||
| 5085 | getnext = TRUE; | ||
| 5086 | continue; /* look on the same line */ | ||
| 5087 | } | ||
| 5088 | } | ||
| 5089 | } | ||
| 5090 | } | ||
| 5091 | |||
| 5092 | |||
| 4928 | /* | 5093 | /* |
| 4929 | * Prolog support | 5094 | * Prolog support |
| 4930 | * | 5095 | * |
| @@ -5315,7 +5480,7 @@ analyse_regex (regex_arg) | |||
| 5315 | { | 5480 | { |
| 5316 | if (regex_arg == NULL) | 5481 | if (regex_arg == NULL) |
| 5317 | { | 5482 | { |
| 5318 | free_patterns (); /* --no-regex: remove existing regexps */ | 5483 | free_regexps (); /* --no-regex: remove existing regexps */ |
| 5319 | return; | 5484 | return; |
| 5320 | } | 5485 | } |
| 5321 | 5486 | ||
| @@ -5343,7 +5508,7 @@ analyse_regex (regex_arg) | |||
| 5343 | pfatal (regexfile); | 5508 | pfatal (regexfile); |
| 5344 | return; | 5509 | return; |
| 5345 | } | 5510 | } |
| 5346 | initbuffer (®exbuf); | 5511 | linebuffer_init (®exbuf); |
| 5347 | while (readline_internal (®exbuf, regexfp) > 0) | 5512 | while (readline_internal (®exbuf, regexfp) > 0) |
| 5348 | analyse_regex (regexbuf.buffer); | 5513 | analyse_regex (regexbuf.buffer); |
| 5349 | free (regexbuf.buffer); | 5514 | free (regexbuf.buffer); |
| @@ -5379,8 +5544,8 @@ analyse_regex (regex_arg) | |||
| 5379 | } | 5544 | } |
| 5380 | } | 5545 | } |
| 5381 | 5546 | ||
| 5382 | /* Turn a name, which is an ed-style (but Emacs syntax) regular | 5547 | /* Separate the regexp pattern, compile it, |
| 5383 | expression, into a real regular expression by compiling it. */ | 5548 | and care for optional name and modifiers. */ |
| 5384 | static void | 5549 | static void |
| 5385 | add_regex (regexp_pattern, lang) | 5550 | add_regex (regexp_pattern, lang) |
| 5386 | char *regexp_pattern; | 5551 | char *regexp_pattern; |
| @@ -5390,8 +5555,12 @@ add_regex (regexp_pattern, lang) | |||
| 5390 | char sep, *pat, *name, *modifiers; | 5555 | char sep, *pat, *name, *modifiers; |
| 5391 | const char *err; | 5556 | const char *err; |
| 5392 | struct re_pattern_buffer *patbuf; | 5557 | struct re_pattern_buffer *patbuf; |
| 5393 | pattern *pp; | 5558 | regexp *rp; |
| 5394 | bool ignore_case, multi_line, single_line; | 5559 | bool |
| 5560 | force_explicit_name = TRUE, /* do not use implicit tag names */ | ||
| 5561 | ignore_case = FALSE, /* case is significant */ | ||
| 5562 | multi_line = FALSE, /* matches are done one line at a time */ | ||
| 5563 | single_line = FALSE; /* dot does not match newline */ | ||
| 5395 | 5564 | ||
| 5396 | 5565 | ||
| 5397 | if (strlen(regexp_pattern) < 3) | 5566 | if (strlen(regexp_pattern) < 3) |
| @@ -5421,12 +5590,14 @@ add_regex (regexp_pattern, lang) | |||
| 5421 | modifiers += 1; /* skip separator */ | 5590 | modifiers += 1; /* skip separator */ |
| 5422 | 5591 | ||
| 5423 | /* Parse regex modifiers. */ | 5592 | /* Parse regex modifiers. */ |
| 5424 | ignore_case = FALSE; /* case is significant */ | ||
| 5425 | multi_line = FALSE; /* matches are done one line at a time */ | ||
| 5426 | single_line = FALSE; /* dot does not match newline */ | ||
| 5427 | for (; modifiers[0] != '\0'; modifiers++) | 5593 | for (; modifiers[0] != '\0'; modifiers++) |
| 5428 | switch (modifiers[0]) | 5594 | switch (modifiers[0]) |
| 5429 | { | 5595 | { |
| 5596 | case 'N': | ||
| 5597 | if (modifiers == name) | ||
| 5598 | error ("forcing explicit tag name but no name, ignoring", NULL); | ||
| 5599 | force_explicit_name = TRUE; | ||
| 5600 | break; | ||
| 5430 | case 'i': | 5601 | case 'i': |
| 5431 | ignore_case = TRUE; | 5602 | ignore_case = TRUE; |
| 5432 | break; | 5603 | break; |
| @@ -5477,14 +5648,15 @@ add_regex (regexp_pattern, lang) | |||
| 5477 | return; | 5648 | return; |
| 5478 | } | 5649 | } |
| 5479 | 5650 | ||
| 5480 | pp = p_head; | 5651 | rp = p_head; |
| 5481 | p_head = xnew (1, pattern); | 5652 | p_head = xnew (1, regexp); |
| 5482 | p_head->regex = savestr (regexp_pattern); | 5653 | p_head->pattern = savestr (regexp_pattern); |
| 5483 | p_head->p_next = pp; | 5654 | p_head->p_next = rp; |
| 5484 | p_head->lang = lang; | 5655 | p_head->lang = lang; |
| 5485 | p_head->pat = patbuf; | 5656 | p_head->pat = patbuf; |
| 5486 | p_head->name_pattern = savestr (name); | 5657 | p_head->name = savestr (name); |
| 5487 | p_head->error_signaled = FALSE; | 5658 | p_head->error_signaled = FALSE; |
| 5659 | p_head->force_explicit_name = force_explicit_name; | ||
| 5488 | p_head->ignore_case = ignore_case; | 5660 | p_head->ignore_case = ignore_case; |
| 5489 | p_head->multi_line = multi_line; | 5661 | p_head->multi_line = multi_line; |
| 5490 | } | 5662 | } |
| @@ -5539,18 +5711,18 @@ substitute (in, out, regs) | |||
| 5539 | return result; | 5711 | return result; |
| 5540 | } | 5712 | } |
| 5541 | 5713 | ||
| 5542 | /* Deallocate all patterns. */ | 5714 | /* Deallocate all regexps. */ |
| 5543 | static void | 5715 | static void |
| 5544 | free_patterns () | 5716 | free_regexps () |
| 5545 | { | 5717 | { |
| 5546 | pattern *pp; | 5718 | regexp *rp; |
| 5547 | while (p_head != NULL) | 5719 | while (p_head != NULL) |
| 5548 | { | 5720 | { |
| 5549 | pp = p_head->p_next; | 5721 | rp = p_head->p_next; |
| 5550 | free (p_head->regex); | 5722 | free (p_head->pattern); |
| 5551 | free (p_head->name_pattern); | 5723 | free (p_head->name); |
| 5552 | free (p_head); | 5724 | free (p_head); |
| 5553 | p_head = pp; | 5725 | p_head = rp; |
| 5554 | } | 5726 | } |
| 5555 | return; | 5727 | return; |
| 5556 | } | 5728 | } |
| @@ -5566,13 +5738,14 @@ static void | |||
| 5566 | regex_tag_multiline () | 5738 | regex_tag_multiline () |
| 5567 | { | 5739 | { |
| 5568 | char *buffer = filebuf.buffer; | 5740 | char *buffer = filebuf.buffer; |
| 5569 | pattern *pp; | 5741 | regexp *rp; |
| 5742 | char *name; | ||
| 5570 | 5743 | ||
| 5571 | for (pp = p_head; pp != NULL; pp = pp->p_next) | 5744 | for (rp = p_head; rp != NULL; rp = rp->p_next) |
| 5572 | { | 5745 | { |
| 5573 | int match = 0; | 5746 | int match = 0; |
| 5574 | 5747 | ||
| 5575 | if (!pp->multi_line) | 5748 | if (!rp->multi_line) |
| 5576 | continue; /* skip normal regexps */ | 5749 | continue; /* skip normal regexps */ |
| 5577 | 5750 | ||
| 5578 | /* Generic initialisations before parsing file from memory. */ | 5751 | /* Generic initialisations before parsing file from memory. */ |
| @@ -5581,62 +5754,55 @@ regex_tag_multiline () | |||
| 5581 | linecharno = 0; /* reset global char number of line start */ | 5754 | linecharno = 0; /* reset global char number of line start */ |
| 5582 | 5755 | ||
| 5583 | /* Only use generic regexps or those for the current language. */ | 5756 | /* Only use generic regexps or those for the current language. */ |
| 5584 | if (pp->lang != NULL && pp->lang != curfdp->lang) | 5757 | if (rp->lang != NULL && rp->lang != curfdp->lang) |
| 5585 | continue; | 5758 | continue; |
| 5586 | 5759 | ||
| 5587 | while (match >= 0 && match < filebuf.len) | 5760 | while (match >= 0 && match < filebuf.len) |
| 5588 | { | 5761 | { |
| 5589 | match = re_search (pp->pat, buffer, filebuf.len, charno, | 5762 | match = re_search (rp->pat, buffer, filebuf.len, charno, |
| 5590 | filebuf.len - match, &pp->regs); | 5763 | filebuf.len - match, &rp->regs); |
| 5591 | switch (match) | 5764 | switch (match) |
| 5592 | { | 5765 | { |
| 5593 | case -2: | 5766 | case -2: |
| 5594 | /* Some error. */ | 5767 | /* Some error. */ |
| 5595 | if (!pp->error_signaled) | 5768 | if (!rp->error_signaled) |
| 5596 | { | 5769 | { |
| 5597 | error ("regexp stack overflow while matching \"%s\"", | 5770 | error ("regexp stack overflow while matching \"%s\"", |
| 5598 | pp->regex); | 5771 | rp->pattern); |
| 5599 | pp->error_signaled = TRUE; | 5772 | rp->error_signaled = TRUE; |
| 5600 | } | 5773 | } |
| 5601 | break; | 5774 | break; |
| 5602 | case -1: | 5775 | case -1: |
| 5603 | /* No match. */ | 5776 | /* No match. */ |
| 5604 | break; | 5777 | break; |
| 5605 | default: | 5778 | default: |
| 5606 | if (match == pp->regs.end[0]) | 5779 | if (match == rp->regs.end[0]) |
| 5607 | { | 5780 | { |
| 5608 | if (!pp->error_signaled) | 5781 | if (!rp->error_signaled) |
| 5609 | { | 5782 | { |
| 5610 | error ("regexp matches the empty string: \"%s\"", | 5783 | error ("regexp matches the empty string: \"%s\"", |
| 5611 | pp->regex); | 5784 | rp->pattern); |
| 5612 | pp->error_signaled = TRUE; | 5785 | rp->error_signaled = TRUE; |
| 5613 | } | 5786 | } |
| 5614 | match = -3; /* exit from while loop */ | 5787 | match = -3; /* exit from while loop */ |
| 5615 | break; | 5788 | break; |
| 5616 | } | 5789 | } |
| 5617 | 5790 | ||
| 5618 | /* Match occurred. Construct a tag. */ | 5791 | /* Match occurred. Construct a tag. */ |
| 5619 | while (charno < pp->regs.end[0]) | 5792 | while (charno < rp->regs.end[0]) |
| 5620 | if (buffer[charno++] == '\n') | 5793 | if (buffer[charno++] == '\n') |
| 5621 | lineno++, linecharno = charno; | 5794 | lineno++, linecharno = charno; |
| 5622 | if (pp->name_pattern[0] != '\0') | 5795 | name = rp->name; |
| 5623 | { | 5796 | if (name[0] != '\0') |
| 5624 | /* Make a named tag. | 5797 | /* Make a named tag. */ |
| 5625 | Do not use make_tag here, as it would make the name | 5798 | name = substitute (buffer, rp->name, &rp->regs); |
| 5626 | implicit if possible, while we want to respect the user's | 5799 | if (rp->force_explicit_name) |
| 5627 | request to create an explicit tag name. */ | 5800 | /* Force explicit tag name, if a name is there. */ |
| 5628 | char *name = substitute (buffer, | 5801 | pfnote (name, TRUE, buffer + linecharno, |
| 5629 | pp->name_pattern, &pp->regs); | 5802 | charno - linecharno + 1, lineno, linecharno); |
| 5630 | if (name != NULL) | ||
| 5631 | pfnote (name, TRUE, buffer + linecharno, | ||
| 5632 | charno - linecharno + 1, lineno, linecharno); | ||
| 5633 | } | ||
| 5634 | else | 5803 | else |
| 5635 | { | 5804 | make_tag (name, strlen (name), TRUE, buffer + linecharno, |
| 5636 | /* Make an unnamed tag. */ | ||
| 5637 | pfnote ((char *)NULL, TRUE, buffer + linecharno, | ||
| 5638 | charno - linecharno + 1, lineno, linecharno); | 5805 | charno - linecharno + 1, lineno, linecharno); |
| 5639 | } | ||
| 5640 | break; | 5806 | break; |
| 5641 | } | 5807 | } |
| 5642 | } | 5808 | } |
| @@ -5682,17 +5848,6 @@ get_tag (bp, namepp) | |||
| 5682 | *namepp = savenstr (bp, cp - bp); | 5848 | *namepp = savenstr (bp, cp - bp); |
| 5683 | } | 5849 | } |
| 5684 | 5850 | ||
| 5685 | /* Initialize a linebuffer for use */ | ||
| 5686 | static void | ||
| 5687 | initbuffer (lbp) | ||
| 5688 | linebuffer *lbp; | ||
| 5689 | { | ||
| 5690 | lbp->size = (DEBUG) ? 3 : 200; | ||
| 5691 | lbp->buffer = xnew (lbp->size, char); | ||
| 5692 | lbp->buffer[0] = '\0'; | ||
| 5693 | lbp->len = 0; | ||
| 5694 | } | ||
| 5695 | |||
| 5696 | /* | 5851 | /* |
| 5697 | * Read a line of text from `stream' into `lbp', excluding the | 5852 | * Read a line of text from `stream' into `lbp', excluding the |
| 5698 | * newline or CR-NL, if any. Return the number of characters read from | 5853 | * newline or CR-NL, if any. Return the number of characters read from |
| @@ -5889,6 +6044,8 @@ readline (lbp, stream) | |||
| 5889 | fdhead->infabsdir = savestr (curfdp->infabsdir); | 6044 | fdhead->infabsdir = savestr (curfdp->infabsdir); |
| 5890 | fdhead->taggedfname = taggedfname; | 6045 | fdhead->taggedfname = taggedfname; |
| 5891 | fdhead->usecharno = FALSE; | 6046 | fdhead->usecharno = FALSE; |
| 6047 | fdhead->prop = NULL; | ||
| 6048 | fdhead->written = FALSE; | ||
| 5892 | curfdp = fdhead; | 6049 | curfdp = fdhead; |
| 5893 | } | 6050 | } |
| 5894 | } | 6051 | } |
| @@ -5919,29 +6076,30 @@ readline (lbp, stream) | |||
| 5919 | #ifdef ETAGS_REGEXPS | 6076 | #ifdef ETAGS_REGEXPS |
| 5920 | { | 6077 | { |
| 5921 | int match; | 6078 | int match; |
| 5922 | pattern *pp; | 6079 | regexp *rp; |
| 6080 | char *name; | ||
| 5923 | 6081 | ||
| 5924 | /* Match against relevant patterns. */ | 6082 | /* Match against relevant regexps. */ |
| 5925 | if (lbp->len > 0) | 6083 | if (lbp->len > 0) |
| 5926 | for (pp = p_head; pp != NULL; pp = pp->p_next) | 6084 | for (rp = p_head; rp != NULL; rp = rp->p_next) |
| 5927 | { | 6085 | { |
| 5928 | /* Only use generic regexps or those for the current language. | 6086 | /* Only use generic regexps or those for the current language. |
| 5929 | Also do not use multiline regexps, which is the job of | 6087 | Also do not use multiline regexps, which is the job of |
| 5930 | regex_tag_multiline. */ | 6088 | regex_tag_multiline. */ |
| 5931 | if ((pp->lang != NULL && pp->lang != fdhead->lang) | 6089 | if ((rp->lang != NULL && rp->lang != fdhead->lang) |
| 5932 | || pp->multi_line) | 6090 | || rp->multi_line) |
| 5933 | continue; | 6091 | continue; |
| 5934 | 6092 | ||
| 5935 | match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs); | 6093 | match = re_match (rp->pat, lbp->buffer, lbp->len, 0, &rp->regs); |
| 5936 | switch (match) | 6094 | switch (match) |
| 5937 | { | 6095 | { |
| 5938 | case -2: | 6096 | case -2: |
| 5939 | /* Some error. */ | 6097 | /* Some error. */ |
| 5940 | if (!pp->error_signaled) | 6098 | if (!rp->error_signaled) |
| 5941 | { | 6099 | { |
| 5942 | error ("regexp stack overflow while matching \"%s\"", | 6100 | error ("regexp stack overflow while matching \"%s\"", |
| 5943 | pp->regex); | 6101 | rp->pattern); |
| 5944 | pp->error_signaled = TRUE; | 6102 | rp->error_signaled = TRUE; |
| 5945 | } | 6103 | } |
| 5946 | break; | 6104 | break; |
| 5947 | case -1: | 6105 | case -1: |
| @@ -5949,32 +6107,24 @@ readline (lbp, stream) | |||
| 5949 | break; | 6107 | break; |
| 5950 | case 0: | 6108 | case 0: |
| 5951 | /* Empty string matched. */ | 6109 | /* Empty string matched. */ |
| 5952 | if (!pp->error_signaled) | 6110 | if (!rp->error_signaled) |
| 5953 | { | 6111 | { |
| 5954 | error ("regexp matches the empty string: \"%s\"", | 6112 | error ("regexp matches the empty string: \"%s\"", rp->pattern); |
| 5955 | pp->regex); | 6113 | rp->error_signaled = TRUE; |
| 5956 | pp->error_signaled = TRUE; | ||
| 5957 | } | 6114 | } |
| 5958 | break; | 6115 | break; |
| 5959 | default: | 6116 | default: |
| 5960 | /* Match occurred. Construct a tag. */ | 6117 | /* Match occurred. Construct a tag. */ |
| 5961 | if (pp->name_pattern[0] != '\0') | 6118 | name = rp->name; |
| 5962 | { | 6119 | if (name[0] != '\0') |
| 5963 | /* Make a named tag. | 6120 | /* Make a named tag. */ |
| 5964 | Do not use make_tag here, as it would make the name | 6121 | name = substitute (lbp->buffer, rp->name, &rp->regs); |
| 5965 | implicit if possible, while we want to respect the user's | 6122 | if (rp->force_explicit_name) |
| 5966 | request to create an explicit tag name. */ | 6123 | /* Force explicit tag name, if a name is there. */ |
| 5967 | char *name = substitute (lbp->buffer, | 6124 | pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno); |
| 5968 | pp->name_pattern, &pp->regs); | ||
| 5969 | if (name != NULL) | ||
| 5970 | pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno); | ||
| 5971 | } | ||
| 5972 | else | 6125 | else |
| 5973 | { | 6126 | make_tag (name, strlen (name), TRUE, |
| 5974 | /* Make an unnamed tag. */ | ||
| 5975 | pfnote ((char *)NULL, TRUE, | ||
| 5976 | lbp->buffer, match, lineno, linecharno); | 6127 | lbp->buffer, match, lineno, linecharno); |
| 5977 | } | ||
| 5978 | break; | 6128 | break; |
| 5979 | } | 6129 | } |
| 5980 | } | 6130 | } |
| @@ -6053,13 +6203,12 @@ etags_strchr (sp, c) | |||
| 6053 | } | 6203 | } |
| 6054 | 6204 | ||
| 6055 | /* | 6205 | /* |
| 6056 | * Return TRUE if the two strings are equal, ignoring case for alphabetic | 6206 | * Compare two strings, ignoring case for alphabetic characters. |
| 6057 | * characters. | ||
| 6058 | * | 6207 | * |
| 6059 | * Analogous to BSD's strcasecmp, included for portability. | 6208 | * Same as BSD's strcasecmp, included for portability. |
| 6060 | */ | 6209 | */ |
| 6061 | static bool | 6210 | static int |
| 6062 | strcaseeq (s1, s2) | 6211 | etags_strcasecmp (s1, s2) |
| 6063 | register const char *s1; | 6212 | register const char *s1; |
| 6064 | register const char *s2; | 6213 | register const char *s2; |
| 6065 | { | 6214 | { |
| @@ -6069,7 +6218,35 @@ strcaseeq (s1, s2) | |||
| 6069 | : *s1 == *s2)) | 6218 | : *s1 == *s2)) |
| 6070 | s1++, s2++; | 6219 | s1++, s2++; |
| 6071 | 6220 | ||
| 6072 | return (*s1 == *s2); | 6221 | return (ISALPHA (*s1) && ISALPHA (*s2) |
| 6222 | ? lowcase (*s1) - lowcase (*s2) | ||
| 6223 | : *s1 - *s2); | ||
| 6224 | } | ||
| 6225 | |||
| 6226 | /* | ||
| 6227 | * Compare two strings, ignoring case for alphabetic characters. | ||
| 6228 | * Stop after a given number of characters | ||
| 6229 | * | ||
| 6230 | * Same as BSD's strncasecmp, included for portability. | ||
| 6231 | */ | ||
| 6232 | static int | ||
| 6233 | etags_strncasecmp (s1, s2, n) | ||
| 6234 | register const char *s1; | ||
| 6235 | register const char *s2; | ||
| 6236 | register int n; | ||
| 6237 | { | ||
| 6238 | while (*s1 != '\0' && n-- > 0 | ||
| 6239 | && (ISALPHA (*s1) && ISALPHA (*s2) | ||
| 6240 | ? lowcase (*s1) == lowcase (*s2) | ||
| 6241 | : *s1 == *s2)) | ||
| 6242 | s1++, s2++; | ||
| 6243 | |||
| 6244 | if (n < 0) | ||
| 6245 | return 0; | ||
| 6246 | else | ||
| 6247 | return (ISALPHA (*s1) && ISALPHA (*s2) | ||
| 6248 | ? lowcase (*s1) - lowcase (*s2) | ||
| 6249 | : *s1 - *s2); | ||
| 6073 | } | 6250 | } |
| 6074 | 6251 | ||
| 6075 | /* Skip spaces, return new pointer. */ | 6252 | /* Skip spaces, return new pointer. */ |
| @@ -6190,7 +6367,7 @@ etags_getcwd () | |||
| 6190 | linebuffer path; | 6367 | linebuffer path; |
| 6191 | FILE *pipe; | 6368 | FILE *pipe; |
| 6192 | 6369 | ||
| 6193 | initbuffer (&path); | 6370 | linebuffer_init (&path); |
| 6194 | pipe = (FILE *) popen ("pwd 2>/dev/null", "r"); | 6371 | pipe = (FILE *) popen ("pwd 2>/dev/null", "r"); |
| 6195 | if (pipe == NULL || readline_internal (&path, pipe) == 0) | 6372 | if (pipe == NULL || readline_internal (&path, pipe) == 0) |
| 6196 | pfatal ("pwd"); | 6373 | pfatal ("pwd"); |
| @@ -6356,6 +6533,18 @@ canonicalize_filename (fn) | |||
| 6356 | #endif | 6533 | #endif |
| 6357 | } | 6534 | } |
| 6358 | 6535 | ||
| 6536 | |||
| 6537 | /* Initialize a linebuffer for use */ | ||
| 6538 | static void | ||
| 6539 | linebuffer_init (lbp) | ||
| 6540 | linebuffer *lbp; | ||
| 6541 | { | ||
| 6542 | lbp->size = (DEBUG) ? 3 : 200; | ||
| 6543 | lbp->buffer = xnew (lbp->size, char); | ||
| 6544 | lbp->buffer[0] = '\0'; | ||
| 6545 | lbp->len = 0; | ||
| 6546 | } | ||
| 6547 | |||
| 6359 | /* Set the minimum size of a string contained in a linebuffer. */ | 6548 | /* Set the minimum size of a string contained in a linebuffer. */ |
| 6360 | static void | 6549 | static void |
| 6361 | linebuffer_setlen (lbp, toksize) | 6550 | linebuffer_setlen (lbp, toksize) |
| @@ -6370,7 +6559,7 @@ linebuffer_setlen (lbp, toksize) | |||
| 6370 | lbp->len = toksize; | 6559 | lbp->len = toksize; |
| 6371 | } | 6560 | } |
| 6372 | 6561 | ||
| 6373 | /* Like malloc but get fatal error if memory is exhausted. */ | 6562 | /* Like malloc but get fatal error if memory is exhausted. */ |
| 6374 | static PTR | 6563 | static PTR |
| 6375 | xmalloc (size) | 6564 | xmalloc (size) |
| 6376 | unsigned int size; | 6565 | unsigned int size; |
| @@ -6398,6 +6587,6 @@ xrealloc (ptr, size) | |||
| 6398 | * indent-tabs-mode: t | 6587 | * indent-tabs-mode: t |
| 6399 | * tab-width: 8 | 6588 | * tab-width: 8 |
| 6400 | * fill-column: 79 | 6589 | * fill-column: 79 |
| 6401 | * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "pattern") | 6590 | * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp") |
| 6402 | * End: | 6591 | * End: |
| 6403 | */ | 6592 | */ |