aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/rt.zc30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/runtime/rt.zc b/src/runtime/rt.zc
index ee3594d..a54d88c 100644
--- a/src/runtime/rt.zc
+++ b/src/runtime/rt.zc
@@ -760,7 +760,10 @@ word .u new_t(int n, int t) {
if (dbg & 1) note_alloc(p, alloc_line);
return p;
}
-// allocate n words without a type stamp; the caller owns the fresh object.
+// new(n) allocates n zeroed words without a type stamp. new(T) and new(T, n) allocate
+// a fresh heap object of type T (n of them for the second form) and stamp T in its
+// header; the compiler rewrites those forms to new_t or new_k. the caller owns it,
+// and the analyzer frees it when its owner's block ends.
word .u new(int n) { return new_t(n, 0); }
// the compiler works out the size class of a constant-size new at compile
// time (k is the class of n + HDR words), so a repeated allocation of the same
@@ -1380,3 +1383,28 @@ char* .u readfile(char* path) {
syscall(SYS_CLOSE, fd, 0, 0);
return buf;
}
+// reads a file's bytes into an owned block, one byte to a word after a length word:
+// [n, b0, b1, ...]. unlike readfile, a 0 byte in the file is kept. returns null if
+// opening fails.
+word.u readbytes(char* path) {
+ int fd; word buf; int n = 0, got, cap; word nb;
+ fd = syscall(SYS_OPEN, path, 0, 0);
+ if (fd < 0) return 0;
+ cap = 256;
+ buf = new(cap);
+ while (1) {
+ if (n + 130 >= cap) {
+ nb = new(cap + cap);
+ copy_w(nb, buf, n + 1);
+ free(buf);
+ buf = nb;
+ cap = cap + cap;
+ }
+ got = syscall(SYS_READ, fd, buf + 1 + n, 128);
+ if (got <= 0) break;
+ n = n + got;
+ }
+ buf[0] = n;
+ syscall(SYS_CLOSE, fd, 0, 0);
+ return buf;
+}