hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 37e7f3e666a32c82836915be63dce0699481ab3a
parent 62c7f5218df795c0b7936eab3a567322e4b84f5e
Author: Sebastian <sebastian@sebsite.pw>
Date:   Fri, 13 Jan 2023 14:20:29 -0500

all: don't autofill fields without a default value

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mbufio/buffered.ha | 27++++++++++++++++-----------
Mcrypto/chacha/chacha20.ha | 6+++---
Mcrypto/cipher/ctr.ha | 3++-
Mcrypto/cipher/gcm.ha | 13++++++++-----
Mcrypto/cipher/stream.ha | 14+++-----------
Mcrypto/salsa/salsa20.ha | 6+++---
Mencoding/pem/pem.ha | 11++++++-----
Mformat/tar/reader.ha | 42+++++++++++++++++++++++++++---------------
Mhare/unit/context.ha | 2+-
Mhare/unit/process.ha | 2+-
Mnet/+freebsd.ha | 4+---
Mnet/+linux.ha | 4+---
Mos/+linux/stdfd.ha | 4++++
Munix/poll/+freebsd.ha | 4++--
Munix/poll/+linux.ha | 4++--
Munix/signal/+linux.ha | 7++++++-
16 files changed, 86 insertions(+), 67 deletions(-)

diff --git a/bufio/buffered.ha b/bufio/buffered.ha @@ -59,23 +59,28 @@ export fn buffered( wbuf: []u8, ) bufstream = { static let flush_default = ['\n': u8]; - let s = bufstream { + + let stream = + if (len(rbuf) != 0 && len(wbuf) != 0) { + assert(rbuf: *[*]u8 != wbuf: *[*]u8, + "Cannot use bufio::buffered with same buffer for reads and writes"); + yield &buffered_vtable_rw; + } else if (len(rbuf) != 0) { + yield &buffered_vtable_r; + } else if (len(wbuf) != 0) { + yield &buffered_vtable_w; + } else { + abort("Must provide at least one buffer to bufio::buffered"); + }; + + return bufstream { + stream = stream, source = src, rbuffer = rbuf, wbuffer = wbuf, flush = flush_default, ... }; - if (len(rbuf) != 0 && len(wbuf) != 0) { - assert(rbuf: *[*]u8 != wbuf: *[*]u8, - "Cannot use bufio::buffered with same buffer for reads and writes"); - s.stream = &buffered_vtable_rw; - } else if (len(rbuf) != 0) { - s.stream = &buffered_vtable_r; - } else if (len(wbuf) != 0) { - s.stream = &buffered_vtable_w; - } else abort("Must provide at least one buffer to bufio::buffered"); - return s; }; // Flushes pending writes to the underlying stream. diff --git a/crypto/chacha/chacha20.ha b/crypto/chacha/chacha20.ha @@ -36,6 +36,8 @@ export type stream = struct { // with [[io::close]] after use to wipe sensitive data from memory. export fn chacha20() stream = { return stream { + stream = &cipher::xorstream_vtable, + h = 0, keybuf = &keybuf, advance = &advance, finish = &finish, @@ -52,7 +54,7 @@ export fn chacha20_init( key: *[KEYSIZE]u8, nonce: *[NONCESIZE]u8 ) void = { - cipher::xorstream_init(s, h); + s.h = h; s.state[0] = magic[0]; s.state[1] = magic[1]; @@ -69,8 +71,6 @@ export fn chacha20_init( s.state[13] = endian::legetu32(nonce[0..4]); s.state[14] = endian::legetu32(nonce[4..8]); s.state[15] = endian::legetu32(nonce[8..12]); - - s.xorused = BLOCKSIZE; }; // Initialise a XChacha20 stream. diff --git a/crypto/cipher/ctr.ha b/crypto/cipher/ctr.ha @@ -54,6 +54,8 @@ export fn ctr(h: io::handle, b: *block, iv: []u8, buf: []u8) ctr_stream = { }; let s = ctr_stream { + stream = &xorstream_vtable, + h = h, keybuf = &ctr_keybuf, advance = &ctr_advance, finish = &ctr_finish, @@ -65,7 +67,6 @@ export fn ctr(h: io::handle, b: *block, iv: []u8, buf: []u8) ctr_stream = { xorused = xorbufsz, ... }; - xorstream_init(&s, h); return s; }; diff --git a/crypto/cipher/gcm.ha b/crypto/cipher/gcm.ha @@ -13,7 +13,7 @@ export def GCMTAGSIZE: size = 16; export type gcmstream = struct { stream: io::stream, - block: *block, + block: nullable *block, handle: io::handle, tagbuf: [GCMBLOCKSIZE]u8, xorbuf: [GCMBLOCKSIZE]u8, @@ -51,6 +51,7 @@ const gcm_vtable: io::vtable = io::vtable { export fn gcm() gcmstream = { return gcmstream { stream = &gcm_vtable, + handle = 0, ... }; }; @@ -144,7 +145,7 @@ fn fillxorbuf(s: *gcmstream) void = { let y: [GCMBLOCKSIZE]u8 = [0...]; s.xorbuf[..] = s.y0[..]; beputu32(s.xorbuf[12..], s.y); - encrypt(s.block, s.xorbuf, s.xorbuf); + encrypt(s.block as *block, s.xorbuf, s.xorbuf); s.y += 1; s.xorbufpos = 0; }; @@ -205,7 +206,7 @@ export fn gcm_seal(s: *gcmstream, tag: []u8) void = { ghash_ctmul64(s.tagbuf, s.h, tag); // use tmp to store the resulting tag - encrypt(s.block, tag, s.y0); + encrypt(s.block as *block, tag, s.y0); xor(tag, tag, s.tagbuf); }; @@ -225,7 +226,7 @@ export fn gcm_verify(s: *gcmstream, tag: []u8) (void | errors::invalid) = { ghash_ctmul64(s.tagbuf, s.h, tmp); - encrypt(s.block, tmp, s.y0); + encrypt(s.block as *block, tmp, s.y0); xor(tmp, tmp, s.tagbuf); if (eqslice(tag, tmp) == 0) { @@ -241,5 +242,7 @@ fn gcm_closer(s: *io::stream) (void | io::error) = { bytes::zero(s.y0); bytes::zero(s.h); - finish(s.block); + if (s.block is *block) { + finish(s.block as *block); + }; }; diff --git a/crypto/cipher/stream.ha b/crypto/cipher/stream.ha @@ -4,9 +4,8 @@ use io; use crypto::math::{xor}; // An abstract interface for implementing streams that encrypt or decrypt by -// producing a key stream that is xored with the data. The implementing stream -// must call [[xorstream_init]] after creation so that [[io::reader]], -// [[io::writer]] and [[io::closer]] functions will be registered. +// producing a key stream that is xored with the data. The stream field should +// be set to &[[xorstream_vtable]]. // // After initializing the xorstream can be written to with [[io::write]] to // encrypt data and write it to the handle 'h'. For decrpytion 'h' will provide @@ -27,14 +26,7 @@ export type xorstream = struct { finish: *fn(s: *xorstream) void, }; -// Initialises a xorstream with the handle 'h' and sets [[io::reader]], -// [[io::writer]] and [[io::closer]] functions. -export fn xorstream_init(xs: *xorstream, h: io::handle) void = { - xs.h = h; - xs.stream = &xorstream_vtable; -}; - -const xorstream_vtable: io::vtable = io::vtable { +export const xorstream_vtable: io::vtable = io::vtable { writer = &xor_writer, reader = &xor_reader, closer = &xor_closer, diff --git a/crypto/salsa/salsa20.ha b/crypto/salsa/salsa20.ha @@ -35,6 +35,8 @@ export type stream = struct { // after use to wipe sensitive data from memory. export fn salsa20() stream = { return stream { + stream = &cipher::xorstream_vtable, + h = 0, keybuf = &keybuf, advance = &advance, finish = &finish, @@ -80,9 +82,7 @@ export fn salsa20_init( let counter: [8]u8 = [0...]; init(&s.state, key, nonce, &counter); - s.xorused = BLOCKSIZE; - - cipher::xorstream_init(s, h); + s.h = h; }; // Initialize an XSalsa20 stream. XSalsa20 differs from Salsa20 via the use of a diff --git a/encoding/pem/pem.ha b/encoding/pem/pem.ha @@ -112,8 +112,13 @@ export fn next(dec: *decoder) ((str, pemdecoder) | io::EOF | io::error) = { return (strio::string(&dec.label), pemdecoder { stream = &pemdecoder_vt, in = &dec.in, + b64_in = b64stream { + stream = &b64stream_r_vt, + in = &dec.in, + }, + // forcefully zero field (it's actually set in pem_read) + b64 = *(&([0...]: [size(base64::decoder)]u8): *base64::decoder), b64_ready = false, - ... }); }; @@ -128,10 +133,6 @@ fn pem_read(st: *io::stream, buf: []u8) (size | io::EOF | io::error) = { const st = st: *pemdecoder; assert(st.stream.reader == &pem_read); if (!st.b64_ready) { - st.b64_in = b64stream { - stream = &b64stream_r_vt, - in = st.in, - }; st.b64 = base64::newdecoder(&base64::std_encoding, &st.b64_in); st.b64_ready = true; }; diff --git a/format/tar/reader.ha b/format/tar/reader.ha @@ -58,23 +58,33 @@ export fn next(rd: *reader) (entry | error | io::EOF) = { return io::EOF; }; - let ent = entry { ... }; const reader = bufio::fixed(buf, io::mode::READ); const name = readstr(&reader, 100); - ent.mode = readoct(&reader, 8)?; - ent.uid = readoct(&reader, 8)?; - ent.gid = readoct(&reader, 8)?; - ent.fsize = readsize(&reader, 12)?; - ent.mtime = readoct(&reader, 12)?; - ent.checksum = readoct(&reader, 8)?; - ent.etype = readoct(&reader, 1)?: entry_type; - ent.link = readstr(&reader, 100); - - if (ent.etype == entry_type::FILE) { - ent.vtable = &file_vtable; - ent.src = rd.src; - ent.orig = ent.fsize; - ent.remain = ent.orig; + const mode = readoct(&reader, 8)?; + const uid = readoct(&reader, 8)?; + const gid = readoct(&reader, 8)?; + const fsize = readsize(&reader, 12)?; + const mtime = readoct(&reader, 12)?; + const checksum = readoct(&reader, 8)?; + const etype = readoct(&reader, 1)?: entry_type; + const link = readstr(&reader, 100); + + let ent = entry { + vtable = if (etype == entry_type::FILE) &file_vtable + else &nonfile_vtable, + src = rd.src, + orig = fsize, + remain = fsize, + name = name, + mode = mode, + uid = uid, + gid = gid, + fsize = fsize, + mtime = mtime, + checksum = checksum, + etype = etype, + link = link, + ... }; const ustar = readstr(&reader, 6); @@ -117,6 +127,8 @@ const file_vtable: io::vtable = io::vtable { ... }; +const nonfile_vtable: io::vtable = io::vtable { ... }; + fn file_read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = { let ent = s: *ent_reader; assert(ent.vtable == &file_vtable); diff --git a/hare/unit/context.ha b/hare/unit/context.ha @@ -5,5 +5,5 @@ use hare::types; type context = struct { store: *types::typestore, scope: *scope, - fntype: *types::func, + fntype: nullable *types::func, }; diff --git a/hare/unit/process.ha b/hare/unit/process.ha @@ -405,7 +405,7 @@ fn process_return(ctx: *context, aexpr: *ast::expr) (*expr | error) = { case let aexpr: *ast::expr => yield process_expr(ctx, aexpr)?; }; - // TODO: assert(types::assignable(ctx.fntype.result, rval.type)); + // TODO: assert(types::assignable(ctx.fntype.result as *types::func, rval.type)); return alloc(expr { start = aexpr.start, end = aexpr.end, diff --git a/net/+freebsd.ha b/net/+freebsd.ha @@ -21,15 +21,13 @@ export type sockflags = enum int { // available. Optionally accepts NOCLOEXEC and NONBLOCK flags. If flags are // supplied, the [[io::file]] returned will have the supplied flags set. export fn accept(sock: socket, flags: sockflags...) (socket | error) = { - let sn = rt::sockaddr {...}; - const sz = size(rt::sockaddr): u32; // Apply any supplied flags let f = 0i; for (let i = 0z; i < len(flags); i += 1) { f |= flags[i]; }; f ^= rt::SOCK_CLOEXEC; // invert CLOEXEC - const fd = match (rt::accept4(sock, &sn, &sz, f)) { + const fd = match (rt::accept4(sock, null, null, f)) { case let err: rt::errno => return errors::errno(err); case let fd: int => diff --git a/net/+linux.ha b/net/+linux.ha @@ -21,15 +21,13 @@ export type sockflags = enum int { // available. Optionally accepts NOCLOEXEC and NONBLOCK flags. If flags are // supplied, the [[io::file]] returned will have the supplied flags set. export fn accept(sock: socket, flags: sockflags...) (socket | error) = { - let sn = rt::sockaddr {...}; - const sz = size(rt::sockaddr): u32; // Apply any supplied flags let f = 0i; for (let i = 0z; i < len(flags); i += 1) { f |= flags[i]; }; f ^= rt::SOCK_CLOEXEC; // invert CLOEXEC - const fd = match (rt::accept4(sock, &sn, &sz, f: int)) { + const fd = match (rt::accept4(sock, null, null, f: int)) { case let err: rt::errno => return errors::errno(err); case let fd: int => diff --git a/os/+linux/stdfd.ha b/os/+linux/stdfd.ha @@ -6,11 +6,15 @@ use io; use rt; let stdin_bufio: bufio::bufstream = bufio::bufstream { + // Will be overwritten, but must be initialized + stream = null: io::stream, source = 0, ... }; let stdout_bufio: bufio::bufstream = bufio::bufstream { + // Will be overwritten, but must be initialized + stream = null: io::stream, source = 1, ... }; diff --git a/unix/poll/+freebsd.ha b/unix/poll/+freebsd.ha @@ -18,8 +18,8 @@ export type event = enum i16 { // A single file descriptor to be polled. export type pollfd = struct { fd: io::file, - events: event, - revents: event, + events: i16, + revents: i16, }; // Pass this [[time::duration]] to [[poll]] to cause it wait indefinitely for diff --git a/unix/poll/+linux.ha b/unix/poll/+linux.ha @@ -18,8 +18,8 @@ export type event = enum i16 { // A single file descriptor to be polled. export type pollfd = struct { fd: io::file, - events: event, - revents: event, + events: i16, + revents: i16, }; // Pass this [[time::duration]] to [[poll]] to cause it wait indefinitely for diff --git a/unix/signal/+linux.ha b/unix/signal/+linux.ha @@ -36,7 +36,12 @@ export fn handle( // Filled in by rt: sa_restorer = null: *fn () void, }; - let old = rt::sigact { ... }; + let old = rt::sigact { + // Filled in by rt: + sa_sigaction = null: *fn(_: int, _: *rt::siginfo, _: *void) void, + sa_restorer = null: *fn() void, + ... + }; match (rt::sigaction(signum, &new, &old)) { case int => yield;