Fix regression in ios_printf implementation

There was some problem with the way the varargs are handled. We had to
need to make (at least one) copy of them with va_copy(). The code is
brittle and I don't understand it, so just rip it all out and replace
with a fixed-size static buffer. It's a hack but we'll soon get rid of
printf completely so this will get us through the day until then.
This commit is contained in:
Lassi Kortela 2019-08-23 00:38:10 +03:00
parent 49e2ac5ae0
commit 9d4bf19367
1 changed files with 23 additions and 47 deletions

70
c/ios.c
View File

@ -3,6 +3,8 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <math.h>
#include <setjmp.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> // for printf #include <stdio.h> // for printf
@ -24,10 +26,16 @@
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#include "utils.h" #include "htable.h"
#include "utf8.h" #include "htableh_inc.h"
#include "ios.h" #include "ios.h"
#include "flisp.h"
#include "error.h"
#include "timefuncs.h" #include "timefuncs.h"
#include "utf8.h"
#include "utils.h"
#define MOST_OF(x) ((x) - ((x) >> 4)) #define MOST_OF(x) ((x) - ((x) >> 4))
@ -993,55 +1001,23 @@ char *ios_readline(struct ios *s)
return ios_takebuf(&dest, &n); return ios_takebuf(&dest, &n);
} }
int ios_vprintf(struct ios *s, const char *format, va_list args)
{
char *str;
va_list al;
size_t avail;
int len;
char *start;
va_copy(al, args);
if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) {
avail = s->maxsize - s->bpos;
start = s->buf + s->bpos;
len = vsnprintf(start, avail, format, args);
if (len < 0) {
goto done;
}
if (avail > (size_t)len) {
s->bpos += (size_t)len;
_write_update_pos(s);
// TODO: only works right if newline is at end
if (s->bm == bm_line && our_memrchr(start, '\n', (size_t)len)) {
ios_flush(s);
}
goto done;
}
}
len = vsnprintf(NULL, 0, format, al);
if (len <= 0) {
len = 0;
goto done;
}
if (!(str = calloc(1, len + 1))) {
goto done;
}
len = vsnprintf(str, len, format, al);
ios_write(s, str, len);
LLT_FREE(str);
done:
va_end(al);
return len;
}
int ios_printf(struct ios *s, const char *format, ...) int ios_printf(struct ios *s, const char *format, ...)
{ {
static char purkka[4096];
va_list args; va_list args;
int c; int len;
va_start(args, format); va_start(args, format);
c = ios_vprintf(s, format, args); ios_flush(s);
memset(purkka, 0, sizeof(purkka));
len = vsnprintf(purkka, sizeof(purkka), format, args);
if (len < 0) {
len = 0;
}
if (len > (int)sizeof(purkka)) {
lerror(MemoryError, "out of memory in ios_printf buffer");
}
ios_write(s, purkka, len);
va_end(args); va_end(args);
return c; return len;
} }