summaryrefslogtreecommitdiff
path: root/src/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output.c')
-rw-r--r--src/output.c90
1 files changed, 60 insertions, 30 deletions
diff --git a/src/output.c b/src/output.c
index f62e7ea..4d3b4c2 100644
--- a/src/output.c
+++ b/src/output.c
@@ -99,9 +99,6 @@ struct output *out1 = &output;
struct output *out2 = &errout;
-#ifndef USE_GLIBC_STDIO
-static void __outstr(const char *, size_t, struct output *);
-#endif
static int xvsnprintf(char *, size_t, const char *, va_list);
@@ -134,16 +131,20 @@ RESET {
#endif
-#ifndef USE_GLIBC_STDIO
-static void
-__outstr(const char *p, size_t len, struct output *dest)
+void
+outmem(const char *p, size_t len, struct output *dest)
{
+#ifdef USE_GLIBC_STDIO
+ INTOFF;
+ fwrite(p, 1, len, dest->stream);
+ INTON;
+#else
size_t bufsize;
size_t offset;
size_t nleft;
nleft = dest->end - dest->nextc;
- if (nleft >= len) {
+ if (likely(nleft >= len)) {
buffered:
dest->nextc = mempcpy(dest->nextc, p, len);
return;
@@ -153,10 +154,13 @@ buffered:
if (!bufsize) {
;
} else if (dest->buf == NULL) {
+#ifdef notyet
if (dest->fd == MEM_OUT && len > bufsize) {
bufsize = len;
}
+#endif
offset = 0;
+#ifdef notyet
goto alloc;
} else if (dest->fd == MEM_OUT) {
offset = bufsize;
@@ -168,6 +172,7 @@ buffered:
if (bufsize < offset)
goto err;
alloc:
+#endif
INTOFF;
dest->buf = ckrealloc(dest->buf, bufsize);
dest->bufsize = bufsize;
@@ -183,11 +188,13 @@ alloc:
goto buffered;
if ((xwrite(dest->fd, p, len))) {
+#ifdef notyet
err:
+#endif
dest->flags |= OUTPUT_ERR;
}
-}
#endif
+}
void
@@ -201,7 +208,7 @@ outstr(const char *p, struct output *file)
size_t len;
len = strlen(p);
- __outstr(p, len, file);
+ outmem(p, len, file);
#endif
}
@@ -213,7 +220,7 @@ void
outcslow(int c, struct output *dest)
{
char buf = c;
- __outstr(&buf, 1, dest);
+ outmem(&buf, 1, dest);
}
#endif
@@ -283,35 +290,58 @@ fmtstr(char *outbuf, size_t length, const char *fmt, ...)
}
+static int xvasprintf(char **sp, size_t size, const char *f, va_list ap)
+{
+ char *s;
+ int len;
+ va_list ap2;
+
+ va_copy(ap2, ap);
+ len = xvsnprintf(*sp, size, f, ap2);
+ va_end(ap2);
+ if (len < 0)
+ sh_error("xvsnprintf failed");
+ if (len < size)
+ return len;
+
+ s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1);
+ *sp = s;
+ len = xvsnprintf(s, len + 1, f, ap);
+ return len;
+}
+
+
+int xasprintf(char **sp, const char *f, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, f);
+ ret = xvasprintf(sp, 0, f, ap);
+ va_end(ap);
+ return ret;
+}
+
+
#ifndef USE_GLIBC_STDIO
void
doformat(struct output *dest, const char *f, va_list ap)
{
struct stackmark smark;
char *s;
- int len, ret;
- size_t size;
- va_list ap2;
+ int len;
+ int olen;
- va_copy(ap2, ap);
- size = dest->end - dest->nextc;
- len = xvsnprintf(dest->nextc, size, f, ap2);
- va_end(ap2);
- if (len < 0) {
- dest->flags |= OUTPUT_ERR;
- return;
- }
- if (len < size) {
+ setstackmark(&smark);
+ s = dest->nextc;
+ olen = dest->end - dest->nextc;
+ len = xvasprintf(&s, olen, f, ap);
+ if (likely(olen > len)) {
dest->nextc += len;
- return;
+ goto out;
}
- setstackmark(&smark);
- s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1);
- ret = xvsnprintf(s, len + 1, f, ap);
- if (ret == len)
- __outstr(s, len, dest);
- else
- dest->flags |= OUTPUT_ERR;
+ outmem(s, len, dest);
+out:
popstackmark(&smark);
}
#endif