Mercurial > emacs
comparison lib-src/etags.c @ 44605:1bec0b430206
Bug fix. New version to come soon.
author | Francesco Potortì <pot@gnu.org> |
---|---|
date | Mon, 15 Apr 2002 15:55:07 +0000 |
parents | 4702b23921b4 |
children | 8f3420af28a8 |
comparison
equal
deleted
inserted
replaced
44604:4702b23921b4 | 44605:1bec0b430206 |
---|---|
344 int main __P((int, char **)); | 344 int main __P((int, char **)); |
345 | 345 |
346 static compressor *get_compressor_from_suffix __P((char *, char **)); | 346 static compressor *get_compressor_from_suffix __P((char *, char **)); |
347 static language *get_language_from_langname __P((const char *)); | 347 static language *get_language_from_langname __P((const char *)); |
348 static language *get_language_from_interpreter __P((char *)); | 348 static language *get_language_from_interpreter __P((char *)); |
349 static language *get_language_from_filename __P((char *)); | 349 static language *get_language_from_filename __P((char *, bool)); |
350 static long readline __P((linebuffer *, FILE *)); | 350 static long readline __P((linebuffer *, FILE *)); |
351 static long readline_internal __P((linebuffer *, FILE *)); | 351 static long readline_internal __P((linebuffer *, FILE *)); |
352 static bool nocase_tail __P((char *)); | 352 static bool nocase_tail __P((char *)); |
353 static char *get_tag __P((char *)); | 353 static char *get_tag __P((char *)); |
354 | 354 |
378 static char *skip_non_spaces __P((char *)); | 378 static char *skip_non_spaces __P((char *)); |
379 static char *savenstr __P((char *, int)); | 379 static char *savenstr __P((char *, int)); |
380 static char *savestr __P((char *)); | 380 static char *savestr __P((char *)); |
381 static char *etags_strchr __P((const char *, int)); | 381 static char *etags_strchr __P((const char *, int)); |
382 static char *etags_strrchr __P((const char *, int)); | 382 static char *etags_strrchr __P((const char *, int)); |
383 static bool strcaseeq __P((const char *, const char *)); | |
383 static char *etags_getcwd __P((void)); | 384 static char *etags_getcwd __P((void)); |
384 static char *relative_filename __P((char *, char *)); | 385 static char *relative_filename __P((char *, char *)); |
385 static char *absolute_filename __P((char *, char *)); | 386 static char *absolute_filename __P((char *, char *)); |
386 static char *absolute_dirname __P((char *, char *)); | 387 static char *absolute_dirname __P((char *, char *)); |
387 static bool filename_is_absolute __P((char *f)); | 388 static bool filename_is_absolute __P((char *f)); |
1349 | 1350 |
1350 /* | 1351 /* |
1351 * Return a language given the file name. | 1352 * Return a language given the file name. |
1352 */ | 1353 */ |
1353 static language * | 1354 static language * |
1354 get_language_from_filename (file) | 1355 get_language_from_filename (file, case_sensitive) |
1355 char *file; | 1356 char *file; |
1357 bool case_sensitive; | |
1356 { | 1358 { |
1357 language *lang; | 1359 language *lang; |
1358 char **name, **ext, *suffix; | 1360 char **name, **ext, *suffix; |
1359 | 1361 |
1360 /* Try whole file name first. */ | 1362 /* Try whole file name first. */ |
1361 for (lang = lang_names; lang->name != NULL; lang++) | 1363 for (lang = lang_names; lang->name != NULL; lang++) |
1362 if (lang->filenames != NULL) | 1364 if (lang->filenames != NULL) |
1363 for (name = lang->filenames; *name != NULL; name++) | 1365 for (name = lang->filenames; *name != NULL; name++) |
1364 if (streq (*name, file)) | 1366 if ((case_sensitive) |
1367 ? streq (*name, file) | |
1368 : strcaseeq (*name, file)) | |
1365 return lang; | 1369 return lang; |
1366 | 1370 |
1367 /* If not found, try suffix after last dot. */ | 1371 /* If not found, try suffix after last dot. */ |
1368 suffix = etags_strrchr (file, '.'); | 1372 suffix = etags_strrchr (file, '.'); |
1369 if (suffix == NULL) | 1373 if (suffix == NULL) |
1370 return NULL; | 1374 return NULL; |
1371 suffix += 1; | 1375 suffix += 1; |
1372 for (lang = lang_names; lang->name != NULL; lang++) | 1376 for (lang = lang_names; lang->name != NULL; lang++) |
1373 if (lang->suffixes != NULL) | 1377 if (lang->suffixes != NULL) |
1374 for (ext = lang->suffixes; *ext != NULL; ext++) | 1378 for (ext = lang->suffixes; *ext != NULL; ext++) |
1375 if (streq (*ext, suffix)) | 1379 if ((case_sensitive) |
1380 ? streq (*ext, suffix) | |
1381 : strcaseeq (*ext, suffix)) | |
1376 return lang; | 1382 return lang; |
1377 return NULL; | 1383 return NULL; |
1378 } | 1384 } |
1379 | 1385 |
1380 | 1386 |
1419 { | 1425 { |
1420 assert (fdp->infname != NULL); | 1426 assert (fdp->infname != NULL); |
1421 if (streq (uncompressed_name, fdp->infname)) | 1427 if (streq (uncompressed_name, fdp->infname)) |
1422 goto cleanup; | 1428 goto cleanup; |
1423 } | 1429 } |
1424 | |
1425 /* Create a new input file description entry. */ | |
1426 fdp = fdhead; | |
1427 fdhead = xnew (1, fdesc); | |
1428 *fdhead = emptyfdesc; | |
1429 fdhead->next = fdp; | |
1430 | 1430 |
1431 if (stat (real_name, &stat_buf) != 0) | 1431 if (stat (real_name, &stat_buf) != 0) |
1432 { | 1432 { |
1433 /* Reset real_name and try with a different name. */ | 1433 /* Reset real_name and try with a different name. */ |
1434 real_name = NULL; | 1434 real_name = NULL; |
1494 { | 1494 { |
1495 perror (real_name); | 1495 perror (real_name); |
1496 goto cleanup; | 1496 goto cleanup; |
1497 } | 1497 } |
1498 | 1498 |
1499 fdhead->infname = savestr (uncompressed_name); | 1499 /* Create a new input file description entry. */ |
1500 fdhead->lang = lang; | 1500 fdp = xnew (1, fdesc); |
1501 fdhead->infabsname = absolute_filename (uncompressed_name, cwd); | 1501 *fdp = emptyfdesc; |
1502 fdhead->infabsdir = absolute_dirname (uncompressed_name, cwd); | 1502 fdp->next = fdhead; |
1503 fdp->infname = savestr (uncompressed_name); | |
1504 fdp->lang = lang; | |
1505 fdp->infabsname = absolute_filename (uncompressed_name, cwd); | |
1506 fdp->infabsdir = absolute_dirname (uncompressed_name, cwd); | |
1503 if (filename_is_absolute (uncompressed_name)) | 1507 if (filename_is_absolute (uncompressed_name)) |
1504 { | 1508 { |
1505 /* file is an absolute file name. Canonicalize it. */ | 1509 /* file is an absolute file name. Canonicalize it. */ |
1506 fdhead->taggedfname = absolute_filename (uncompressed_name, NULL); | 1510 fdp->taggedfname = absolute_filename (uncompressed_name, NULL); |
1507 } | 1511 } |
1508 else | 1512 else |
1509 { | 1513 { |
1510 /* file is a file name relative to cwd. Make it relative | 1514 /* file is a file name relative to cwd. Make it relative |
1511 to the directory of the tags file. */ | 1515 to the directory of the tags file. */ |
1512 fdhead->taggedfname = relative_filename (uncompressed_name, tagfiledir); | 1516 fdp->taggedfname = relative_filename (uncompressed_name, tagfiledir); |
1513 } | 1517 } |
1514 fdhead->usecharno = TRUE; /* use char position when making tags */ | 1518 fdp->usecharno = TRUE; /* use char position when making tags */ |
1515 fdhead->prop = NULL; | 1519 fdp->prop = NULL; |
1516 | 1520 |
1521 fdhead = fdp; | |
1517 curfdp = fdhead; /* the current file description */ | 1522 curfdp = fdhead; /* the current file description */ |
1518 | 1523 |
1519 find_entries (inf); | 1524 find_entries (inf); |
1520 | 1525 |
1521 if (real_name == compressed_name) | 1526 if (real_name == compressed_name) |
1524 retval = fclose (inf); | 1529 retval = fclose (inf); |
1525 if (retval < 0) | 1530 if (retval < 0) |
1526 pfatal (file); | 1531 pfatal (file); |
1527 | 1532 |
1528 cleanup: | 1533 cleanup: |
1529 /* XXX if no more useful, delete head of file description list */ | 1534 /* Memory leak here: if this is not metasource and if it contained no #line |
1535 directives, curfdp could be freed, and so could all nodes pointing to it | |
1536 if not CTAGS. */ | |
1530 if (compressed_name) free (compressed_name); | 1537 if (compressed_name) free (compressed_name); |
1531 if (uncompressed_name) free (uncompressed_name); | 1538 if (uncompressed_name) free (uncompressed_name); |
1532 return; | 1539 return; |
1533 } | 1540 } |
1534 | 1541 |
1581 } | 1588 } |
1582 | 1589 |
1583 /* Else try to guess the language given the file name. */ | 1590 /* Else try to guess the language given the file name. */ |
1584 if (parser == NULL) | 1591 if (parser == NULL) |
1585 { | 1592 { |
1586 lang = get_language_from_filename (curfdp->infname); | 1593 lang = get_language_from_filename (curfdp->infname, TRUE); |
1587 if (lang != NULL && lang->function != NULL) | 1594 if (lang != NULL && lang->function != NULL) |
1588 { | 1595 { |
1589 curfdp->lang = lang; | 1596 curfdp->lang = lang; |
1590 parser = lang->function; | 1597 parser = lang->function; |
1591 } | 1598 } |
1620 parser = lang->function; | 1627 parser = lang->function; |
1621 } | 1628 } |
1622 } | 1629 } |
1623 } | 1630 } |
1624 | 1631 |
1632 /* We rewind here, even if inf may be a pipe. We fail if the | |
1633 length of the first line is longer than the pipe block size, | |
1634 which is unlikely. */ | |
1635 if (parser == NULL) | |
1636 rewind (inf); | |
1637 #if 0 | |
1638 /* Else try to guess the language given the case insensitive file name. */ | |
1639 if (parser == NULL) | |
1640 { | |
1641 lang = get_language_from_filename (curfdp->infname, FALSE); | |
1642 if (lang != NULL && lang->function != NULL) | |
1643 { | |
1644 curfdp->lang = lang; | |
1645 parser = lang->function; | |
1646 } | |
1647 } | |
1648 #endif | |
1625 if (!no_line_directive | 1649 if (!no_line_directive |
1626 && curfdp->lang != NULL && curfdp->lang->metasource) | 1650 && curfdp->lang != NULL && curfdp->lang->metasource) |
1627 /* It may be that this is an xxx.y file, and we already parsed an xxx.c | 1651 /* It may be that this is a bingo.y file, and we already parsed a bingo.c |
1628 file, or anyway we parsed a file that is automatically generated from | 1652 file, or anyway we parsed a file that is automatically generated from |
1629 this one. If this is the case, the xxx.c file contained #line | 1653 this one. If this is the case, the bingo.c file contained #line |
1630 directives that generated tags pointing to this file. Let's delete | 1654 directives that generated tags pointing to this file. Let's delete |
1631 them all before parsing this file, which is the real source. */ | 1655 them all before parsing this file, which is the real source. */ |
1632 { | 1656 { |
1633 fdesc **fdpp = &fdhead; | 1657 fdesc **fdpp = &fdhead; |
1634 while (*fdpp != NULL) | 1658 while (*fdpp != NULL) |
1640 fdesc *badfdp = *fdpp; | 1664 fdesc *badfdp = *fdpp; |
1641 | 1665 |
1642 *fdpp = badfdp->next; /* remove the bad description from the list */ | 1666 *fdpp = badfdp->next; /* remove the bad description from the list */ |
1643 fdpp = &badfdp->next; /* advance the list pointer */ | 1667 fdpp = &badfdp->next; /* advance the list pointer */ |
1644 | 1668 |
1645 fprintf (stderr, "Removing references to \"%s\" obtained from \"%s\"\n", | 1669 if (DEBUG) |
1646 badfdp->taggedfname, badfdp->infname); | 1670 fprintf (stderr, |
1671 "Removing references to \"%s\" obtained from \"%s\"\n", | |
1672 badfdp->taggedfname, badfdp->infname); | |
1673 | |
1647 /* Delete the tags referring to badfdp. */ | 1674 /* Delete the tags referring to badfdp. */ |
1648 invalidate_nodes (badfdp, nodehead); | 1675 invalidate_nodes (badfdp, nodehead); |
1649 | 1676 |
1650 /* Delete badfdp. */ | 1677 /* Delete badfdp. */ |
1651 if (badfdp->infname != NULL) free (badfdp->infname); | 1678 if (badfdp->infname != NULL) free (badfdp->infname); |
1662 if (parser != NULL) | 1689 if (parser != NULL) |
1663 { | 1690 { |
1664 parser (inf); | 1691 parser (inf); |
1665 return; | 1692 return; |
1666 } | 1693 } |
1667 | |
1668 /* We rewind here, even if inf may be a pipe. We fail if the | |
1669 length of the first line is longer than the pipe block size, | |
1670 which is unlikely. */ | |
1671 rewind (inf); | |
1672 | 1694 |
1673 /* Else try Fortran. */ | 1695 /* Else try Fortran. */ |
1674 old_last_node = last_node; | 1696 old_last_node = last_node; |
1675 curfdp->lang = get_language_from_langname ("fortran"); | 1697 curfdp->lang = get_language_from_langname ("fortran"); |
1676 Fortran_functions (inf); | 1698 Fortran_functions (inf); |
1914 fdesc *badfdp; | 1936 fdesc *badfdp; |
1915 node *np; | 1937 node *np; |
1916 { | 1938 { |
1917 if (np->left != NULL) | 1939 if (np->left != NULL) |
1918 invalidate_nodes (badfdp, np->left); | 1940 invalidate_nodes (badfdp, np->left); |
1941 /* Memory leak here: if not CTAGS, in which case it would be quite | |
1942 difficult, the node could be freed. If CTAGS the node is part of a | |
1943 binary tree, if not it is part of a list of lists. */ | |
1919 if (np->fdp == badfdp) | 1944 if (np->fdp == badfdp) |
1920 np-> valid = FALSE; | 1945 np-> valid = FALSE; |
1921 if (np->right != NULL) | 1946 if (np->right != NULL) |
1922 invalidate_nodes (badfdp, np->right); | 1947 invalidate_nodes (badfdp, np->right); |
1923 } | 1948 } |
5739 r = sp; | 5764 r = sp; |
5740 } while (*sp++); | 5765 } while (*sp++); |
5741 return (char *)r; | 5766 return (char *)r; |
5742 } | 5767 } |
5743 | 5768 |
5744 | |
5745 /* | 5769 /* |
5746 * Return the ptr in sp at which the character c first | 5770 * Return the ptr in sp at which the character c first |
5747 * appears; NULL if not found | 5771 * appears; NULL if not found |
5748 * | 5772 * |
5749 * Identical to POSIX strchr, included for portability. | 5773 * Identical to POSIX strchr, included for portability. |
5757 { | 5781 { |
5758 if (*sp == c) | 5782 if (*sp == c) |
5759 return (char *)sp; | 5783 return (char *)sp; |
5760 } while (*sp++); | 5784 } while (*sp++); |
5761 return NULL; | 5785 return NULL; |
5786 } | |
5787 | |
5788 /* | |
5789 * Return TRUE if the two strings are equal, ignoring case for alphabetic | |
5790 * characters. | |
5791 * | |
5792 * Analogous to BSD's strcasecmp, included for portability. | |
5793 */ | |
5794 static bool | |
5795 strcaseeq (s1, s2) | |
5796 register const char *s1; | |
5797 register const char *s2; | |
5798 { | |
5799 while (*s1 != '\0' | |
5800 && (ISALPHA (*s1) && ISALPHA (*s2) | |
5801 ? lowcase (*s1) == lowcase (*s2) | |
5802 : *s1 == *s2)) | |
5803 s1++, s2++; | |
5804 | |
5805 return (*s1 == *s2); | |
5762 } | 5806 } |
5763 | 5807 |
5764 /* Skip spaces, return new pointer. */ | 5808 /* Skip spaces, return new pointer. */ |
5765 static char * | 5809 static char * |
5766 skip_spaces (cp) | 5810 skip_spaces (cp) |