summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-02-18 11:38:54 -0700
committerEric Blake <ebb9@byu.net>2009-02-18 15:06:20 -0700
commit028f5c5976a35256f5fa3804f33292a75ba56c6e (patch)
tree1d72384c7988c80d33b4ce6cfa5521713da08a2d
parent4cd6b69ea7747052d12c0f2c4c28be082b030b00 (diff)
downloadm4-028f5c5976a35256f5fa3804f33292a75ba56c6e.tar.gz
Speed up esyscmd with buffer reads.
* modules/gnu.c (esyscmd): Read blocks directly into obstack, rather than repeatedly reading bytes. Detect read errors. Signed-off-by: Eric Blake <ebb9@byu.net> (cherry picked from commit 1974da270a84d8c0cf2b3e3e08ce5292fdb211f3)
-rw-r--r--ChangeLog4
-rw-r--r--modules/gnu.c24
2 files changed, 25 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3f98309c..51fda555 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2009-02-18 Eric Blake <ebb9@byu.net>
+ Speed up esyscmd with buffer reads.
+ * modules/gnu.c (esyscmd): Read blocks directly into obstack,
+ rather than repeatedly reading bytes. Detect read errors.
+
Avoid risk of stack overflow.
* m4/output.c (insert_file): Avoid stack allocation of large
buffer.
diff --git a/modules/gnu.c b/modules/gnu.c
index f44f0ba4..e6c7691e 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -654,7 +654,6 @@ M4BUILTIN_HANDLER (esyscmd)
if (m4_set_sysval && m4_sysval_flush)
{
FILE *pin;
- int ch;
if (m4_get_safer_opt (context))
{
@@ -684,8 +683,27 @@ M4BUILTIN_HANDLER (esyscmd)
}
else
{
- while ((ch = getc (pin)) != EOF)
- obstack_1grow (obs, ch);
+ while (1)
+ {
+ size_t avail = obstack_room (obs);
+ if (!avail)
+ {
+ int ch = getc (pin);
+ if (ch == EOF)
+ break;
+ obstack_1grow (obs, ch);
+ }
+ else
+ {
+ size_t len = fread (obstack_next_free (obs), 1, avail, pin);
+ if (len <= 0)
+ break;
+ obstack_blank_fast (obs, len);
+ }
+ }
+ if (ferror (pin))
+ m4_warn (context, errno, me, _("cannot read pipe to command %s"),
+ quotearg_style (locale_quoting_style, cmd));
m4_set_sysval (pclose (pin));
}
}