aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorPaul Eggert2015-05-24 14:20:09 -0700
committerPaul Eggert2015-05-24 14:20:09 -0700
commit379d77dfa3a03083517114e1ce32bb72137aea05 (patch)
tree74104c55d057e646d3ea10c1e05ae1400fe6b613 /lib-src
parent3441b0cc61d88edb921bbf27462f3f961e794b4d (diff)
downloademacs-379d77dfa3a03083517114e1ce32bb72137aea05.tar.gz
emacs-379d77dfa3a03083517114e1ce32bb72137aea05.zip
Improve etags I/O error reporting
* lib-src/etags.c: Don't include sys/types.h and sys/stat.h; no longer needed. (infilename): New static var. (process_file_name): Don't call 'stat'. Instead, just open the file for reading and report any errors. Don't bother making a copy of the file argument; it's not needed. Be more careful to use the failing errno when reporting an error. Quote the real name better (though no perfectly) when passing it to the shell. (reset_input): New function, which reports I/O errors. All uses of 'rewind' changed to use this function. (perhaps_more_input): New function, which also checks for I/O errors. All uses of 'feof' changed to use this function. (analyze_regex): Report an error if fclose fails. (readline_internal): Report an error if getc fails. (etags_mktmp): Return an error if close fails.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c183
1 files changed, 103 insertions, 80 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index ea337d41008..48d2299410a 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -127,8 +127,6 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
127#include <sysstdio.h> 127#include <sysstdio.h>
128#include <errno.h> 128#include <errno.h>
129#include <fcntl.h> 129#include <fcntl.h>
130#include <sys/types.h>
131#include <sys/stat.h>
132#include <binary-io.h> 130#include <binary-io.h>
133#include <c-ctype.h> 131#include <c-ctype.h>
134#include <c-strcase.h> 132#include <c-strcase.h>
@@ -355,7 +353,7 @@ static void just_read_file (FILE *);
355 353
356static language *get_language_from_langname (const char *); 354static language *get_language_from_langname (const char *);
357static void readline (linebuffer *, FILE *); 355static void readline (linebuffer *, FILE *);
358static long readline_internal (linebuffer *, FILE *); 356static long readline_internal (linebuffer *, FILE *, char const *);
359static bool nocase_tail (const char *); 357static bool nocase_tail (const char *);
360static void get_tag (char *, char **); 358static void get_tag (char *, char **);
361 359
@@ -407,6 +405,7 @@ static ptrdiff_t whatlen_max; /* maximum length of any 'what' member */
407 405
408static fdesc *fdhead; /* head of file description list */ 406static fdesc *fdhead; /* head of file description list */
409static fdesc *curfdp; /* current file description */ 407static fdesc *curfdp; /* current file description */
408static char *infilename; /* current input file name */
410static int lineno; /* line number of current line */ 409static int lineno; /* line number of current line */
411static long charno; /* current character number */ 410static long charno; /* current character number */
412static long linecharno; /* charno of start of current line */ 411static long linecharno; /* charno of start of current line */
@@ -1247,7 +1246,7 @@ main (int argc, char **argv)
1247 if (parsing_stdin) 1246 if (parsing_stdin)
1248 fatal ("cannot parse standard input AND read file names from it", 1247 fatal ("cannot parse standard input AND read file names from it",
1249 (char *)NULL); 1248 (char *)NULL);
1250 while (readline_internal (&filename_lb, stdin) > 0) 1249 while (readline_internal (&filename_lb, stdin, "-") > 0)
1251 process_file_name (filename_lb.buffer, lang); 1250 process_file_name (filename_lb.buffer, lang);
1252 } 1251 }
1253 else 1252 else
@@ -1470,7 +1469,6 @@ get_language_from_filename (char *file, int case_sensitive)
1470static void 1469static void
1471process_file_name (char *file, language *lang) 1470process_file_name (char *file, language *lang)
1472{ 1471{
1473 struct stat stat_buf;
1474 FILE *inf; 1472 FILE *inf;
1475 fdesc *fdp; 1473 fdesc *fdp;
1476 compressor *compr; 1474 compressor *compr;
@@ -1487,13 +1485,13 @@ process_file_name (char *file, language *lang)
1487 compr = get_compressor_from_suffix (file, &ext); 1485 compr = get_compressor_from_suffix (file, &ext);
1488 if (compr) 1486 if (compr)
1489 { 1487 {
1490 real_name = compressed_name = savestr (file); 1488 compressed_name = file;
1491 uncompressed_name = savenstr (file, ext - file); 1489 uncompressed_name = savenstr (file, ext - file);
1492 } 1490 }
1493 else 1491 else
1494 { 1492 {
1495 compressed_name = NULL; 1493 compressed_name = NULL;
1496 real_name = uncompressed_name = savestr (file); 1494 uncompressed_name = file;
1497 } 1495 }
1498 1496
1499 /* If the canonicalized uncompressed name 1497 /* If the canonicalized uncompressed name
@@ -1505,83 +1503,91 @@ process_file_name (char *file, language *lang)
1505 goto cleanup; 1503 goto cleanup;
1506 } 1504 }
1507 1505
1508 if (stat (real_name, &stat_buf) != 0) 1506 inf = fopen (file, "r" FOPEN_BINARY);
1507 if (inf)
1508 real_name = file;
1509 else
1509 { 1510 {
1510 /* Reset real_name and try with a different name. */ 1511 int file_errno = errno;
1511 real_name = NULL; 1512 if (compressed_name)
1512 if (compressed_name != NULL) /* try with the given suffix */
1513 { 1513 {
1514 if (stat (uncompressed_name, &stat_buf) == 0) 1514 /* Try with the given suffix. */
1515 inf = fopen (uncompressed_name, "r" FOPEN_BINARY);
1516 if (inf)
1515 real_name = uncompressed_name; 1517 real_name = uncompressed_name;
1516 } 1518 }
1517 else /* try all possible suffixes */ 1519 else
1518 { 1520 {
1521 /* Try all possible suffixes. */
1519 for (compr = compressors; compr->suffix != NULL; compr++) 1522 for (compr = compressors; compr->suffix != NULL; compr++)
1520 { 1523 {
1521 compressed_name = concat (file, ".", compr->suffix); 1524 compressed_name = concat (file, ".", compr->suffix);
1522 if (stat (compressed_name, &stat_buf) != 0) 1525 inf = fopen (compressed_name, "r" FOPEN_BINARY);
1526 if (inf)
1527 {
1528 real_name = compressed_name;
1529 break;
1530 }
1531 if (MSDOS)
1523 { 1532 {
1524 if (MSDOS) 1533 char *suf = compressed_name + strlen (file);
1534 size_t suflen = strlen (compr->suffix) + 1;
1535 for ( ; suf[1]; suf++, suflen--)
1525 { 1536 {
1526 char *suf = compressed_name + strlen (file); 1537 memmove (suf, suf + 1, suflen);
1527 size_t suflen = strlen (compr->suffix) + 1; 1538 inf = fopen (compressed_name, "r" FOPEN_BINARY);
1528 for ( ; suf[1]; suf++, suflen--) 1539 if (inf)
1529 { 1540 {
1530 memmove (suf, suf + 1, suflen); 1541 real_name = compressed_name;
1531 if (stat (compressed_name, &stat_buf) == 0) 1542 break;
1532 {
1533 real_name = compressed_name;
1534 break;
1535 }
1536 } 1543 }
1537 if (real_name != NULL) 1544 }
1538 break; 1545 if (inf)
1539 } /* MSDOS */ 1546 break;
1540 free (compressed_name);
1541 compressed_name = NULL;
1542 }
1543 else
1544 {
1545 real_name = compressed_name;
1546 break;
1547 } 1547 }
1548 free (compressed_name);
1549 compressed_name = NULL;
1548 } 1550 }
1549 } 1551 }
1550 if (real_name == NULL) 1552 if (! inf)
1551 { 1553 {
1554 errno = file_errno;
1552 perror (file); 1555 perror (file);
1553 goto cleanup; 1556 goto cleanup;
1554 } 1557 }
1555 } /* try with a different name */
1556
1557 if (!S_ISREG (stat_buf.st_mode))
1558 {
1559 error ("skipping %s: it is not a regular file.", real_name);
1560 goto cleanup;
1561 } 1558 }
1559
1562 if (real_name == compressed_name) 1560 if (real_name == compressed_name)
1563 { 1561 {
1562 fclose (inf);
1564 tmp_name = etags_mktmp (); 1563 tmp_name = etags_mktmp ();
1565 if (!tmp_name) 1564 if (!tmp_name)
1566 inf = NULL; 1565 inf = NULL;
1567 else 1566 else
1568 { 1567 {
1569 char *cmd1 = concat (compr->command, " ", real_name); 1568 char *cmd1 = concat (compr->command, " '", real_name);
1570 char *cmd = concat (cmd1, " > ", tmp_name); 1569 char *cmd = concat (cmd1, "' > ", tmp_name);
1571 free (cmd1); 1570 free (cmd1);
1571 int tmp_errno;
1572 if (system (cmd) == -1) 1572 if (system (cmd) == -1)
1573 inf = NULL; 1573 {
1574 inf = NULL;
1575 tmp_errno = EINVAL;
1576 }
1574 else 1577 else
1575 inf = fopen (tmp_name, "r" FOPEN_BINARY); 1578 {
1579 inf = fopen (tmp_name, "r" FOPEN_BINARY);
1580 tmp_errno = errno;
1581 }
1576 free (cmd); 1582 free (cmd);
1583 errno = tmp_errno;
1584 }
1585
1586 if (!inf)
1587 {
1588 perror (real_name);
1589 goto cleanup;
1577 } 1590 }
1578 }
1579 else
1580 inf = fopen (real_name, "r" FOPEN_BINARY);
1581 if (inf == NULL)
1582 {
1583 perror (real_name);
1584 goto cleanup;
1585 } 1591 }
1586 1592
1587 process_file (inf, uncompressed_name, lang); 1593 process_file (inf, uncompressed_name, lang);
@@ -1596,8 +1602,10 @@ process_file_name (char *file, language *lang)
1596 pfatal (file); 1602 pfatal (file);
1597 1603
1598 cleanup: 1604 cleanup:
1599 free (compressed_name); 1605 if (compressed_name != file)
1600 free (uncompressed_name); 1606 free (compressed_name);
1607 if (uncompressed_name != file)
1608 free (uncompressed_name);
1601 last_node = NULL; 1609 last_node = NULL;
1602 curfdp = NULL; 1610 curfdp = NULL;
1603 return; 1611 return;
@@ -1609,6 +1617,7 @@ process_file (FILE *fh, char *fn, language *lang)
1609 static const fdesc emptyfdesc; 1617 static const fdesc emptyfdesc;
1610 fdesc *fdp; 1618 fdesc *fdp;
1611 1619
1620 infilename = fn;
1612 /* Create a new input file description entry. */ 1621 /* Create a new input file description entry. */
1613 fdp = xnew (1, fdesc); 1622 fdp = xnew (1, fdesc);
1614 *fdp = emptyfdesc; 1623 *fdp = emptyfdesc;
@@ -1672,6 +1681,13 @@ process_file (FILE *fh, char *fn, language *lang)
1672 } 1681 }
1673} 1682}
1674 1683
1684static void
1685reset_input (FILE *inf)
1686{
1687 if (fseek (inf, 0, SEEK_SET) != 0)
1688 perror (infilename);
1689}
1690
1675/* 1691/*
1676 * This routine opens the specified file and calls the function 1692 * This routine opens the specified file and calls the function
1677 * which finds the function and type definitions. 1693 * which finds the function and type definitions.
@@ -1702,7 +1718,7 @@ find_entries (FILE *inf)
1702 1718
1703 /* Else look for sharp-bang as the first two characters. */ 1719 /* Else look for sharp-bang as the first two characters. */
1704 if (parser == NULL 1720 if (parser == NULL
1705 && readline_internal (&lb, inf) > 0 1721 && readline_internal (&lb, inf, infilename) > 0
1706 && lb.len >= 2 1722 && lb.len >= 2
1707 && lb.buffer[0] == '#' 1723 && lb.buffer[0] == '#'
1708 && lb.buffer[1] == '!') 1724 && lb.buffer[1] == '!')
@@ -1731,7 +1747,7 @@ find_entries (FILE *inf)
1731 } 1747 }
1732 } 1748 }
1733 1749
1734 rewind (inf); 1750 reset_input (inf);
1735 1751
1736 /* Else try to guess the language given the case insensitive file name. */ 1752 /* Else try to guess the language given the case insensitive file name. */
1737 if (parser == NULL) 1753 if (parser == NULL)
@@ -1755,7 +1771,7 @@ find_entries (FILE *inf)
1755 if (old_last_node == last_node) 1771 if (old_last_node == last_node)
1756 /* No Fortran entries found. Try C. */ 1772 /* No Fortran entries found. Try C. */
1757 { 1773 {
1758 rewind (inf); 1774 reset_input (inf);
1759 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c"); 1775 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
1760 find_entries (inf); 1776 find_entries (inf);
1761 } 1777 }
@@ -2965,7 +2981,7 @@ do { \
2965 2981
2966#define CNL() \ 2982#define CNL() \
2967do { \ 2983do { \
2968 CNL_SAVE_DEFINEDEF(); \ 2984 CNL_SAVE_DEFINEDEF (); \
2969 if (savetoken.valid) \ 2985 if (savetoken.valid) \
2970 { \ 2986 { \
2971 token = savetoken; \ 2987 token = savetoken; \
@@ -2994,6 +3010,12 @@ make_C_tag (bool isfun)
2994 token.valid = false; 3010 token.valid = false;
2995} 3011}
2996 3012
3013static bool
3014perhaps_more_input (FILE *inf)
3015{
3016 return !feof (inf) && !ferror (inf);
3017}
3018
2997 3019
2998/* 3020/*
2999 * C_entries () 3021 * C_entries ()
@@ -3051,7 +3073,7 @@ C_entries (int c_ext, FILE *inf)
3051 { qualifier = "::"; qlen = 2; } 3073 { qualifier = "::"; qlen = 2; }
3052 3074
3053 3075
3054 while (!feof (inf)) 3076 while (perhaps_more_input (inf))
3055 { 3077 {
3056 c = *lp++; 3078 c = *lp++;
3057 if (c == '\\') 3079 if (c == '\\')
@@ -3892,13 +3914,10 @@ Yacc_entries (FILE *inf)
3892 3914
3893/* Useful macros. */ 3915/* Useful macros. */
3894#define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \ 3916#define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3895 for (; /* loop initialization */ \ 3917 while (perhaps_more_input (file_pointer) \
3896 !feof (file_pointer) /* loop test */ \ 3918 && (readline (&(line_buffer), file_pointer), \
3897 && /* instructions at start of loop */ \ 3919 (char_pointer) = (line_buffer).buffer, \
3898 (readline (&line_buffer, file_pointer), \ 3920 true)) \
3899 char_pointer = line_buffer.buffer, \
3900 true); \
3901 )
3902 3921
3903#define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \ 3922#define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \
3904 ((assert ("" kw), true) /* syntax error if not a literal string */ \ 3923 ((assert ("" kw), true) /* syntax error if not a literal string */ \
@@ -3919,7 +3938,7 @@ Yacc_entries (FILE *inf)
3919static void 3938static void
3920just_read_file (FILE *inf) 3939just_read_file (FILE *inf)
3921{ 3940{
3922 while (!feof (inf)) 3941 while (perhaps_more_input (inf))
3923 readline (&lb, inf); 3942 readline (&lb, inf);
3924} 3943}
3925 3944
@@ -4074,7 +4093,7 @@ Ada_getit (FILE *inf, const char *name_qualifier)
4074 char *name; 4093 char *name;
4075 char c; 4094 char c;
4076 4095
4077 while (!feof (inf)) 4096 while (perhaps_more_input (inf))
4078 { 4097 {
4079 dbp = skip_spaces (dbp); 4098 dbp = skip_spaces (dbp);
4080 if (*dbp == '\0' 4099 if (*dbp == '\0'
@@ -4576,7 +4595,7 @@ Pascal_functions (FILE *inf)
4576 verify_tag = false; /* check if "extern" is ahead */ 4595 verify_tag = false; /* check if "extern" is ahead */
4577 4596
4578 4597
4579 while (!feof (inf)) /* long main loop to get next char */ 4598 while (perhaps_more_input (inf)) /* long main loop to get next char */
4580 { 4599 {
4581 c = *dbp++; 4600 c = *dbp++;
4582 if (c == '\0') /* if end of line */ 4601 if (c == '\0') /* if end of line */
@@ -5033,7 +5052,7 @@ TEX_mode (FILE *inf)
5033 TEX_opgrp = '<'; 5052 TEX_opgrp = '<';
5034 TEX_clgrp = '>'; 5053 TEX_clgrp = '>';
5035 } 5054 }
5036 rewind (inf); 5055 reset_input (inf);
5037} 5056}
5038 5057
5039/* Read environment and prepend it to the default string. 5058/* Read environment and prepend it to the default string.
@@ -5279,7 +5298,7 @@ prolog_skip_comment (linebuffer *plb, FILE *inf)
5279 return; 5298 return;
5280 readline (plb, inf); 5299 readline (plb, inf);
5281 } 5300 }
5282 while (!feof (inf)); 5301 while (perhaps_more_input (inf));
5283} 5302}
5284 5303
5285/* 5304/*
@@ -5629,10 +5648,11 @@ analyze_regex (char *regex_arg)
5629 if (regexfp == NULL) 5648 if (regexfp == NULL)
5630 pfatal (regexfile); 5649 pfatal (regexfile);
5631 linebuffer_init (&regexbuf); 5650 linebuffer_init (&regexbuf);
5632 while (readline_internal (&regexbuf, regexfp) > 0) 5651 while (readline_internal (&regexbuf, regexfp, regexfile) > 0)
5633 analyze_regex (regexbuf.buffer); 5652 analyze_regex (regexbuf.buffer);
5634 free (regexbuf.buffer); 5653 free (regexbuf.buffer);
5635 fclose (regexfp); 5654 if (fclose (regexfp) != 0)
5655 pfatal (regexfile);
5636 } 5656 }
5637 break; 5657 break;
5638 5658
@@ -5972,11 +5992,11 @@ get_tag (register char *bp, char **namepp)
5972 * appended to `filebuf'. 5992 * appended to `filebuf'.
5973 */ 5993 */
5974static long 5994static long
5975readline_internal (linebuffer *lbp, register FILE *stream) 5995readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
5976{ 5996{
5977 char *buffer = lbp->buffer; 5997 char *buffer = lbp->buffer;
5978 register char *p = lbp->buffer; 5998 char *p = lbp->buffer;
5979 register char *pend; 5999 char *pend;
5980 int chars_deleted; 6000 int chars_deleted;
5981 6001
5982 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */ 6002 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
@@ -5995,6 +6015,8 @@ readline_internal (linebuffer *lbp, register FILE *stream)
5995 } 6015 }
5996 if (c == EOF) 6016 if (c == EOF)
5997 { 6017 {
6018 if (ferror (stream))
6019 perror (filename);
5998 *p = '\0'; 6020 *p = '\0';
5999 chars_deleted = 0; 6021 chars_deleted = 0;
6000 break; 6022 break;
@@ -6055,7 +6077,7 @@ readline (linebuffer *lbp, FILE *stream)
6055 long result; 6077 long result;
6056 6078
6057 linecharno = charno; /* update global char number of line start */ 6079 linecharno = charno; /* update global char number of line start */
6058 result = readline_internal (lbp, stream); /* read line */ 6080 result = readline_internal (lbp, stream, infilename); /* read line */
6059 lineno += 1; /* increment global line number */ 6081 lineno += 1; /* increment global line number */
6060 charno += result; /* increment global char number */ 6082 charno += result; /* increment global char number */
6061 6083
@@ -6386,13 +6408,13 @@ etags_mktmp (void)
6386 6408
6387 char *templt = concat (tmpdir, slash, "etXXXXXX"); 6409 char *templt = concat (tmpdir, slash, "etXXXXXX");
6388 int fd = mkostemp (templt, O_CLOEXEC); 6410 int fd = mkostemp (templt, O_CLOEXEC);
6389 if (fd < 0) 6411 if (fd < 0 || close (fd) != 0)
6390 { 6412 {
6413 int temp_errno = errno;
6391 free (templt); 6414 free (templt);
6415 errno = temp_errno;
6392 templt = NULL; 6416 templt = NULL;
6393 } 6417 }
6394 else
6395 close (fd);
6396 6418
6397#if defined (DOS_NT) 6419#if defined (DOS_NT)
6398 /* The file name will be used in shell redirection, so it needs to have 6420 /* The file name will be used in shell redirection, so it needs to have
@@ -6402,6 +6424,7 @@ etags_mktmp (void)
6402 if (*p == '/') 6424 if (*p == '/')
6403 *p = '\\'; 6425 *p = '\\';
6404#endif 6426#endif
6427
6405 return templt; 6428 return templt;
6406} 6429}
6407 6430