diff options
author | Paul Smith <psmith@gnu.org> | 2016-03-19 17:26:08 -0400 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2016-03-21 00:44:53 -0400 |
commit | 2b9dd215d588a1b9aa8eaa398e567414afaafce8 (patch) | |
tree | 5fa7dd34968fe6c63ef78bcc83aaa795cf1144e5 /function.c | |
parent | fc2ddebdae087dbdd4b0db7654696e1a0e53ebc3 (diff) |
* function.c (func_file): Support reading from files.
* NEWS: Add information about reading files.
* make.texi (File Function): Describe reading files.
* tests/scripts/functions/file: Test new features for $(file ...)
Diffstat (limited to 'function.c')
-rw-r--r-- | function.c | 62 |
1 files changed, 51 insertions, 11 deletions
@@ -2208,27 +2208,67 @@ func_file (char *o, char **argv, const char *funcname UNUSED) } fn = next_token (fn); - fp = fopen (fn, mode); + if (fn[0] == '\0') + O (fatal, *expanding_var, _("file: missing filename")); + + ENULLLOOP (fp, fopen (fn, mode)); if (fp == NULL) - { - const char *err = strerror (errno); - OSS (fatal, reading_file, _("open: %s: %s"), fn, err); - } + OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno)); + if (argv[1]) { int l = strlen (argv[1]); int nl = l == 0 || argv[1][l-1] != '\n'; if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF)) - { - const char *err = strerror (errno); - OSS (fatal, reading_file, _("write: %s: %s"), fn, err); - } + OSS (fatal, reading_file, _("write: %s: %s"), fn, strerror (errno)); + } + if (fclose (fp)) + OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno)); + } + else if (fn[0] == '<') + { + char *preo = o; + FILE *fp; + + fn = next_token (++fn); + if (fn[0] == '\0') + O (fatal, *expanding_var, _("file: missing filename")); + + if (argv[1]) + O (fatal, *expanding_var, _("file: too many arguments")); + + ENULLLOOP (fp, fopen (fn, "r")); + if (fp == NULL) + { + if (errno == ENOENT) + return o; + OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno)); } - fclose (fp); + + while (1) + { + char buf[1024]; + size_t l = fread (buf, 1, sizeof (buf), fp); + if (l > 0) + o = variable_buffer_output (o, buf, l); + + if (ferror (fp)) + if (errno != EINTR) + OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno)); + if (feof (fp)) + break; + } + if (fclose (fp)) + OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno)); + + /* Remove trailing newline. */ + if (o > preo && o[-1] == '\n') + if (--o > preo && o[-1] == '\r') + --o; } else - OS (fatal, reading_file, _("Invalid file operation: %s"), fn); + OS (fatal, *expanding_var, _("file: invalid file operation: %s"), fn); return o; } |