os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit cf69454fe5d34d92e4e4987efe0fa70c2974e999
parent c57ba5281c2a026ea671a56411ef8c0956f5836d
Author: erai <erai@omiltem.net>
Date:   Sat, 16 Mar 2024 11:39:46 -0400

buffered file io

Diffstat:
Malloc.c | 3+++
Mas.c | 16+++++++++++-----
Abufio.c | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc1.c | 18++++++++++++------
Mlex1.c | 29++++++++---------------------
Dwatch.sh | 39---------------------------------------
6 files changed, 150 insertions(+), 71 deletions(-)

diff --git a/alloc.c b/alloc.c @@ -60,3 +60,6 @@ alloc(c: *alloc, size: int): *byte { return ret; } + +free(a: *alloc, p: *byte): void { +} diff --git a/as.c b/as.c @@ -19,7 +19,7 @@ struct chunk { struct assembler { a: *alloc; - fdout: int; + out: *file; at: int; text: *chunk; text_end: *chunk; @@ -29,7 +29,7 @@ setup_assembler(a: *alloc): *assembler { var c: *assembler; c = alloc(a, sizeof(*c)): *assembler; c.a = a; - c.fdout = 1; + c.out = 0: *file; c.at = 0; c.text = 0:*chunk; c.text_end = 0:*chunk; @@ -37,13 +37,13 @@ setup_assembler(a: *alloc): *assembler { } putchar(c: *assembler, ch: int) { - fdputc(c.fdout, ch); + fputc(c.out, ch); } open_output(c: *assembler, filename: *byte) { var fd: int; - if (c.fdout != 1) { + if (c.out) { die("multiple output files"); } @@ -54,7 +54,7 @@ open_output(c: *assembler, filename: *byte) { die("failed to open output"); } - c.fdout = fd; + c.out = fopen(fd, c.a); } // Create a new label @@ -746,6 +746,10 @@ writeout(c: *assembler, start: *label) { var load_addr: int; var entry: int; + if (!c.out) { + open_output(c, "a.out"); + } + load_addr = 0x100000; text_size = c.at; @@ -957,4 +961,6 @@ writeout(c: *assembler, start: *label) { } b = b.next; } + + fflush(c.out); } diff --git a/bufio.c b/bufio.c @@ -0,0 +1,116 @@ +struct file { + a: *alloc; + fd: int; + buf: *byte; + r: int; + w: int; + cap: int; + eof: int; +} + +fopen(fd: int, a: *alloc): *file { + var f: *file; + + f = alloc(a, sizeof(*f)): *file; + + f.fd = fd; + f.a = a; + f.r = 0; + f.w = 0; + f.cap = 4096; + f.eof = 0; + + f.buf = alloc(a, f.cap); + + return f; +} + +fclose(f: *file): void { + if (close(f.fd) != 0) { + die("write failed"); + } + + free(f.a, f.buf); + + free(f.a, f: *byte); +} + +fflush(f: *file): void { + var ret: int; + + loop { + if (f.r == f.w) { + f.r = 0; + f.w = 0; + return; + } + + ret = write(f.fd, &f.buf[f.r], f.w - f.r); + + if (ret < 0) { + die("write failed"); + } + + f.r = f.r + ret; + } +} + +ffill(f: *file): void { + var ret: int; + + if (f.eof) { + return; + } + + if (f.r == f.w) { + f.r = 0; + f.w = 0; + } + + if (f.w == f.cap) { + die("out of space"); + } + + ret = read(f.fd, &f.buf[f.w], f.cap - f.w); + + if (ret < 0) { + die("read failed"); + } + + if (ret == 0) { + f.eof = 1; + } + + f.w = f.w + ret; +} + +fputc(f: *file, ch: int): void { + if (f.w == f.cap) { + fflush(f); + } + + f.buf[f.w] = ch: byte; + f.w = f.w + 1; + + if (ch == '\n') { + fflush(f); + } +} + +fgetc(f: *file): int { + var ch: int; + + if (f.r == f.w) { + ffill(f); + } + + if (f.eof) { + return -1; + } + + ch = f.buf[f.r]: int; + + f.r = f.r + 1; + + return ch; +} diff --git a/cc1.c b/cc1.c @@ -38,7 +38,7 @@ struct compiler { a: *alloc; // Lexer - fdin: int; + in: *file; nc: int; filename: *byte; lineno: int; @@ -82,7 +82,7 @@ comp_setup(a: *alloc): *compiler { c.a = a; - c.fdin = 0; + c.in = 0: *file; c.nc = 0; c.filename = 0:*byte; c.lineno = 1; @@ -1271,6 +1271,16 @@ main(argc: int, argv: **byte, envp: **byte) { continue; } + if (!strcmp(argv[i], "-C")) { + i = i + 1; + if (i >= argc) { + die("invalid -C at end of argument list"); + } + //open_coutput(c.as, argv[i]); + i = i + 1; + continue; + } + if (argv[i][0] == '-':byte) { die("invalid argument"); } @@ -1284,10 +1294,6 @@ main(argc: int, argv: **byte, envp: **byte) { compile(c, p); - if (c.as.fdout == 1) { - open_output(c.as, "a.out"); - } - d = find(c, "syscall", 0:*byte, 1); if (d.func_defined && !d.func_label.fixed) { fixup_label(c.as, d.func_label); diff --git a/lex1.c b/lex1.c @@ -53,34 +53,21 @@ open_source(c: *compiler, filename: *byte) { cdie(c, "failed to open file"); } - c.fdin = fd; - c.nc = getchar(c); + c.in = fopen(fd, c.a); + c.nc = fgetc(c.in); feed(c); } close_source(c: *compiler) { - if (c.fdin != 0) { - close(c.fdin); + if (c.in) { + fclose(c.in); } - c.fdin = 0; -} - -getchar(c: *compiler): int { - var b: byte; - var ret: int; - ret = read(c.fdin, &b, 1); - if (ret < 0) { - exit(3); - } - if (ret == 0) { - return -1; - } - return b: int; + c.in = 0: *file; } feedc(c: *compiler) { - c.nc = getchar(c); + c.nc = fgetc(c.in); if (c.nc == '\n') { c.lineno = c.lineno + 1; c.colno = 0; @@ -304,10 +291,10 @@ feed_escape(c: *compiler) { } else if (c.nc == 'n') { c.nc = '\n'; } else if (c.nc == 'x') { - c.nc = getchar(c); + c.nc = fgetc(c.in); hex = hexdig(c) * 16; - c.nc = getchar(c); + c.nc = fgetc(c.in); hex = hex + hexdig(c); c.nc = hex; diff --git a/watch.sh b/watch.sh @@ -1,39 +0,0 @@ -#!/bin/bash - -trap : TERM # INT - -cd "$(dirname "$0")" - -# Create event pipe -if ! [ -p ~/.post ]; then - mkfifo ~/.post -fi - -# Child process to wait for events -( - trap : INT - - # Wait for timeout - sleep 1 - kill -INT 0 - - # Wait for someone to post an event - : < ~/.post - kill -TERM 0 -) & - -# Run build with pager -"$@" 2>&1 | less -Rc; rc=$? -stty sane - -# Kill event process -kill -TERM 0 -wait - -# Pager exited from our TERM -if [ ${rc} -ne 15 ] && [ ${rc} -ne 143 ]; then - exit 0 -fi - -# Build again -exec "$0" "$@"