# HG changeset patch # User Francesco Potort # Date 1018886107 0 # Node ID 1bec0b43020603f05baf01f8958a1c16d34213bb # Parent 4702b23921b43397a71d09cd54aa60aadec501e5 Bug fix. New version to come soon. diff -r 4702b23921b4 -r 1bec0b430206 lib-src/etags.c --- a/lib-src/etags.c Mon Apr 15 14:18:47 2002 +0000 +++ b/lib-src/etags.c Mon Apr 15 15:55:07 2002 +0000 @@ -346,7 +346,7 @@ static compressor *get_compressor_from_suffix __P((char *, char **)); static language *get_language_from_langname __P((const char *)); static language *get_language_from_interpreter __P((char *)); -static language *get_language_from_filename __P((char *)); +static language *get_language_from_filename __P((char *, bool)); static long readline __P((linebuffer *, FILE *)); static long readline_internal __P((linebuffer *, FILE *)); static bool nocase_tail __P((char *)); @@ -380,6 +380,7 @@ static char *savestr __P((char *)); static char *etags_strchr __P((const char *, int)); static char *etags_strrchr __P((const char *, int)); +static bool strcaseeq __P((const char *, const char *)); static char *etags_getcwd __P((void)); static char *relative_filename __P((char *, char *)); static char *absolute_filename __P((char *, char *)); @@ -1351,8 +1352,9 @@ * Return a language given the file name. */ static language * -get_language_from_filename (file) +get_language_from_filename (file, case_sensitive) char *file; + bool case_sensitive; { language *lang; char **name, **ext, *suffix; @@ -1361,7 +1363,9 @@ for (lang = lang_names; lang->name != NULL; lang++) if (lang->filenames != NULL) for (name = lang->filenames; *name != NULL; name++) - if (streq (*name, file)) + if ((case_sensitive) + ? streq (*name, file) + : strcaseeq (*name, file)) return lang; /* If not found, try suffix after last dot. */ @@ -1372,7 +1376,9 @@ for (lang = lang_names; lang->name != NULL; lang++) if (lang->suffixes != NULL) for (ext = lang->suffixes; *ext != NULL; ext++) - if (streq (*ext, suffix)) + if ((case_sensitive) + ? streq (*ext, suffix) + : strcaseeq (*ext, suffix)) return lang; return NULL; } @@ -1422,12 +1428,6 @@ goto cleanup; } - /* Create a new input file description entry. */ - fdp = fdhead; - fdhead = xnew (1, fdesc); - *fdhead = emptyfdesc; - fdhead->next = fdp; - if (stat (real_name, &stat_buf) != 0) { /* Reset real_name and try with a different name. */ @@ -1496,24 +1496,29 @@ goto cleanup; } - fdhead->infname = savestr (uncompressed_name); - fdhead->lang = lang; - fdhead->infabsname = absolute_filename (uncompressed_name, cwd); - fdhead->infabsdir = absolute_dirname (uncompressed_name, cwd); + /* Create a new input file description entry. */ + fdp = xnew (1, fdesc); + *fdp = emptyfdesc; + fdp->next = fdhead; + fdp->infname = savestr (uncompressed_name); + fdp->lang = lang; + fdp->infabsname = absolute_filename (uncompressed_name, cwd); + fdp->infabsdir = absolute_dirname (uncompressed_name, cwd); if (filename_is_absolute (uncompressed_name)) { /* file is an absolute file name. Canonicalize it. */ - fdhead->taggedfname = absolute_filename (uncompressed_name, NULL); + fdp->taggedfname = absolute_filename (uncompressed_name, NULL); } else { /* file is a file name relative to cwd. Make it relative to the directory of the tags file. */ - fdhead->taggedfname = relative_filename (uncompressed_name, tagfiledir); + fdp->taggedfname = relative_filename (uncompressed_name, tagfiledir); } - fdhead->usecharno = TRUE; /* use char position when making tags */ - fdhead->prop = NULL; - + fdp->usecharno = TRUE; /* use char position when making tags */ + fdp->prop = NULL; + + fdhead = fdp; curfdp = fdhead; /* the current file description */ find_entries (inf); @@ -1526,7 +1531,9 @@ pfatal (file); cleanup: - /* XXX if no more useful, delete head of file description list */ + /* Memory leak here: if this is not metasource and if it contained no #line + directives, curfdp could be freed, and so could all nodes pointing to it + if not CTAGS. */ if (compressed_name) free (compressed_name); if (uncompressed_name) free (uncompressed_name); return; @@ -1583,7 +1590,7 @@ /* Else try to guess the language given the file name. */ if (parser == NULL) { - lang = get_language_from_filename (curfdp->infname); + lang = get_language_from_filename (curfdp->infname, TRUE); if (lang != NULL && lang->function != NULL) { curfdp->lang = lang; @@ -1622,11 +1629,28 @@ } } + /* We rewind here, even if inf may be a pipe. We fail if the + length of the first line is longer than the pipe block size, + which is unlikely. */ + if (parser == NULL) + rewind (inf); +#if 0 + /* Else try to guess the language given the case insensitive file name. */ + if (parser == NULL) + { + lang = get_language_from_filename (curfdp->infname, FALSE); + if (lang != NULL && lang->function != NULL) + { + curfdp->lang = lang; + parser = lang->function; + } + } +#endif if (!no_line_directive && curfdp->lang != NULL && curfdp->lang->metasource) - /* It may be that this is an xxx.y file, and we already parsed an xxx.c + /* It may be that this is a bingo.y file, and we already parsed a bingo.c file, or anyway we parsed a file that is automatically generated from - this one. If this is the case, the xxx.c file contained #line + this one. If this is the case, the bingo.c file contained #line directives that generated tags pointing to this file. Let's delete them all before parsing this file, which is the real source. */ { @@ -1642,8 +1666,11 @@ *fdpp = badfdp->next; /* remove the bad description from the list */ fdpp = &badfdp->next; /* advance the list pointer */ - fprintf (stderr, "Removing references to \"%s\" obtained from \"%s\"\n", - badfdp->taggedfname, badfdp->infname); + if (DEBUG) + fprintf (stderr, + "Removing references to \"%s\" obtained from \"%s\"\n", + badfdp->taggedfname, badfdp->infname); + /* Delete the tags referring to badfdp. */ invalidate_nodes (badfdp, nodehead); @@ -1665,11 +1692,6 @@ return; } - /* We rewind here, even if inf may be a pipe. We fail if the - length of the first line is longer than the pipe block size, - which is unlikely. */ - rewind (inf); - /* Else try Fortran. */ old_last_node = last_node; curfdp->lang = get_language_from_langname ("fortran"); @@ -1916,6 +1938,9 @@ { if (np->left != NULL) invalidate_nodes (badfdp, np->left); + /* Memory leak here: if not CTAGS, in which case it would be quite + difficult, the node could be freed. If CTAGS the node is part of a + binary tree, if not it is part of a list of lists. */ if (np->fdp == badfdp) np-> valid = FALSE; if (np->right != NULL) @@ -5741,7 +5766,6 @@ return (char *)r; } - /* * Return the ptr in sp at which the character c first * appears; NULL if not found @@ -5761,6 +5785,26 @@ return NULL; } +/* + * Return TRUE if the two strings are equal, ignoring case for alphabetic + * characters. + * + * Analogous to BSD's strcasecmp, included for portability. + */ +static bool +strcaseeq (s1, s2) + register const char *s1; + register const char *s2; +{ + while (*s1 != '\0' + && (ISALPHA (*s1) && ISALPHA (*s2) + ? lowcase (*s1) == lowcase (*s2) + : *s1 == *s2)) + s1++, s2++; + + return (*s1 == *s2); +} + /* Skip spaces, return new pointer. */ static char * skip_spaces (cp)