aboutsummaryrefslogtreecommitdiffhomepage
path: root/io.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-10-23 11:18:54 +0200
committerlemon <lsof@mailbox.org>2025-10-23 11:18:54 +0200
commit0a51f5b8d9b3d98225382277a176fa85ccdb5ab8 (patch)
treed4d4fa38c04db077bac14137f965d51385f87b6a /io.c
parentcb199f47ca31b079212fe4fd3987e5ba39b12273 (diff)
use libc's stdout/stderr; also eliminate some unnecessary recursion in bfmt
Diffstat (limited to 'io.c')
-rw-r--r--io.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/io.c b/io.c
index 6390d96..53cb6af 100644
--- a/io.c
+++ b/io.c
@@ -1,22 +1,35 @@
#include "c/lex.h"
+#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <errno.h>
-static char stdoutbuf[1024], stderrbuf[1024];
-struct wbuf bstdout = FDBUF(stdoutbuf, sizeof stdoutbuf, 1),
- bstderr = FDBUF(stderrbuf, sizeof stderrbuf, 2);
+struct wbuf bstdout, bstderr;
+
+void
+ioinit(void)
+{
+ bstdout.fp = stdout;
+ bstdout.isfp = 1;
+ bstderr.fp = stderr;
+ bstderr.isfp = 1;
+}
void
iowrite(struct wbuf *buf, const void *Src, int n)
{
const uchar *src = Src;
+ if (buf->isfp) {
+ fwrite(Src, 1, n, buf->fp);
+ buf->err = ferror(buf->fp) != 0;
+ return;
+ }
while (n > 0) {
int avail = buf->cap - buf->len;
int amt = avail < n ? avail : n;
@@ -40,6 +53,11 @@ ioflush(struct wbuf *buf)
{
int i, ret;
+ if (buf->isfp) {
+ fflush(buf->fp);
+ buf->err = ferror(buf->fp) != 0;
+ return;
+ }
buf->err = 0;
if (buf->fd < 0) {
buf->len = 0;
@@ -63,6 +81,10 @@ ioflush(struct wbuf *buf)
void
ioputc(struct wbuf *buf, uchar c)
{
+ if (buf->isfp) {
+ buf->err = fputc(c, buf->fp) != EOF;
+ return;
+ }
if (buf->len == buf->cap) {
if (buf->fd < 0) {
buf->err = 1;
@@ -381,6 +403,7 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
case 'S': /* string ptr + len */
s = va_arg(ap, const char *);
i = va_arg(ap, uint);
+ PriS:
assert(s && "%S null");
if (quote) {
n += bputc(buf, '"');
@@ -468,9 +491,16 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
n += bwriteS(buf, "\?\?\?");
break;
case TKNUMLIT:
- if (quote) n += bputc(buf, '`');
- n += bfmt(buf, "%S", tok->s, tok->len);
- if (quote) n += bputc(buf, '\'');
+ if (quote) {
+ n += bputc(buf, '`');
+ iowrite(buf, tok->s, tok->len);
+ n += tok->len;
+ n += bputc(buf, '\'');
+ } else {
+ s = tok->s;
+ i = tok->len;
+ goto PriS;
+ }
break;
case TKCHRLIT:
if (tok->wide) n += bputc(buf, tok->wideuni ? tok->wide == 1 ? 'u' : 'U' : 'L');
@@ -490,9 +520,12 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
n += bputc(buf, '\'');
break;
case TKSTRLIT:
- if (tok->wide == 0)
- n += bfmt(buf, "%'S", tok->s, tok->len);
- else {
+ if (tok->wide == 0) {
+ s = tok->s;
+ i = tok->len;
+ quote = 1;
+ goto PriS;
+ } else {
n += bputc(buf, tok->wideuni ? tok->wide == 1 ? 'u' : 'U' : 'L');
n += bputc(buf, '\"');
for (int i = 0; i < tok->len; ++i) {
@@ -547,7 +580,8 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
default:
if (quote) n += bputc(buf, '`');
if (in_range(tok->t, TKWBEGIN_, TKWEND_)) {
- n += bfmt(buf, "%s", tok->s);
+ iowrite(buf, tok->s, tok->len);
+ n += tok->len;
} else if (aisprint(tok->t)) {
n += bputc(buf, tok->t);
} else {
@@ -561,16 +595,16 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
tok = &(struct token) { va_arg(ap, int) };
switch (tok->t) {
case TKNUMLIT:
- n += bfmt(buf, "numeric literal");
+ n += bwriteS(buf, "numeric literal");
break;
case TKSTRLIT:
- n += bfmt(buf, "string literal");
+ n += bwriteS(buf, "string literal");
break;
case TKIDENT:
- n += bfmt(buf, "identifier");
+ n += bwriteS(buf, "identifier");
break;
case TKEOF:
- n += bfmt(buf, "<end-of-file>");
+ n += bwriteS(buf, "<end-of-file>");
break;
default:
if (tok->t >= TKWBEGIN_ && tok->t <= TKWEND_) {
@@ -628,6 +662,7 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
if (pad > 0) { /* left pad */
while (pad-- > buf->len)
n += bputc(out, ' ');
+ assert(buf != out);
iowrite(out, buf->buf, buf->len);
out->err |= buf->err;
} else if (pad < 0) { /* right pad */