aboutsummaryrefslogtreecommitdiffhomepage
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
parentcb199f47ca31b079212fe4fd3987e5ba39b12273 (diff)
use libc's stdout/stderr; also eliminate some unnecessary recursion in bfmt
-rw-r--r--c/lex.c2
-rw-r--r--common.h19
-rw-r--r--io.c67
-rw-r--r--main.c11
4 files changed, 66 insertions, 33 deletions
diff --git a/c/lex.c b/c/lex.c
index 7c9b615..ec0b4d2 100644
--- a/c/lex.c
+++ b/c/lex.c
@@ -1206,7 +1206,7 @@ advancemacro(struct lexer *lx, struct token *tk)
return 0;
}
*tk = rl.tk[lx->macstk->idx++];
- assert(tk->t);
+ assert(tk->t && tk->t != TKEOF);
tk->span.ex = lx->macstk->exspan;
if (tryexpand(lx, tk))
return 0;
diff --git a/common.h b/common.h
index 6f01da0..9c9fd70 100644
--- a/common.h
+++ b/common.h
@@ -541,11 +541,17 @@ rsiter(int *i, uvlong rs)
/********/
struct wbuf {
- char *buf;
- const uint cap;
- uint len;
- int fd;
+ union {
+ struct {
+ char *buf;
+ const uint cap;
+ uint len;
+ int fd;
+ };
+ void *fp;
+ };
bool err;
+ bool isfp;
};
/* read-only file mapping that is at least 1 page larger than the real file
@@ -562,9 +568,10 @@ struct embedfile {
size_t len;
};
-#define MEMBUF(buf, cap) { (buf), (cap), .fd = -1 }
-#define FDBUF(buf, cap, fd_) { (buf), (cap), .fd = (fd_) }
+#define MEMBUF(buf_, cap_) { .buf = (buf_), .cap = (cap_), .fd = -1 }
+#define FDBUF(buf_, cap_, fd_) { .buf = (buf_), .cap = (cap_), .fd = (fd_) }
extern struct wbuf bstdout, bstderr;
+void ioinit(void);
void iowrite(struct wbuf *, const void *src, int n);
void ioputc(struct wbuf *, uchar);
void ioflush(struct wbuf *);
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 */
diff --git a/main.c b/main.c
index 9449d85..575cf46 100644
--- a/main.c
+++ b/main.c
@@ -9,13 +9,6 @@
struct option ccopt;
struct inclpaths *cinclpaths;
-static void
-flushstd(void)
-{
- ioflush(&bstdout);
- ioflush(&bstderr);
-}
-
/* parse an argument of the form 'opt=abcd'
* e.g. arg="foo=bar123"; opt="foo"; returns "bar123" */
static const char *
@@ -236,7 +229,6 @@ compileobjs(void)
if (!ccopt.dbg.any) mktemps();
for (int i = 0; i < task.ninf; ++i) {
- flushstd();
if ((p = fork()) < 0) {
error(NULL, "fork(): %s\n", strerror(errno));
exit(1);
@@ -284,7 +276,6 @@ dolink(void)
efmt("\n");
}
vpush(&cmd, NULL);
- flushstd();
if ((p = fork()) < 0) {
error(NULL, "fork(): %s\n", strerror(errno));
exit(1);
@@ -410,9 +401,9 @@ sysinclpaths(void)
int
main(int argc, char **argv)
{
- atexit(flushstd);
globarena->cap = sizeof(_arenamem.mem) - sizeof(struct arena);
+ ioinit();
/* setup defaults */
detectcolor();
sysinclpaths();