summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorS. Gilles <sgilles@math.umd.edu>2018-04-18 08:30:41 -0400
committerS. Gilles <sgilles@math.umd.edu>2018-04-18 08:30:41 -0400
commit9aabbe574e648e0a462b211c62da5eb5875343b7 (patch)
tree9ac90949a12806359fd4b996029757c84ef6e2a6
parent4acd9ee51a541f94e81457b1a7fb3accbd790696 (diff)
parent3d71446ecb6569add0d9eaf2e7e4a05d99bd2625 (diff)
downloadmc-9aabbe574e648e0a462b211c62da5eb5875343b7.tar.gz
Merge remote-tracking branch 'ori/master' into HEAD
-rw-r--r--6/main.c6
-rw-r--r--6/simp.c9
-rw-r--r--Makefile2
-rw-r--r--doc/6m.19
-rw-r--r--lib/crypto/bld.sub7
-rw-r--r--lib/crypto/ct.myr2
-rw-r--r--lib/crypto/ctbig.myr460
-rw-r--r--lib/crypto/rsa.myr107
-rw-r--r--lib/crypto/test/ctbig.myr233
-rw-r--r--lib/crypto/test/rsa.myr65
-rw-r--r--lib/regex/interp.myr69
-rw-r--r--lib/regex/redump.myr36
-rw-r--r--lib/std/bigint.myr1
-rw-r--r--lib/std/env+posixy.myr26
-rw-r--r--lib/std/fmt.myr7
-rw-r--r--lib/std/hashfuncs.myr6
-rw-r--r--lib/std/strfind.myr23
-rw-r--r--lib/std/test/fltbits.myr66
-rw-r--r--lib/sys/bld.sub5
-rw-r--r--lib/sys/sys+openbsd-x64.myr1
-rw-r--r--lib/sys/sys+openbsd:6.2-x64.myr1
-rw-r--r--lib/sys/sys+openbsd:6.3-x64.myr1759
-rw-r--r--lib/testr/testr.myr12
-rw-r--r--lib/thread/spawn+openbsd.myr2
-rw-r--r--mbld/bld.sub3
-rw-r--r--mbld/cpufeatures+plan9-x64.s8
-rw-r--r--mbld/cpufeatures+posixy-x64.s (renamed from mbld/cpufeatures+x64.s)4
-rw-r--r--mbld/deps.myr2
-rw-r--r--mbld/test.myr40
-rwxr-xr-xmk/bootstrap/bootstrap+Darwin-x86_64.sh2
-rwxr-xr-xmk/bootstrap/bootstrap+FreeBSD-amd64.sh2
-rwxr-xr-xmk/bootstrap/bootstrap+Linux-x86_64.sh2
-rwxr-xr-xmk/bootstrap/bootstrap+NetBSD-amd64.sh2
-rwxr-xr-xmk/bootstrap/bootstrap+OpenBSD-amd64.sh4
-rwxr-xr-xmk/bootstrap/bootstrap+Plan9-amd64.sh2
-rw-r--r--parse/infer.c60
-rw-r--r--parse/parse.h1
-rw-r--r--parse/stab.c10
-rwxr-xr-xsupport/syscall-gen/gensys.sh2
-rw-r--r--support/syscall-gen/gentypes+openbsd:6.3-x64.frag119
-rw-r--r--support/syscall-gen/specials+openbsd:6.3-x64.frag286
-rw-r--r--support/syscall-gen/types+openbsd:6.2-x64.frag2
-rw-r--r--support/syscall-gen/types+openbsd:6.3-x64.frag479
-rw-r--r--test/data/strfind-expected2
44 files changed, 3724 insertions, 222 deletions
diff --git a/6/main.c b/6/main.c
index a153b8b..b770222 100644
--- a/6/main.c
+++ b/6/main.c
@@ -41,6 +41,7 @@ usage(char *prog)
printf("\t-o\tOutput to outfile\n");
printf("\t-O dir\tOutput to dir\n");
printf("\t-S\tGenerate assembly source alongside object code\n");
+ printf("\t-T\tCompile in test mode\n");
printf("\t-c\tEnable additional (possibly flaky) checking\n");
printf("\t-I path\tAdd 'path' to use search path\n");
printf("\t-d\tPrint debug dumps. Recognized options: f r p i\n");
@@ -200,7 +201,7 @@ main(int argc, char **argv)
outfile = NULL;
- optinit(&ctx, "cd:?hSo:I:9G:O:", argv, argc);
+ optinit(&ctx, "cd:?hSo:I:9G:O:T", argv, argc);
asmsyntax = Defaultasm;
sizefn = size;
while (!optdone(&ctx)) {
@@ -240,6 +241,9 @@ main(int argc, char **argv)
case 'I':
lappend(&incpaths, &nincpaths, ctx.optarg);
break;
+ case 'T':
+ allowhidden++;
+ break;
default:
usage(argv[0]);
exit(0);
diff --git a/6/simp.c b/6/simp.c
index d2a9d18..803c5d3 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -1006,6 +1006,15 @@ capture(Simp *s, Node *n, Node *dst)
envsz->expr.type = tyintptr;
assignat(s, e, 0, envsz);
assignat(s, fp, 0, e);
+ } else {
+ /*
+ * We need to zero out the environment, so that
+ * duplicating the function doesn't think we have
+ * a bogus environment.
+ */
+ e = mkintlit(n->loc, 0);
+ e->expr.type = tyintptr;
+ assignat(s, fp, 0, e);
}
assignat(s, fp, Ptrsz, f);
return dst;
diff --git a/Makefile b/Makefile
index e75dc71..af70c21 100644
--- a/Makefile
+++ b/Makefile
@@ -41,4 +41,4 @@ uninstallmyr:
./mbldwrap.sh uninstall
release:
- ./support/release.sh 0.2.0
+ ./support/release.sh $(VERSION)
diff --git a/doc/6m.1 b/doc/6m.1
index f04090c..5605d84 100644
--- a/doc/6m.1
+++ b/doc/6m.1
@@ -65,6 +65,15 @@ Generate assembly code along with the object file.
Generate assembly in the Gnu As syntax.
.TP
+.B -O out
+Output code to output path 'out'
+
+.TP
+.B -T
+Compile in test mode. This implies that pkglocal functions are
+available.
+
+.TP
.B -9
Generate assembly in the Plan 9 syntax.
diff --git a/lib/crypto/bld.sub b/lib/crypto/bld.sub
index 1c58997..f6954fd 100644
--- a/lib/crypto/bld.sub
+++ b/lib/crypto/bld.sub
@@ -12,21 +12,26 @@ lib crypto =
# hmac
hmac.myr
- # ciphers
+ # symmetric ciphers
chacha20.myr
aes.myr
+ # public key ciphers
+ rsa.myr
+
# randomness
entropy.myr # currently assumes a /dev/random
rand.myr
# utilities for subtle bits
ct.myr
+ ctbig.myr
clear.myr
lib ../std:std
lib ../sys:sys
lib ../thread:thread
+ lib ../iter:iter
;;
diff --git a/lib/crypto/ct.myr b/lib/crypto/ct.myr
index 28be694..d6fe34d 100644
--- a/lib/crypto/ct.myr
+++ b/lib/crypto/ct.myr
@@ -53,7 +53,7 @@ generic le = {a, b
generic ne = {a, b
const nshift = 8*sizeof(@t) - 1
var q = a ^ b
- -> ((q | -q) >> nshift)^1
+ -> (q | -q) >> nshift
}
generic mux = {c, a, b
diff --git a/lib/crypto/ctbig.myr b/lib/crypto/ctbig.myr
index 59ff5f7..89d0caa 100644
--- a/lib/crypto/ctbig.myr
+++ b/lib/crypto/ctbig.myr
@@ -1,4 +1,5 @@
use std
+use iter
use "ct"
@@ -9,32 +10,64 @@ pkg crypto =
;;
generic mkctbign : (v : @a, nbit : std.size -> ctbig#) :: numeric,integral @a
+ const ctzero : (nbit : std.size -> ctbig#)
+ const ctbytesle : (v : ctbig# -> byte[:])
+ const ctbytesbe : (v : ctbig# -> byte[:])
const mkctbigle : (v : byte[:], nbit : std.size -> ctbig#)
- //const mkctbigbe : (v : byte[:], nbit : std.size -> ctbig#)
+ const mkctbigbe : (v : byte[:], nbit : std.size -> ctbig#)
const ctfree : (v : ctbig# -> void)
const ctbigdup : (v : ctbig# -> ctbig#)
- const ctlike : (v : ctbig# -> ctbig#)
- const ct2big : (v : ctbig# -> std.bigint#)
- const big2ct : (v : std.bigint#, ndig : std.size -> ctbig#)
-
- const ctadd : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
- const ctsub : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
- const ctmul : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
- //const ctdivmod : (r : ctbig#, m : ctbig#, a : ctbig#, b : ctbig# -> void)
- //const ctmodpow : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
-
- const ctiszero : (v : ctbig# -> bool)
- const cteq : (a : ctbig#, b : ctbig# -> bool)
- const ctne : (a : ctbig#, b : ctbig# -> bool)
- const ctgt : (a : ctbig#, b : ctbig# -> bool)
- const ctge : (a : ctbig#, b : ctbig# -> bool)
- const ctlt : (a : ctbig#, b : ctbig# -> bool)
- const ctle : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ct2big : (v : ctbig# -> std.bigint#)
+ pkglocal const big2ct : (v : std.bigint#, nbit : std.size -> ctbig#)
+
+ /* arithmetic */
+ pkglocal const ctadd : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
+ pkglocal const ctsub : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
+ pkglocal const ctmul : (r : ctbig#, a : ctbig#, b : ctbig# -> void)
+ pkglocal const ctmodpow : (r : ctbig#, a : ctbig#, b : ctbig#, m : ctbig# -> void)
+
+ pkglocal const ctiszero : (v : ctbig# -> bool)
+ pkglocal const cteq : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ctne : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ctgt : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ctge : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ctlt : (a : ctbig#, b : ctbig# -> bool)
+ pkglocal const ctle : (a : ctbig#, b : ctbig# -> bool)
+
+ /* for testing */
+ pkglocal const growmod : (r : ctbig#, a : ctbig#, k : uint32, m : ctbig# -> void)
+ pkglocal const clip : (v : ctbig# -> ctbig#)
+
+ impl std.equatable ctbig#
;;
+const Bits = 32
const Base = 0x100000000ul
+impl std.equatable ctbig# =
+ eq = {a, b
+ -> cteq(a, b)
+ }
+;;
+
+const __init__ = {
+ var ct : ctbig#
+
+ ct = ctzero(0)
+ std.fmtinstall(std.typeof(ct), ctfmt)
+ ctfree(ct)
+}
+
+const ctfmt = {sb, ap, opts
+ var ct : ctbig#
+
+ ct = std.vanext(ap)
+ for d : iter.byreverse(ct.dig)
+ std.sbfmt(sb, "{w=8,p=0,x}.", d)
+ ;;
+}
+
generic mkctbign = {v : @a, nbit : std.size :: integral,numeric @a
var a
var val
@@ -50,7 +83,21 @@ generic mkctbign = {v : @a, nbit : std.size :: integral,numeric @a
if nbit > 32
a.dig[1] = (val >> 32 : uint32)
;;
- -> a
+ -> clip(a)
+}
+
+const ctzero = {nbit
+ -> std.mk([
+ .nbit=nbit,
+ .dig=std.slzalloc(ndig(nbit)),
+ ])
+}
+
+const ctdup = {v
+ -> std.mk([
+ .nbit=v.nbit,
+ .dig=std.sldup(v.dig)
+ ])
}
const ct2big = {ct
@@ -60,17 +107,17 @@ const ct2big = {ct
])
}
-const big2ct = {ct, nbit
+const big2ct = {big, nbit
var v, n, l
n = ndig(nbit)
- l = std.min(n, ct.dig.len)
+ l = std.min(n, big.dig.len)
v = std.slzalloc(n)
- std.slcp(v, ct.dig[:l])
- -> std.mk([
+ std.slcp(v[:l], big.dig[:l])
+ -> clip(std.mk([
.nbit=nbit,
.dig=v,
- ])
+ ]))
}
const mkctbigle = {v, nbit
@@ -84,26 +131,89 @@ const mkctbigle = {v, nbit
a = std.slzalloc(ndig(nbit))
for i = 0; i + 4 <= v.len; i += 4
a[o++] = \
- (v[i + 0] << 0 : uint32) | \
- (v[i + 1] << 8 : uint32) | \
- (v[i + 2] << 16 : uint32) | \
- (v[i + 3] << 24 : uint32)
+ ((v[i + 0] : uint32) << 0) | \
+ ((v[i + 1] : uint32) << 8) | \
+ ((v[i + 2] : uint32) << 16) | \
+ ((v[i + 3] : uint32) << 24)
;;
- last = 0
- for i; i < v.len; i++
- off = i & 0x3
- last |= (v[off] : uint32) << (8 *off)
+ if i != v.len
+ last = 0
+ for i; i < v.len; i++
+ off = i & 0x3
+ last |= (v[i] : uint32) << (8 *off)
+ ;;
+ a[o++] = last
;;
- a[o++] = last
- -> std.mk([.nbit=nbit, .dig=a])
+ -> clip(std.mk([.nbit=nbit, .dig=a]))
}
-const ctlike = {v
- -> std.mk([
- .nbit = v.nbit,
- .dig=std.slzalloc(v.dig.len),
- ])
+const mkctbigbe = {v, nbit
+ var a, i, o, tail : byte[4]
+
+ /*
+ It's ok to depend on the length of v here: we can leak the
+ size of the numbers.
+ */
+ o = 0
+ a = std.slzalloc(ndig(nbit))
+ for i = v.len ; i >= 4; i -= 4
+ a[o++] = std.getbe32(v[i-4:i])
+ ;;
+
+ if i != 0
+ std.slfill(tail[:], 0)
+ std.slcp(tail[4-i:], v[:i])
+ a[o++] = std.getbe32(tail[:])
+ ;;
+ -> clip(std.mk([.nbit=nbit, .dig=a]))
+}
+
+const ctbytesle = {v
+ var d, i, n, o, ret
+
+ o = 0
+ n = (v.nbit + 7) / 8
+ ret = std.slalloc(n)
+ for i = 0; i * 4 < n; i++
+ d = v.dig[i]
+ ret[o++] = (d >> 0 : byte)
+ ret[o++] = (d >> 8 : byte)
+ ret[o++] = (d >> 16 : byte)
+ ret[o++] = (d >> 24 : byte)
+ ;;
+
+ if i * 4 != n
+ d = v.dig[i]
+ for ; i < n; i++
+ ret[o++] = (d : byte)
+ d >>= 8
+ ;;
+ ;;
+ -> ret
+}
+
+const ctbytesbe = {v : ctbig#
+ var d : uint32, i, n, o, ret
+
+ i = v.dig.len - 1
+ o = 0
+ n = (v.nbit + 7) / 8
+ ret = std.slalloc(n)
+ if n & 0x3 != 0
+ d = v.dig[i--]
+ for var j = n & 0x3 + 1; j > 0; j--
+ ret[o++] = (d >> 8*(j - 1 : uint32): byte)
+ ;;
+ ;;
+ for ; i >= 0 ; i--
+ d = v.dig[i]
+ ret[o++] = (d >> 24 : byte)
+ ret[o++] = (d >> 16 : byte)
+ ret[o++] = (d >> 8 : byte)
+ ret[o++] = (d >> 0 : byte)
+ ;;
+ -> ret
}
const ctbigdup = {v
@@ -119,21 +229,29 @@ const ctfree = {v
}
const ctadd = {r, a, b
- var v, i, carry, n
+ ctaddcc(r, a, b, 1)
+}
+
+const ctaddcc = {r, a, b, ctl
+ var v, i, carry
checksz(a, b)
checksz(a, r)
carry = 0
- n = max(a.dig.len, b.dig.len)
- for i = 0; i < n; i++
+ for i = 0; i < a.dig.len; i++
v = (a.dig[i] : uint64) + (b.dig[i] : uint64) + carry;
- r.dig[i] = (v : uint32)
- carry >>= 32
+ r.dig[i] = mux(ctl, (v : uint32), r.dig[i])
+ carry = v >> 32
;;
+ clip(r)
}
const ctsub = {r, a, b
+ ctsubcc(r, a, b, 1)
+}
+
+const ctsubcc = {r, a, b, ctl
var borrow, v, i
checksz(a, b)
@@ -143,9 +261,10 @@ const ctsub = {r, a, b
for i = 0; i < a.dig.len; i++
v = (a.dig[i] : uint64) - (b.dig[i] : uint64) - borrow
borrow = (v & (1<<63)) >> 63
- v = mux(borrow, v + Base, v)
- r.dig[i] = (v : uint32)
+ r.dig[i] = mux(ctl, (v : uint32), r.dig[i])
;;
+ clip(r)
+ -> borrow
}
const ctmul = {r, a, b
@@ -176,17 +295,201 @@ const ctmul = {r, a, b
std.slfree(a.dig)
;;
r.dig = w[:a.dig.len]
+ clip(r)
+}
+
+/*
+ * Returns the top digit in the number that has
+ * a bit set. This is useful for finding our division.
+ */
+ const topfull = {n : ctbig#
+ var top
+
+ top = 0
+ for var i = 0; i < n.dig.len; i++
+ top = mux(n.dig[i], i, top)
+ ;;
+ -> 0
+}
+
+const unalignedword = {v, bit
+ var lo, hi, s, i
+
+ s = (bit & 0x1f : uint32)
+ i = (bit >> 5 : uint32)
+ lo = v.dig[i]
+ if s == 0
+ hi = 0
+ else
+ hi = v.dig[i + 1]
+ ;;
+ -> (lo >> s) | (hi << (32 - s))
}
-//const ctmodpow = {res, a, b
-// /* find rinv, mprime */
-//
-// /* convert to monty space */
-//
-// /* do the modpow */
-//
-// /* and come back */
-//}
+/*
+ * Multiplies by 2**32 mod m
+ */
+const growmod = {r, a, k, m
+ var a0, a1, b0, hi, g, q, tb, e
+ var chf, clow, under, over
+ var cc : uint64
+
+ checksz(a, m)
+ std.assert(a.dig.len > 1, "bad modulus\n")
+ std.assert(m.dig[m.dig.len - 1] & (1 << 31) != 0, "top of mod not set: m={}, nbit={}\n", m, m.nbit)
+ std.assert(m.nbit % 32 == 0, "ragged sizes not yet supported: a.nbit=={}\n", a.nbit)
+
+ a0 = (unalignedword(a, a.nbit - 32) : uint64) << 32
+ a1 = (unalignedword(a, a.nbit - 64) : uint64) << 0
+ b0 = (unalignedword(m, m.nbit - 32) : uint64)
+
+ /*
+ * We hold the top digit here, so
+ * this keeps the number of digits the same, and
+ * as a result, keeps checksz() happy.
+ */
+ hi = a.dig[a.dig.len - 1]
+
+ /* Do the multiplication of x by 2**32 */
+ std.slcp(r.dig[1:], a.dig[:a.dig.len-1])
+ r.dig[0] = k
+ g = ((a0 + a1) / b0 : uint32)
+ e = eq(a0, b0)
+ q = mux((e : uint32), 0xffffffff, mux(eq(g, 0), 0, g - 1));
+
+ cc = 0;
+ tb = 1;
+ for var u = 0; u < r.dig.len; u++
+ var mw, zw, xw, nxw
+ var zl : uint64
+
+ mw = m.dig[u];
+ zl = (mw : uint64) * (q : uint64) + cc
+ cc = zl >> 32
+ zw = (zl : uint32)
+ xw = r.dig[u]
+ nxw = xw - zw;
+ cc += (gt(nxw, xw) : uint64)
+ r.dig[u] = nxw;
+ tb = mux(eq(nxw, mw), tb, gt(nxw, mw));
+ ;;
+
+ /*
+ * We can either underestimate or overestimate q,
+ * - If we overestimated, either cc < hi, or cc == hi && tb != 0.
+ * - If we overestimated, cc > hi.
+ * - Otherwise, we got it exactly right.
+ *
+ * If we overestimated, we need to subtract 'm' once. If we
+ * underestimated, we need to add it once.
+ */
+ chf = (cc >> 32 : uint32)
+ clow = (cc >> 0 : uint32)
+ over = chf | gt(clow, hi);
+ under = ~over & (tb | (~chf & lt(clow, hi)));
+ ctaddcc(r, r, m, over);
+ ctsubcc(r, r, m, under);
+ clip(r)
+
+}
+
+const tomonty = {r, x, m
+ checksz(x, r)
+ checksz(x, m)
+
+ std.slcp(r.dig, x.dig)
+ for var i = 0; i < m.dig.len; i++
+ growmod(r, r, 0, m)
+ ;;
+}
+
+const ccopy = {r, v, ctl
+ checksz(r, v)
+ for var i = 0; i < r.dig.len; i++
+ r.dig[i] = mux(ctl, v.dig[i], r.dig[i])
+ ;;
+}
+
+const muladd = {a, b, k
+ -> (a : uint64) * (b : uint64) + (k : uint64)
+}
+
+const montymul = {r : ctbig#, x : ctbig#, y : ctbig#, m : ctbig#, m0i : uint32
+ var dh : uint64
+ var s
+
+ checksz(x, y)
+ checksz(x, m)
+ checksz(x, r)
+
+ std.slfill(r.dig, 0)
+ dh = 0
+ for var u = 0; u < x.dig.len; u++
+ var f : uint32, xu : uint32
+ var r1 : uint64, r2 : uint64, zh : uint64
+
+ xu = x.dig[u]
+ f = (r.dig[0] + x.dig[u] * y.dig[0]) * m0i;
+ r1 = 0;
+ r2 = 0;
+ for var v = 0; v < y.dig.len; v++
+ var z : uint64
+ var t : uint32
+
+ z = muladd(xu, y.dig[v], r.dig[v]) + r1
+ r1 = z >> 32
+ t = (z : uint32)
+ z = muladd(f, m.dig[v], t) + r2
+ r2 = z >> 32
+ if v != 0
+ r.dig[v - 1] = (z : uint32)
+ ;;
+ ;;
+ zh = dh + r1 + r2;
+ r.dig[r.dig.len - 1] = (zh : uint32)
+ dh = zh >> 32;
+ ;;
+
+ /*
+ * r may still be greater than m at that point; notably, the
+ * 'dh' word may be non-zero.
+ */
+ s = ne(dh, 0) | (ctge(r, m) : uint64)
+ ctsubcc(r, r, m, (s : uint32))
+}
+
+const ninv32 = {x
+ var y
+
+ y = 2 - x
+ y *= 2 - y * x
+ y *= 2 - y * x
+ y *= 2 - y * x
+ y *= 2 - y * x
+ -> mux(x & 1, -y, 0)
+}
+
+const ctmodpow = {r, a, e, m
+ var t1, t2, m0i, ctl
+ var n = 0
+
+ t1 = ctdup(a)
+ t2 = ctzero(a.nbit)
+ m0i = ninv32(m.dig[0])
+
+ tomonty(t1, a, m);
+ std.slfill(r.dig, 0);
+ r.dig[0] = 1;
+ for var i = 0; i < e.nbit; i++
+ ctl = (e.dig[i>>5] >> (i & 0x1f : uint32)) & 1
+ montymul(t2, r, t1, m, m0i)
+ ccopy(r, t2, ctl);
+ montymul(t2, t1, t1, m, m0i);
+ std.slcp(t1.dig, t2.dig);
+ ;;
+ ctfree(t1)
+ ctfree(t2)
+}
const ctiszero = {a
var z, zz
@@ -200,17 +503,14 @@ const ctiszero = {a
}
const cteq = {a, b
- var z, d, e
+ var nz
checksz(a, b)
-
- e = 1
+ nz = 0
for var i = 0; i < a.dig.len; i++
- z = a.dig[i] - b.dig[i]
- d = mux(z, 1, 0)
- e = mux(e, d, 0)
+ nz = nz | a.dig[i] - b.dig[i]
;;
- -> (e : bool)
+ -> (eq(nz, 0) : bool)
}
const ctne = {a, b
@@ -221,17 +521,7 @@ const ctne = {a, b
}
const ctgt = {a, b
- var e, d, g
-
- checksz(a, b)
-
- g = 0
- for var i = 0; i < a.dig.len; i++
- e = not(a.dig[i] - b.dig[i])
- d = gt(a.dig[i], b.dig[i])
- g = mux(e, g, d)
- ;;
- -> (g : bool)
+ -> (ctsubcc(b, b, a, 0) : bool)
}
const ctge = {a, b
@@ -242,17 +532,7 @@ const ctge = {a, b
}
const ctlt = {a, b
- var e, d, l
-
- checksz(a, b)
-
- l = 0
- for var i = 0; i < a.dig.len; i++
- e = not(a.dig[i] - b.dig[i])
- d = gt(a.dig[i], b.dig[i])
- l = mux(e, l, d)
- ;;
- -> (l : bool)
+ -> (ctsubcc(a, a, b, 0) : bool)
}
const ctle = {a, b
@@ -263,10 +543,20 @@ const ctle = {a, b
}
const ndig = {nbit
- -> (nbit + 8*sizeof(uint32) - 1)/sizeof(uint32)
+ -> (nbit + 8*sizeof(uint32) - 1)/(8*sizeof(uint32))
}
const checksz = {a, b
std.assert(a.nbit == b.nbit, "mismatched bit sizes")
std.assert(a.dig.len == b.dig.len, "mismatched backing sizes")
}
+
+const clip = {v
+ var mask, edge : uint64
+
+ edge = (v.nbit : uint64) & (Bits - 1)
+ mask = mux(edge, (1 << edge) - 1, ~0)
+ v.dig[v.dig.len - 1] &= (mask : uint32)
+ -> v
+}
+
diff --git a/lib/crypto/rsa.myr b/lib/crypto/rsa.myr
new file mode 100644
index 0000000..c05ced1
--- /dev/null
+++ b/lib/crypto/rsa.myr
@@ -0,0 +1,107 @@
+use std
+
+use "ct"
+use "ctbig"
+use "rand"
+
+pkg crypto =
+ const rsapub_pkcs15 : (msg : byte[:], exp : byte[:], mod : byte[:] -> byte[:])
+
+ /*
+ * For unit testing, we need constant output. That means
+ * to use a constant, deterministic padding. As a result,
+ * if we pass a non-zero seed size here, we use that seed.
+ */
+ pkglocal const rsapubseed_pkcs15 : (\
+ msg : byte[:],
+ exp : byte[:],
+ mod : byte[:],
+ seed : byte[:] -> byte[:])
+;;
+
+const rsapub_pkcs15 = {msgbuf, expbuf, modbuf
+ -> rsapubseed_pkcs15(msgbuf, expbuf, modbuf, "")
+}
+
+const rsapubseed_pkcs15 = {msgbuf, expbuf, modbuf, padbuf
+ var ret, res, msg, exp, mod, nbit
+
+ nbit = bitcount(modbuf)
+ res = ctzero(nbit)
+ msg = decodepad(msgbuf, nbit, padbuf)
+ exp = decode(expbuf, nbit)
+ mod = decode(modbuf, nbit)
+
+ ctmodpow(res, msg, exp, mod)
+ ret = ctbytesbe(res)
+
+ ctfree(res)
+ ctfree(msg)
+ ctfree(exp)
+ ctfree(mod)
+ -> ret
+}
+
+const decodepad = {msg, len, padbuf
+ var mpad, m
+
+ mpad = pad(msg, (len + 7) / 8, padbuf)
+ m = mkctbigbe(mpad, len)
+ std.slfree(mpad)
+ -> m
+}
+
+const decode = {msg, len
+ -> mkctbigbe(msg, len)
+}
+
+const pad = {msg, nbytes, padbuf
+ var buf, pslen
+
+ std.assert(msg.len < nbytes - 11, "overlong message")
+ buf = std.slalloc(nbytes)
+
+ buf[0] = 0
+ buf[1] = 2
+ pslen = nbytes - msg.len - 3
+ if padbuf.len > 0
+ std.slcp(buf[2:pslen+2], padbuf)
+ else
+ randbytes(buf[2:pslen+2])
+ for var i = 0; i < pslen; i++
+ while buf[i + 2] == 0
+ randbytes(buf[i+2:i+3])
+ ;;
+ ;;
+ ;;
+ buf[pslen + 2] = 0
+ std.slcp(buf[pslen+3:], msg)
+
+ -> buf
+}
+
+/*
+ * Count the number of bits in a pkcs15 modulus. This assumes
+ * that we're representing the number in a big endian format.
+ */
+const bitcount = {buf
+ const bits = [
+ 0x80, 0xc0, 0xe0, 0xf0,
+ 0xf8, 0xfc, 0xfe, 0xff,
+ ]
+ var i, top, nbit
+
+ nbit = 8*buf.len
+ for i = 0; buf[i] == 0 && i < buf.len; i++
+ nbit -= 0
+ i++
+ ;;
+ top = buf[i]
+ for b : bits[:]
+ if top & b != 0
+ break
+ ;;
+ nbit--
+ ;;
+ -> nbit
+}
diff --git a/lib/crypto/test/ctbig.myr b/lib/crypto/test/ctbig.myr
new file mode 100644
index 0000000..44c031a
--- /dev/null
+++ b/lib/crypto/test/ctbig.myr
@@ -0,0 +1,233 @@
+use std
+use crypto
+use testr
+
+const Nbit = 128
+const Nfunky = 79
+
+const main = {
+ testr.run([
+ [.name="clip", .fn={ctx
+ var v = [
+ .nbit=32,
+ .dig=[0xffffffff][:]
+ ]
+ crypto.clip(&v)
+ testr.eq(ctx, v.dig[0], 0xffffffff)
+ v = [
+ .nbit=31,
+ .dig=[0xffffffff][:]
+ ]
+ crypto.clip(&v)
+ testr.eq(ctx, v.dig[0], 0x7fffffff)
+ }],
+ [.name="mkbig-le", .fn={ctx
+ docvt(ctx, crypto.mkctbigle, Nbit,
+ "6618611909121",
+ "\x01\x02\x03\x04\x05\x06")
+ }],
+ [.name="mkbig-be", .fn={ctx
+ docvt(ctx, crypto.mkctbigbe, Nbit,
+ "1108152157446",
+ "\x00\x01\x02\x03\x04\x05\x06")
+ }],
+ /* normal */
+ [.name="add", .fn={ctx
+ do2(ctx, crypto.ctadd, Nbit,
+ "5192296858610368357189246603769160",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="sub", .fn={ctx
+ do2(ctx, crypto.ctsub, Nbit,
+ "5192296858459252629770411284885280",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="mul", .fn={ctx
+ do2(ctx, crypto.ctmul, Nbit,
+ "392318858376010676506814412592879878824393346033951606800",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="growmod", .fn={ctx
+ do2(ctx, growmod0, Nbit,
+ "259016584597313952181375284077740334036",
+ "137304361882109849168381018424069802644",
+ "279268927326277818181333274586733399084")
+ }],
+ /* comparisons */
+ [.name="lt-less", .fn={ctx
+ dobool(ctx, crypto.ctlt, Nbit,
+ true,
+ "137304361882109849168381018424069802644",
+ "279268927326277818181333274586733399084")
+ }],
+ [.name="lt-equal", .fn={ctx
+ dobool(ctx, crypto.ctlt, Nbit,
+ false,
+ "137304361882109849168381018424069802644",
+ "137304361882109849168381018424069802644")
+ }],
+ [.name="lt-greater", .fn={ctx
+ dobool(ctx, crypto.ctlt, Nbit,
+ false,
+ "279268927326277818181333274586733399084",
+ "137304361882109849168381018424069802644")
+ }],
+ [.name="gt-less", .fn={ctx
+ dobool(ctx, crypto.ctgt, Nbit,
+ false,
+ "137304361882109849168381018424069802644",
+ "279268927326277818181333274586733399084")
+ }],
+ [.name="gt-equal", .fn={ctx
+ dobool(ctx, crypto.ctgt, Nbit,
+ false,
+ "137304361882109849168381018424069802644",
+ "137304361882109849168381018424069802644")
+ }],
+ [.name="gt-greater", .fn={ctx
+ dobool(ctx, crypto.ctgt, Nbit,
+ true,
+ "279268927326277818181333274586733399084",
+ "137304361882109849168381018424069802644")
+ }],
+ [.name="growmodsmall", .fn={ctx
+ do2(ctx, growmod0, Nbit,
+ "30064771072",
+ "7",
+ "279268927326277818181333274586733399084")
+ }],
+ [.name="addfunky", .fn={ctx
+ do2(ctx, crypto.ctadd, Nfunky,
+ "75540728658750274549064",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="subfunky", .fn={ctx
+ do2(ctx, crypto.ctsub, Nfunky,
+ "528887911047229543018272",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="mulfunky", .fn={ctx
+ do2(ctx, crypto.ctmul, Nfunky,
+ "434472066238453871708176",
+ "5192296858534810493479828944327220",
+ "75557863709417659441940")
+ }],
+ [.name="modpow-nop", .fn={ctx
+ do3(ctx, crypto.ctmodpow, Nbit,
+ "1231231254019581241243091223098123",
+ "1231231254019581241243091223098123",
+ "1",
+ "238513807008428752753137056878245001837")
+ }],
+ [.name="modpow-small", .fn={ctx
+ do3(ctx, crypto.ctmodpow, Nbit,
+ "190803258902817973474500147337505443108",
+ "1231231254019581241243091223098123",
+ "7",
+ "238513807008428752753137056878245001837")
+ }],
+ [.name="modpow", .fn={ctx
+ do3(ctx, crypto.ctmodpow, Nbit,
+ "134487661739548107356399382114451163287",
+ "1231231254019581241243091223098123",
+ "312312091230",
+ "238513807008428752753137056878245001837")
+ }],
+ ][:])
+}
+
+const growmod0 = {r, a, b
+ crypto.growmod(r, a, 0, b)
+}
+
+const dobool = {ctx, op, nbit, e, astr, bstr
+ var r, a, ai, b, bi
+
+ r = crypto.ctzero(nbit)
+ ai = std.get(std.bigparse(astr))
+ bi = std.get(std.bigparse(bstr))
+ a = crypto.big2ct(ai, nbit)
+ b = crypto.big2ct(bi, nbit)
+
+ std.bigfree(ai)
+ std.bigfree(bi)
+ testr.eq(ctx, op(a, b), e)
+
+ crypto.ctfree(a)
+ crypto.ctfree(b)
+}
+
+const docvt = {ctx, op, nbit, estr, buf
+ var v, e, ei
+
+ ei = std.get(std.bigparse(estr))
+ e = crypto.big2ct(ei, nbit)
+ std.bigfree(ei)
+
+ v = op(buf, nbit)
+ testr.eq(ctx, v, e)
+
+ crypto.ctfree(e)
+ crypto.ctfree(v)
+}
+
+const do2 = {ctx, op, nbit, estr, astr, bstr
+ var r, a, ai, b, bi, e, ei
+
+ r = crypto.ctzero(nbit)
+ ei = std.get(std.bigparse(estr))
+ ai = std.get(std.bigparse(astr))
+ bi = std.get(std.bigparse(bstr))
+ e = crypto.big2ct(ei, nbit)
+ a = crypto.big2ct(ai, nbit)
+ b = crypto.big2ct(bi, nbit)
+
+ std.bigfree(ei)
+ std.bigfree(ai)
+ std.bigfree(bi)
+
+ op(r, a, b)
+
+ testr.eq(ctx, r, e)
+
+ crypto.ctfree(r)
+ crypto.ctfree(e)
+ crypto.ctfree(a)
+ crypto.ctfree(b)
+}
+
+
+const do3 = {ctx, op, nbit, estr, astr, bstr, cstr
+ var r, a, ai, b, bi, c, ci, e, ei
+
+ r = crypto.ctzero(nbit)
+ ei = std.get(std.bigparse(estr))
+ ai = std.get(std.bigparse(astr))
+ bi = std.get(std.bigparse(bstr))
+ ci = std.get(std.bigparse(cstr))
+ e = crypto.big2ct(ei, nbit)
+ a = crypto.big2ct(ai, nbit)
+ b = crypto.big2ct(bi, nbit)
+ c = crypto.big2ct(ci, nbit)
+
+ std.bigfree(ei)
+ std.bigfree(ai)
+ std.bigfree(bi)
+
+ op(r, a, b, c)
+
+ testr.eq(ctx, r, e)
+
+ crypto.ctfree(r)
+ crypto.ctfree(e)
+ crypto.ctfree(a)
+ crypto.ctfree(b)
+ crypto.ctfree(c)
+}
+
+
diff --git a/lib/crypto/test/rsa.myr b/lib/crypto/test/rsa.myr
new file mode 100644
index 0000000..c03d9b2
--- /dev/null
+++ b/lib/crypto/test/rsa.myr
@@ -0,0 +1,65 @@
+use std
+use crypto
+use iter
+use testr
+
+type pubcase = struct
+ name : byte[:]
+ nbit : std.size
+ msg : byte[:]
+ exp : byte[:]
+ mod : byte[:]
+ seed : byte[:]
+ ctext : byte[:]
+;;
+
+const main = {
+ for case : iter.byref(pubcases)
+ testr.run([
+ [.name=case.name, .fn={ctx
+ var ct
+ ct = crypto.rsapubseed_pkcs15(case.msg, case.exp, case.mod, case.seed)
+ testr.eq(ctx, ct, case.ctext)
+ }],
+ ][:])
+ ;;
+}
+
+const pubcases : pubcase[:] = [
+ [
+ .name="basic",
+ .nbit=1024,
+ .mod=\
+ "\xa8\xb3\xb2\x84\xaf\x8e\xb5\x0b\x38\x70\x34\xa8\x60\xf1\x46\xc4" \
+ "\x91\x9f\x31\x87\x63\xcd\x6c\x55\x98\xc8\xae\x48\x11\xa1\xe0\xab" \
+ "\xc4\xc7\xe0\xb0\x82\xd6\x93\xa5\xe7\xfc\xed\x67\x5c\xf4\x66\x85" \
+ "\x12\x77\x2c\x0c\xbc\x64\xa7\x42\xc6\xc6\x30\xf5\x33\xc8\xcc\x72" \
+ "\xf6\x2a\xe8\x33\xc4\x0b\xf2\x58\x42\xe9\x84\xbb\x78\xbd\xbf\x97" \
+ "\xc0\x10\x7d\x55\xbd\xb6\x62\xf5\xc4\xe0\xfa\xb9\x84\x5c\xb5\x14" \
+ "\x8e\xf7\x39\x2d\xd3\xaa\xff\x93\xae\x1e\x6b\x66\x7b\xb3\xd4\x24" \
+ "\x76\x16\xd4\xf5\xba\x10\xd4\xcf\xd2\x26\xde\x88\xd3\x9f\x16\xfb",
+ .exp="\x01\x00\x01",
+ .msg=\
+ "\x66\x28\x19\x4e\x12\x07\x3d\xb0\x3b\xa9\x4c\xda\x9e\xf9\x53\x23" \
+ "\x97\xd5\x0d\xba\x79\xb9\x87\x00\x4a\xfe\xfe\x34",
+ .seed=\
+ "\x01\x73\x41\xae\x38\x75\xd5\xf8\x71\x01\xf8\xcc\x4f\xa9\xb9\xbc" \
+ "\x15\x6b\xb0\x46\x28\xfc\xcd\xb2\xf4\xf1\x1e\x90\x5b\xd3\xa1\x55" \
+ "\xd3\x76\xf5\x93\xbd\x73\x04\x21\x08\x74\xeb\xa0\x8a\x5e\x22\xbc" \
+ "\xcc\xb4\xc9\xd3\x88\x2a\x93\xa5\x4d\xb0\x22\xf5\x03\xd1\x63\x38" \
+ "\xb6\xb7\xce\x16\xdc\x7f\x4b\xbf\x9a\x96\xb5\x97\x72\xd6\x60\x6e" \
+ "\x97\x47\xc7\x64\x9b\xf9\xe0\x83\xdb\x98\x18\x84\xa9\x54\xab\x3c" \
+ "\x6f",
+
+ .ctext=\
+ "\x50\xb4\xc1\x41\x36\xbd\x19\x8c\x2f\x3c\x3e\xd2\x43\xfc\xe0\x36" \
+ "\xe1\x68\xd5\x65\x17\x98\x4a\x26\x3c\xd6\x64\x92\xb8\x08\x04\xf1" \
+ "\x69\xd2\x10\xf2\xb9\xbd\xfb\x48\xb1\x2f\x9e\xa0\x50\x09\xc7\x7d" \
+ "\xa2\x57\xcc\x60\x0c\xce\xfe\x3a\x62\x83\x78\x9d\x8e\xa0\xe6\x07" \
+ "\xac\x58\xe2\x69\x0e\xc4\xeb\xc1\x01\x46\xe8\xcb\xaa\x5e\xd4\xd5" \
+ "\xcc\xe6\xfe\x7b\x0f\xf9\xef\xc1\xea\xbb\x56\x4d\xbf\x49\x82\x85" \
+ "\xf4\x49\xee\x61\xdd\x7b\x42\xee\x5b\x58\x92\xcb\x90\x60\x1f\x30" \
+ "\xcd\xa0\x7b\xf2\x64\x89\x31\x0b\xcd\x23\xb5\x28\xce\xab\x3c\x31",
+ ]
+][:]
+
diff --git a/lib/regex/interp.myr b/lib/regex/interp.myr
index 15e2230..6db8495 100644
--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -173,7 +173,13 @@ const getidxmatches = {re, thr
-> `std.Some ret
}
-/* returns a matching thread, or Zthr if no threads matched */
+/*
+ * Run manages the virtual machine state, and schedules the
+ * regex threads. Each linear match runs in its own thread.
+ * When a new thread is created, it is carefully scheduled
+ * after the current thread, to ensure that match order is
+ * preserved.
+ */
const run = {re, str, idx, wholestr
var bestmatch
var consumed
@@ -189,7 +195,13 @@ const run = {re, str, idx, wholestr
states = std.mkbs()
re.runq = mkthread(re, 0)
if re.debug
- /* The last run could have left things here, since we need this info after the run */
+ /*
+ If we're in debug mode, then we keep
+ the traces around, so we can show them
+ to the user. To avoid leaking, we need
+ to free the traces from the last run
+ when we start a new one.
+ */
for bs : re.traces
std.bsfree(bs)
;;
@@ -206,16 +218,34 @@ const run = {re, str, idx, wholestr
if re.trace
std.put("switch\n")
;;
- /* set up the next thread */
thr = re.runq
re.runq = thr.next
ip = thr.ip
+ /*
+ Stepping continues until the first
+ non-consuming operator is seen. This
+ keeps all the threads in lockstep,
+ which means that when a match is
+ encountered, we know all the other
+ threads have seen what they need
+ to, and we can terminate them.
+ */
consumed = step(re, thr, -1)
while !consumed
consumed = step(re, thr, ip)
;;
+ /*
+ * Because threads have no memory,
+ * their ip (and current input
+ * character, which is the same
+ * thanks to the above mentioned
+ * lockstep) uniquely identify them.
+ * As a result, if we have two
+ * threads with the same ip, one of
+ * them can be culled.
+ */
if std.bshas(states, thr.ip)
die(re, thr)
;;
@@ -259,10 +289,26 @@ const run = {re, str, idx, wholestr
-> bestmatch
}
-/*
- Steps forward one instruction. Returns true if a byte of input was
- consumed, false otherwise.
-*/
+/*
+ * Step executes a single step of the compiled regex.
+ *
+ * Operations fall into two overall categories. Consuming
+ * operators advance the match, and nonconsuming operators
+ * change the state of the regex virtual machine.
+ *
+ * Consuming operators are simple: They check if the current
+ * character matches a criteria, and then advance the regex.
+ *
+ * Nonconsuming operators can do one of several things. They
+ * can fork the vm, record a successful match, or mark a
+ * thread as a failure.
+ *
+ * A thread continues to run forward until a consuming
+ * opcode is encountered, after which it must switch.
+ * This is in order to keep all threads in lockstep
+ * operating over the same characters, and finishing
+ * at the same time.
+ */
const step = {re, thr, curip
var str, nthr, inst
@@ -275,7 +321,7 @@ const step = {re, thr, curip
std.bsput(re.traces[thr.tid], thr.ip)
;;
match inst & 0xf
- /* Char matching. Consume exactly one byte from the string. */
+ /* Consuming opcodes */
| OpRange:
var lo = (inst >> 4 : byte)
var hi = (inst >> 16 : byte)
@@ -308,10 +354,7 @@ const step = {re, thr, curip
;;
thr.ip = lip
-> false
- /*
- Non-consuming. All of these return false, and expect step to be
- called again until exactly one byte is consumed from the string.
- */
+ /* Non-consuming opcodes. */
| OpJmp:
var ip = (inst >> 4 : std.size)
thr.ip = ip
@@ -345,7 +388,6 @@ const step = {re, thr, curip
else
die(re, thr)
;;
- /* check for word characters */
| OpBow:
if iswordchar(str[re.strp:]) && (re.strp == 0 || !iswordchar(prevchar(str, re.strp)))
thr.ip++
@@ -443,7 +485,6 @@ const itrace = {re, thr, inst
;;
}
-/* must be called with i >= 1 */
const prevchar = {s, i
std.assert(i != 0, "prevchar must be called with i >= 1\n")
i--
diff --git a/lib/regex/redump.myr b/lib/regex/redump.myr
index 4a4fe8f..6ac04ce 100644
--- a/lib/regex/redump.myr
+++ b/lib/regex/redump.myr
@@ -68,6 +68,21 @@ const dump = {re, fd
;;
}
+/*
+ * Renders a match in a way that's pleasant to read. There are
+ * two cases here.
+ *
+ * 1) The pattern matched. In this case, we want to show the
+ * regions of the pattern that contributed to the match.
+ *
+ * 2) The pattern did not match. In this case, we want to show
+ * the location of the failed match.
+ *
+ * In both cases, we render a caret that describes the position
+ * of the match. Unfortunately, for the coverage code we don't
+ * have a great way of mapping whole subranges, so the caret can
+ * be slightly truncated. Fixing this isn't worth hte complexity.
+ */
const show = {re, ln, mg
match mg
| `std.Some rl:
@@ -81,13 +96,21 @@ const show = {re, ln, mg
| `std.None:
std.put("Match failed at {}:\n", re.lastip)
std.put("\t{}\n", re.pat)
- caret(re, re.pcidx[re.lastip])
+ showpos(re, re.pcidx[re.lastip])
std.put("\t{}\n", ln)
- caret(re, re.strp - 1)
+ showpos(re, re.strp - 1)
;;
}
-const caret = {re, idx
+/*
+ * Simple position carets for failures: Draws out
+ * an arrow of the form:
+ *
+ * ~~~~~^
+ *
+ * from the start of the line.
+ */
+const showpos = {re, idx
std.put("\t")
for var i = 0; i < idx; i++
std.put("~")
@@ -95,6 +118,13 @@ const caret = {re, idx
std.put("^\n")
}
+/*
+ * Coverage carets for success. This tries to output
+ * a '^' for every section of the string that matched.
+ *
+ * (this|that)
+ * ^^^^
+ */
const showcoverage = {re
var hit
var idx
diff --git a/lib/std/bigint.myr b/lib/std/bigint.myr
index d708f7d..afa65c1 100644
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -741,7 +741,6 @@ const bigdivmod = {a : bigint#, b : bigint# -> (bigint#, bigint#)
;;
/* undo the biasing for remainder */
bigshri(u, shift)
- trim(q)
bigfree(v)
-> (trim(q), trim(u))
}
diff --git a/lib/std/env+posixy.myr b/lib/std/env+posixy.myr
index 7ee9e43..cf4d8f7 100644
--- a/lib/std/env+posixy.myr
+++ b/lib/std/env+posixy.myr
@@ -59,21 +59,25 @@ const setenv = {name, val
lock(envlck)
for envp : environ
- if envp != Zenvp
- env = cstrconvp(envp)
- n = min(name.len, env.len - 1)
- if eq(name, env[:n]) && env[n] == ('=' : byte)
- found = true
- break
- ;;
- idx++
+ if envp == Zenvp
+ break
+ ;;
+
+ env = cstrconvp(envp)
+ n = min(name.len, env.len - 1)
+ if eq(name, env[:n]) && env[n] == ('=' : byte)
+ found = true
+ break
;;
+ idx++
;;
- if !found
- idx = env.len - 1
+ if found
+ std.slfree(cstrconvp(environ[idx]))
+ else
+ idx = environ.len - 1
std.slpush(&environ, Zenvp)
;;
- e = cstrconvp(environ[idx])
+ environ[idx] = (e : byte#)
sys.__cenvp = (environ : byte##)
unlock(envlck)
}
diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr
index c26d5c4..c7e7eda 100644
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -492,7 +492,12 @@ const strfmt = {sb, str, params
| ("p", pad): p = decode(pad)
| ("r", ""): raw = true
| ("e", ""): esc = true
- | _: std.die("unreachable\n")
+ | (opt, arg):
+ std.write(2, "fmt: ")
+ std.write(2, opt)
+ std.write(2, "arg: ")
+ std.write(2, arg)
+ std.die("unreachable\n")
;;
;;
iassert(p >= 0, "pad must be >= 0")
diff --git a/lib/std/hashfuncs.myr b/lib/std/hashfuncs.myr
index 013bfde..96eb91a 100644
--- a/lib/std/hashfuncs.myr
+++ b/lib/std/hashfuncs.myr
@@ -18,6 +18,12 @@ pkg std =
}
;;
+ impl equatable bool =
+ eq = {a, b
+ -> a == b
+ }
+ ;;
+
impl equatable @a :: integral,numeric @a =
eq = {a, b
-> a == b
diff --git a/lib/std/strfind.myr b/lib/std/strfind.myr
index 3645f8c..f446f69 100644
--- a/lib/std/strfind.myr
+++ b/lib/std/strfind.myr
@@ -8,19 +8,16 @@ pkg std =
;;
const strfind = {haystack, needle
- -> strfindin(haystack, needle, 0, haystack.len)
+ -> strfindin(haystack, needle, 0, haystack.len, 1)
}
const strrfind = {haystack, needle
- -> strfindin(haystack, needle, haystack.len - 1, -1)
+ -> strfindin(haystack, needle, haystack.len - 1, -1, -1)
}
-const strfindin = {haystack, needle, start, end
- var inc : size
-
- inc = 1
- if start > end
- inc = -1
+const strfindin = {haystack, needle, start, end, inc
+ if haystack.len == 0 && needle.len == 0
+ -> `std.Some 0
;;
for var i = start; i != end; i += inc
/*
@@ -30,14 +27,12 @@ const strfindin = {haystack, needle, start, end
if i + needle.len > haystack.len
continue
;;
- if haystack[i] == needle[0]
- for var j = 0; j < needle.len; j++
- if haystack[i + j] != needle[j]
- goto nextiter
- ;;
+ for var j = 0; j < needle.len; j++
+ if haystack[i + j] != needle[j]
+ goto nextiter
;;
- -> `Some i
;;
+ -> `Some i
:nextiter
;;
-> `None
diff --git a/lib/std/test/fltbits.myr b/lib/std/test/fltbits.myr
index 3907a0f..6493231 100644
--- a/lib/std/test/fltbits.myr
+++ b/lib/std/test/fltbits.myr
@@ -1,8 +1,18 @@
use std
-
use testr
+var testnan
+
const main = {
+ var si
+
+ /* Floating point mode traps on 9front. */
+ std.getsysinfo(&si)
+ match si.system
+ | "Plan9": testnan = false
+ | _: testnan = true
+ ;;
+
testr.run([
[.name = "isnan", .fn = isnan01],
[.name = "bits-roundtrip-32", .fn = bitsround32],
@@ -15,24 +25,26 @@ const main = {
}
const isnan01 = {c
- testr.check(c, std.isnan(std.flt64nan()), "std.flt64nan() should give a NaN")
- testr.check(c, std.isnan(std.flt32nan()), "std.flt32nan() should give a NaN")
-
- /*
- a NaN should be {any sign bit}, then {8 or 11 exponent
- bits, all 1}, then {any non-zero sequence of 23 or 52
- bits}
- */
- testr.check(c, std.isnan(std.flt64frombits(0xfff0000500000000ul)), "0xfff0000500000000 should be a NaN")
- testr.check(c, std.isnan(std.flt64frombits(0x7ff0000500000000ul)), "0x7ff0000500000000 should be a NaN")
- testr.check(c, std.isnan(std.flt32frombits(0xff800090)), "0xff800090 should be a NaN")
- testr.check(c, std.isnan(std.flt32frombits(0x7f800090)), "0x7f800090 should be a NaN")
-
- /* if the significand bits are all 0, it's an infinity instead */
- testr.check(c, !std.isnan(std.flt64frombits(0x7ff0000000000000ul)), "Infinities[1] should not be NaNs")
- testr.check(c, !std.isnan(std.flt64frombits(0xfff0000000000000ul)), "Infinities[2] should not be NaNs")
- testr.check(c, !std.isnan(std.flt32frombits(0xff800000)), "Infinities[3] should not be NaNs")
- testr.check(c, !std.isnan(std.flt32frombits(0x7f800000)), "Infinities[4] should not be NaNs")
+ if testnan
+ testr.check(c, std.isnan(std.flt64nan()), "std.flt64nan() should give a NaN")
+ testr.check(c, std.isnan(std.flt32nan()), "std.flt32nan() should give a NaN")
+
+ /*
+ a NaN should be {any sign bit}, then {8 or 11 exponent
+ bits, all 1}, then {any non-zero sequence of 23 or 52
+ bits}
+ */
+ testr.check(c, std.isnan(std.flt64frombits(0xfff0000500000000ul)), "0xfff0000500000000 should be a NaN")
+ testr.check(c, std.isnan(std.flt64frombits(0x7ff0000500000000ul)), "0x7ff0000500000000 should be a NaN")
+ testr.check(c, std.isnan(std.flt32frombits(0xff800090)), "0xff800090 should be a NaN")
+ testr.check(c, std.isnan(std.flt32frombits(0x7f800090)), "0x7f800090 should be a NaN")
+
+ /* if the significand bits are all 0, it's an infinity instead */
+ testr.check(c, !std.isnan(std.flt64frombits(0x7ff0000000000000ul)), "Infinities[1] should not be NaNs")
+ testr.check(c, !std.isnan(std.flt64frombits(0xfff0000000000000ul)), "Infinities[2] should not be NaNs")
+ testr.check(c, !std.isnan(std.flt32frombits(0xff800000)), "Infinities[3] should not be NaNs")
+ testr.check(c, !std.isnan(std.flt32frombits(0x7f800000)), "Infinities[4] should not be NaNs")
+ ;;
}
const bitsround32 = {c
@@ -46,9 +58,11 @@ const bitsround32 = {c
testr.check(c, u == v, "bits -> flt -> bits non-identity: {} != {}", u, v)
;;
- var nan_f = std.flt32frombits(0xff800090)
- var nan_g = std.flt32frombits(std.flt32bits(nan_f))
- testr.check(c, nan_f == nan_g, "flt -> bits -> flt non-identity for nan")
+ if testnan
+ var nan_f = std.flt32frombits(0xff800090)
+ var nan_g = std.flt32frombits(std.flt32bits(nan_f))
+ testr.check(c, nan_f == nan_g, "flt -> bits -> flt non-identity for nan")
+ ;;
var inf_f = std.flt32frombits(0x7f800000)
var inf_g = std.flt32frombits(std.flt32bits(inf_f))
@@ -66,9 +80,11 @@ const bitsround64 = {c
testr.check(c, u == v, "bits -> flt -> bits non-identity: {} != {}", u, v)
;;
- var nan_f = std.flt64frombits(0x7ff000000000a000ul)
- var nan_g = std.flt64frombits(std.flt64bits(nan_f))
- testr.check(c, nan_f == nan_g, "flt -> bits -> flt non-identity for nan")
+ if testnan
+ var nan_f = std.flt64frombits(0x7ff000000000a000ul)
+ var nan_g = std.flt64frombits(std.flt64bits(nan_f))
+ testr.check(c, nan_f == nan_g, "flt -> bits -> flt non-identity for nan")
+ ;;
var inf_f = std.flt64frombits(0xfff0000000000000ul)
var inf_g = std.flt64frombits(std.flt64bits(inf_f))
diff --git a/lib/sys/bld.sub b/lib/sys/bld.sub
index abf90f5..6bc266b 100644
--- a/lib/sys/bld.sub
+++ b/lib/sys/bld.sub
@@ -5,10 +5,13 @@ lib sys =
sys+netbsd-x64.myr
sys+linux-x64.myr
sys+osx-x64.myr
+ sys+plan9-x64.myr
+
+ # openbsd versions.
sys+openbsd-x64.myr
sys+openbsd:6.1-x64.myr
sys+openbsd:6.2-x64.myr
- sys+plan9-x64.myr
+ sys+openbsd:6.3-x64.myr
syscall+freebsd-x64.s
syscall+netbsd-x64.s
diff --git a/lib/sys/sys+openbsd-x64.myr b/lib/sys/sys+openbsd-x64.myr
index 7b0df69..454567a 100644
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -215,6 +215,7 @@ pkg sys =
const Mfixed : mopt = 0x10
const Mfile : mopt = 0x0
const Manon : mopt = 0x1000
+ const Mstack : mopt = 0x4000
const Mnoreplace : mopt = 0x0800
/* file types */
diff --git a/lib/sys/sys+openbsd:6.2-x64.myr b/lib/sys/sys+openbsd:6.2-x64.myr
index 4a1f0e5..62bc1d2 100644
--- a/lib/sys/sys+openbsd:6.2-x64.myr
+++ b/lib/sys/sys+openbsd:6.2-x64.myr
@@ -348,6 +348,7 @@ pkg sys =
const Mfixed : mopt = 0x10
const Mfile : mopt = 0x0
const Manon : mopt = 0x1000
+ const Mstack : mopt = 0x4000
const Mnoreplace : mopt = 0x0800
/* file types */
diff --git a/lib/sys/sys+openbsd:6.3-x64.myr b/lib/sys/sys+openbsd:6.3-x64.myr
new file mode 100644
index 0000000..82a6b17
--- /dev/null
+++ b/lib/sys/sys+openbsd:6.3-x64.myr
@@ -0,0 +1,1759 @@
+/*
+ generated-ish source
+ stitched for openbsd:6.3 arch:x64
+ edit with caution.
+ */
+pkg sys =
+ type size = int64 /* spans entire address space */
+ type usize = uint64 /* unsigned size */
+ type off = int64 /* file offsets */
+ type intptr = uint64/* can hold any pointer losslessly */
+ type time = int64 /* milliseconds since epoch */
+ type pid = int32 /* process id */
+ type scno = int64 /*syscall*/
+ type fdopt = int64 /* fd options */
+ type fd = int32 /* fd */
+ type whence = uint64 /* seek from whence */
+ type mprot = int64 /* memory protection */
+ type mopt = int64 /* memory mapping options */
+ type socktype = int64 /* socket type */
+ type sockproto = int64 /* socket protocol */
+ type sockopt = int32 /* socket option */
+ type sockfam = uint8 /* socket family */
+ type filemode = uint32
+ type filetype = uint8
+ type fcntlcmd = int64
+ type signo = int32
+ type sigflags = int32
+ type sigset = uint32
+ type msg = void
+ type gid = uint32
+
+ const Futexwait : int = 1
+ const Futexwake : int = 2
+ const Futexrequeue : int = 3
+
+
+ type clock = union
+ `Clockrealtime
+ `Clockmonotonic
+ `Clockproccputime
+ `Clockthreadcputime
+ `Clockuptime
+ ;;
+
+ type waitstatus = union
+ `Waitfail int32
+ `Waitexit int32
+ `Waitsig int32
+ `Waitstop int32
+ ;;
+
+ type rlimit = struct
+ cur : uint64 /* current (soft) limit */
+ max : uint64 /* maximum value for rlim_cur */
+ ;;
+
+ type timespec = struct
+ sec : uint64
+ nsec : uint64
+ ;;
+
+ type timeval = struct
+ sec : uint64
+ usec : uint64
+ ;;
+
+ type timezone = struct
+ minwest : int32 /* minutes west of Greenwich */
+ dsttime : int32 /* type of dst correction */
+ ;;
+
+ type pollfd = struct
+ fd : fd
+ events : uint16
+ revents : uint16
+ ;;
+
+ type itimerval = struct
+ interval : timeval /* timer interval */
+ value : timeval /* current value */
+ ;;
+
+ type sigaction = struct
+ handler : byte# /* code pointer */
+ mask : sigset
+ flags : sigflags
+ ;;
+ /*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+ type sigcontext = struct
+ /* plain match trapframe */
+ rdi : int64
+ rsi : int64
+ rdx : int64
+ rcx : int64
+ r8 : int64
+ r9 : int64
+ r10 : int64
+ r11 : int64
+ r12 : int64
+ r13 : int64
+ r14 : int64
+ r15 : int64
+ rbp : int64
+ rbx : int64
+ rax : int64
+ gs : int64
+ fs : int64
+ es : int64
+ ds : int64
+ trapno : int64
+ err : int64
+ rip : int64
+ cs : int64
+ rflags : int64
+ rsp : int64
+ ss : int64
+
+ fpstate : fxsave64#
+ __pad : int32
+ mask : int32
+ cookie : int64
+ ;;
+
+ type sigaltstack = struct
+ sp : void#
+ size : size
+ flags : int32
+ ;;
+
+ type fxsave64 = struct
+ fcw : int16
+ fsw : int16
+ ftw : int8
+ unused1 : int8
+ fop : int16
+ rip : int64
+ rdp : int64
+ mxcsr : int32
+ mxcsrmask : int32
+ st : int64[8][2] /* 8 normal FP regs */
+ xmm : int64[16][2] /* 16 SSE2 registers */
+ unused3 : int8[96]
+ ;;
+
+ const Simaxsz = 128
+ const Sipad = (Simaxsz / 4) - 3
+ type siginfo = struct
+ signo : int
+ code : int
+ errno : int
+ pad : int[Sipad]
+ ;;
+
+ type rusage = struct
+ utime : timeval /* user time */
+ stime : timeval /* system time */
+ maxrss : uint64 /* max resident set size*/
+ ixrss : uint64 /* shared text size */
+ idrss : uint64 /* unshared data size */
+ isrss : uint64 /* unshared stack size */
+ minflt : uint64 /* page reclaims */
+ majflt : uint64 /* page faults */
+ nswap : uint64 /* swaps */
+ inblock : uint64 /* block input ops */
+ oublock : uint64 /* block output ops */
+ msgsnd : uint64 /* messages sent */
+ msgrcv : uint64 /* messages received */
+ nsignals : uint64 /* signals received */
+ nvcsw : uint64 /* voluntary context switches */
+ nivcsw : uint64 /* involuntary context switches */
+ ;;
+
+ type tforkparams = struct
+ tcb : void#
+ tid : pid#
+ stk : byte#
+ ;;
+
+ type statbuf = struct
+ mode : filemode
+ dev : uint32
+ ino : uint64
+ nlink : uint32
+ uid : uint32
+ gid : uint32
+ rdev : uint32
+ atime : timespec
+ mtime : timespec
+ ctime : timespec
+ size : off
+ blocks : int64
+ blksize : uint32
+ flags : uint32
+ gen : uint32
+ birthtim : timespec
+ ;;
+
+ type semun = struct
+ semarr : void#
+ ;;
+
+ const Mfsnamelen = 16 /* length of fs type name, including nul */
+ const Mnamelen = 90 /* length of buffer for returned name */
+
+ type statfs = struct
+ flags : uint32 /* copy of mount flags */
+ bsize : uint32 /* file system block size */
+ iosize : uint32 /* optimal transfer block size */
+
+ /* unit is f_bsize */
+ blocks : uint64 /* total data blocks in file system */
+ bfree : uint64 /* free blocks in fs */
+ bavail : int64 /* free blocks avail to non-superuser */
+
+ files : int64 /* total file nodes in file system */
+ ffree : int64 /* free file nodes in fs */
+ favail : int64 /* free file nodes avail to non-root */
+
+ syncwr : int64 /* count of sync writes since mount */
+ syncrd : int64 /* count of sync reads since mount */
+ asyncwr : int64 /* count of async writes since mount */
+ asyncrd : int64 /* count of async reads since mount */
+
+ fsid : fsid /* file system id */
+ namemax : uint32 /* maximum filename length */
+ owner : uid /* user that mounted the file system */
+ ctime : uint64 /* last mount [-u] time */
+
+ fstypename : byte[Mfsnamelen]; /* fs type name */
+ mntonname : byte[Mnamelen]; /* directory on which mounted */
+ mntfromname : byte[Mnamelen]; /* mounted file system */
+ mntfromspec : byte[Mnamelen]; /* special for mount request */
+ ///union mount_info mount_info; /* per-filesystem mount options */
+ __mountinfo : byte[160]; /* storage for 'union mount_info' */
+ ;;
+
+ type utsname = struct
+ system : byte[32]
+ node : byte[32]
+ release : byte[32]
+ version : byte[32]
+ machine : byte[32]
+ ;;
+
+ type sockaddr = struct
+ len : byte
+ fam : sockfam
+ data : byte[14] /* what is the *actual* length? */
+ ;;
+
+ type sockaddr_in = struct
+ len : byte
+ fam : sockfam
+ port : uint16
+ addr : byte[4]
+ zero : byte[8]
+ ;;
+
+ type sockaddr_in6 = struct
+ len : byte
+ fam : sockfam
+ port : uint16
+ flow : uint32
+ addr : byte[16]
+ scope : uint32
+ ;;
+
+ type sockaddr_un = struct
+ len : uint8
+ fam : sockfam
+ path : byte[104]
+ ;;
+
+ type sockaddr_storage = struct
+ len : byte
+ fam : sockfam
+ __pad1 : byte[6]
+ __align : int64
+ __pad2 : byte[240]
+ ;;
+
+ type dirent = struct
+ fileno : uint64
+ off : uint64
+ reclen : uint16
+ ftype : uint8
+ namlen : uint8
+ __pad : byte[4]
+ name : byte[256]
+ ;;
+
+ type iovec = struct
+ base : byte#
+ len : uint64
+ ;;
+
+ /* open options */
+ const Ordonly : fdopt = 0x0
+ const Owronly : fdopt = 0x1
+ const Ordwr : fdopt = 0x2
+ const Oappend : fdopt = 0x8
+ const Ondelay : fdopt = 0x4
+ const Oshlock : fdopt = 0x10 /* open with shared file lock */
+ const Oexlock : fdopt = 0x20 /* open with exclusive file lock */
+ const Oasync : fdopt = 0x40 /* signal pgrp when data ready */
+ const Osync : fdopt = 0x80 /* backwards compatibility */
+ const Onofollow : fdopt = 0x100
+ const Ocreat : fdopt = 0x200
+ const Otrunc : fdopt = 0x400
+ const Oexcl : fdopt = 0x800
+ const Ocloexec : fdopt = 0x10000
+ const Odsync : fdopt = Osync /* synchronous data writes */
+ const Orsync : fdopt = Osync /* synchronous reads */
+ const Odir : fdopt = 0x20000
+
+ /* poll options */
+ const Pollin : uint16 = 0x0001
+ const Pollpri : uint16 = 0x0002
+ const Pollout : uint16 = 0x0004
+ const Pollerr : uint16 = 0x0008
+ const Pollhup : uint16 = 0x0010
+ const Pollnval : uint16 = 0x0020
+ const Pollnorm : uint16 = 0x0040
+ const Pollrdband: uint16 = 0x0080
+ const Pollwrband: uint16 = 0x0100
+
+ /* stat modes */
+ const Sifmt : filemode = 0xf000
+ const Sififo : filemode = 0x1000
+ const Sifchr : filemode = 0x2000
+ const Sifdir : filemode = 0x4000
+ const Sifblk : filemode = 0x6000
+ const Sifreg : filemode = 0x8000
+ const Siflnk : filemode = 0xa000
+ const Sifsock : filemode = 0xc000
+ const Sisvtx : filemode = 0x0200
+
+ /* mmap protection */
+ const Mprotnone : mprot = 0x0
+ const Mprotrd : mprot = 0x1
+ const Mprotwr : mprot = 0x2
+ const Mprotexec : mprot = 0x4
+ const Mprotrw : mprot = 0x3
+
+ /* mmap options */
+ const Mshared : mopt = 0x1
+ const Mpriv : mopt = 0x2
+ const Mfixed : mopt = 0x10
+ const Mfile : mopt = 0x0
+ const Manon : mopt = 0x1000
+ const Mstack : mopt = 0x4000
+ const Mnoreplace : mopt = 0x0800
+
+ /* file types */
+ const Dtunknown : filetype = 0
+ const Dtfifo : filetype = 1
+ const Dtchr : filetype = 2
+ const Dtdir : filetype = 4
+ const Dtblk : filetype = 6
+ const Dtreg : filetype = 8
+ const Dtlnk : filetype = 10
+ const Dtsock : filetype = 12
+
+ /* socket families. INCOMPLETE. */
+ const Afunspec : sockfam = 0
+ const Afunix : sockfam = 1
+ const Afinet : sockfam = 2
+ const Afinet6 : sockfam = 24
+
+ /* socket types. */
+ const Sockstream : socktype = 1
+ const Sockdgram : socktype = 2
+ const Sockraw : socktype = 3
+ const Sockrdm : socktype = 4
+ const Sockseqpacket : socktype = 5
+
+ /* socket options */
+ const Sodebug : sockopt = 0x0001 /* turn on debugging info recording */
+ const Soacceptconn : sockopt = 0x0002 /* socket has had listen() */
+ const Soreuseaddr : sockopt = 0x0004 /* allow local address reuse */
+ const Sokeepalive : sockopt = 0x0008 /* keep connections alive */
+ const Sodontroute : sockopt = 0x0010 /* just use interface addresses */
+ const Sobroadcast : sockopt = 0x0020 /* permit sending of broadcast msgs */
+ const Souseloopback : sockopt = 0x0040 /* bypass hardware when possible */
+ const Solinger : sockopt = 0x0080 /* linger on close if data present */
+ const Sooobinline : sockopt = 0x0100 /* leave received OOB data in line */
+ const Soreuseport : sockopt = 0x0200 /* allow local address & port reuse */
+ const Sotimestamp : sockopt = 0x0800 /* timestamp received dgram traffic */
+ const Sobindany : sockopt = 0x1000 /* allow bind to any address */
+ const Sosndbuf : sockopt = 0x1001 /* send buffer size */
+ const Sorcvbuf : sockopt = 0x1002 /* receive buffer size */
+ const Sosndlowat : sockopt = 0x1003 /* send low-water mark */
+ const Sorcvlowat : sockopt = 0x1004 /* receive low-water mark */
+ const Sosndtimeo : sockopt = 0x1005 /* send timeout */
+ const Sorcvtimeo : sockopt = 0x1006 /* receive timeout */
+ const Soerror : sockopt = 0x1007 /* get error status and clear */
+ const Sotype : sockopt = 0x1008 /* get socket type */
+ const Sonetproc : sockopt = 0x1020 /* multiplex; network processing */
+ const Sortable : sockopt = 0x1021 /* routing table to be used */
+ const Sopeercred : sockopt = 0x1022 /* get connect-time credentials */
+ const Sosplice : sockopt = 0x1023 /* splice data to other socket */
+
+ /* socket option levels */
+ const Solsocket : sockproto = 0xffff
+
+ /* network protocols */
+ const Ipproto_ip : sockproto = 0
+ const Ipproto_icmp : sockproto = 1
+ const Ipproto_tcp : sockproto = 6
+ const Ipproto_udp : sockproto = 17
+ const Ipproto_raw : sockproto = 255
+
+ const Seekset : whence = 0
+ const Seekcur : whence = 1
+ const Seekend : whence = 2
+
+ /* system specific constants */
+ const Maxpathlen : size = 1024
+
+ /* fcntl constants */
+ const Fdupfd : fcntlcmd = 0 /* duplicate file descriptor */
+ const Fgetfd : fcntlcmd = 1 /* get file descriptor flags */
+ const Fsetfd : fcntlcmd = 2 /* set file descriptor flags */
+ const Fgetfl : fcntlcmd = 3 /* get file status flags */
+ const Fsetfl : fcntlcmd = 4 /* set file status flags */
+ const Fgetown : fcntlcmd = 5 /* get SIGIO/SIGURG proc/pgrp */
+ const Fsetown : fcntlcmd = 6 /* set SIGIO/SIGURG proc/pgrp */
+ const Fogetlk : fcntlcmd = 7 /* get record locking information */
+ const Fosetlk : fcntlcmd = 8 /* set record locking information */
+
+ /* return value for a failed mapping */
+ const Mapbad : byte# = (-1 : byte#)
+
+ /* signal flags */
+ const Saonstack : sigflags = 0x0001 /* take signal on signal stack */
+ const Sarestart : sigflags = 0x0002 /* restart system on signal return */
+ const Saresethand : sigflags = 0x0004 /* reset to SIG_DFL when taking signal */
+ const Sanodefer : sigflags = 0x0010 /* don't mask the signal we're delivering */
+ const Sanocldwait : sigflags = 0x0020 /* don't create zombies (assign to pid 1) */
+ const Sanocldstop : sigflags = 0x0008 /* do not generate SIGCHLD on child stop */
+ const Sasiginfo : sigflags = 0x0040 /* generate siginfo_t */
+
+ /* signals */
+ const Sighup : signo = 1 /* hangup */
+ const Sigint : signo = 2 /* interrupt */
+ const Sigquit : signo = 3 /* quit */
+ const Sigill : signo = 4 /* illegal instruction (not reset when caught) */
+ const Sigtrap : signo = 5 /* trace trap (not reset when caught) */
+ const Sigabrt : signo = 6 /* abort() */
+ const Sigiot : signo = Sigabrt /* compatibility */
+ const Sigemt : signo = 7 /* EMT instruction */
+ const Sigfpe : signo = 8 /* floating point exception */
+ const Sigkill : signo = 9 /* kill (cannot be caught or ignored) */
+ const Sigbus : signo = 10 /* bus error */
+ const Sigsegv : signo = 11 /* segmentation violation */
+ const Sigsys : signo = 12 /* bad argument to system call */
+ const Sigpipe : signo = 13 /* write on a pipe with no one to read it */
+ const Sigalrm : signo = 14 /* alarm clock */
+ const Sigterm : signo = 15 /* software termination signal from kill */
+ const Sigurg : signo = 16 /* urgent condition on IO channel */
+ const Sigstop : signo = 17 /* sendable stop signal not from tty */
+ const Sigtstp : signo = 18 /* stop signal from tty */
+ const Sigcont : signo = 19 /* continue a stopped process */
+ const Sigchld : signo = 20 /* to parent on child stop or exit */
+ const Sigttin : signo = 21 /* to readers pgrp upon background tty read */
+ const Sigttou : signo = 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
+ const Sigio : signo = 23 /* input/output possible signal */
+ const Sigxcpu : signo = 24 /* exceeded CPU time limit */
+ const Sigxfsz : signo = 25 /* exceeded file size limit */
+ const Sigvtalrm : signo = 26 /* virtual time alarm */
+ const Sigprof : signo = 27 /* profiling time alarm */
+ const Sigwinch : signo = 28 /* window size changes */
+ const Siginfo : signo = 29 /* information request */
+ const Sigusr1 : signo = 30 /* user defined signal 1 */
+ const Sigusr2 : signo = 31 /* user defined signal 2 */
+ const Sigthr : signo = 32 /* thread library AST */
+
+ extern const syscall : (sc:scno, args:... -> int64)
+ extern var __cenvp : byte##
+ type dev = int32
+ type uid = uint32
+ type fd_mask = uint32
+ type uintptr = uint64
+ type clockid = int32
+ type id = uint32
+ type key = int64
+ type shmatt = int16
+
+ type tfork = struct
+ tcb : void#
+ tid : pid#
+ stack : void#
+
+ ;;
+
+ type msghdr = struct
+ name : void#
+ namelen : int32
+ iov : iovec#
+ iovlen : uint
+ control : void#
+ controllen : int32
+ flags : int
+
+ ;;
+
+ type fsid = struct
+ val : int32[2]
+
+ ;;
+
+ type fid = struct
+ len : uint16
+ reserved : uint16
+ data : byte[16]
+
+ ;;
+
+ type fhandle = struct
+ fsid : fsid
+ fid : fid
+
+ ;;
+
+ type fdset = struct
+ bits : fd_mask[32]
+
+ ;;
+
+ type kevent = struct
+ ident : uintptr
+ filter : int16
+ flags : uint16
+ fflags : uint
+ data : int64
+ udata : void#
+
+ ;;
+
+ type kbind = struct
+ addr : void#
+ size : size
+
+ ;;
+
+ type sembuf = struct
+ num : uint16
+ op : int16
+ flg : int16
+
+ ;;
+
+ type ipc_perm = struct
+ cuid : uid
+ cgid : gid
+ uid : uid
+ gid : gid
+ mode : filemode
+ seq : uint16
+ key : key
+
+ ;;
+
+ type shmid_ds = struct
+ perm : ipc_perm
+ segsz : int
+ lpid : pid
+ cpid : pid
+ nattch : shmatt
+ atime : time
+ atimensec : int64
+ dtime : time
+ dtimensec : int64
+ ctime : time
+ ctimensec : int64
+ internal : void#
+
+ ;;
+
+ type msqid_ds = struct
+ perm : ipc_perm
+ first : msg#
+ last : msg#
+ cbytes : uint64
+ qnum : uint64
+ qbytes : uint64
+ lspid : pid
+ lrpid : pid
+ stime : time
+ pad1 : int64
+ rtime : time
+ pad2 : int64
+ ctime : time
+ pad3 : int64
+ pad4 : int64[4]
+
+ ;;
+
+
+ const Sysexit : scno = 1
+ const Sysfork : scno = 2
+ const Sysread : scno = 3
+ const Syswrite : scno = 4
+ const Sysopen : scno = 5
+ const Sysclose : scno = 6
+ const Sysgetentropy : scno = 7
+ const Sys__tfork : scno = 8
+ const Syslink : scno = 9
+ const Sysunlink : scno = 10
+ const Syswait4 : scno = 11
+ const Syschdir : scno = 12
+ const Sysfchdir : scno = 13
+ const Sysmknod : scno = 14
+ const Syschmod : scno = 15
+ const Syschown : scno = 16
+ const Sysobreak : scno = 17
+ const Sysgetdtablecount : scno = 18
+ const Sysgetrusage : scno = 19
+ const Sysgetpid : scno = 20
+ const Sysmount : scno = 21
+ const Sysunmount : scno = 22
+ const Syssetuid : scno = 23
+ const Sysgetuid : scno = 24
+ const Sysgeteuid : scno = 25
+ const Sysptrace : scno = 26
+ const Sysrecvmsg : scno = 27
+ const Syssendmsg : scno = 28
+ const Sysrecvfrom : scno = 29
+ const Sysaccept : scno = 30
+ const Sysgetpeername : scno = 31
+ const Sysgetsockname : scno = 32
+ const Sysaccess : scno = 33
+ const Syschflags : scno = 34
+ const Sysfchflags : scno = 35
+ const Syssync : scno = 36
+ const Sysstat : scno = 38
+ const Sysgetppid : scno = 39
+ const Syslstat : scno = 40
+ const Sysdup : scno = 41
+ const Sysfstatat : scno = 42
+ const Sysgetegid : scno = 43
+ const Sysprofil : scno = 44
+ const Sysktrace : scno = 45
+ const Syssigaction : scno = 46
+ const Sysgetgid : scno = 47
+ const Syssigprocmask : scno = 48
+ const Syssetlogin : scno = 50
+ const Sysacct : scno = 51
+ const Syssigpending : scno = 52
+ const Sysfstat : scno = 53
+ const Sysioctl : scno = 54
+ const Sysreboot : scno = 55
+ const Sysrevoke : scno = 56
+ const Syssymlink : scno = 57
+ const Sysreadlink : scno = 58
+ const Sysexecve : scno = 59
+ const Sysumask : scno = 60
+ const Syschroot : scno = 61
+ const Sysgetfsstat : scno = 62
+ const Sysstatfs : scno = 63
+ const Sysfstatfs : scno = 64
+ const Sysfhstatfs : scno = 65
+ const Sysvfork : scno = 66
+ const Sysgettimeofday : scno = 67
+ const Syssettimeofday : scno = 68
+ const Syssetitimer : scno = 69
+ const Sysgetitimer : scno = 70
+ const Sysselect : scno = 71
+ const Syskevent : scno = 72
+ const Sysmunmap : scno = 73
+ const Sysmprotect : scno = 74
+ const Sysmadvise : scno = 75
+ const Sysutimes : scno = 76
+ const Sysfutimes : scno = 77
+ const Sysmincore : scno = 78
+ const Sysgetgroups : scno = 79
+ const Syssetgroups : scno = 80
+ const Sysgetpgrp : scno = 81
+ const Syssetpgid : scno = 82
+ const Sysfutex : scno = 83
+ const Sysutimensat : scno = 84
+ const Sysfutimens : scno = 85
+ const Syskbind : scno = 86
+ const Sysclock_gettime : scno = 87
+ const Sysclock_settime : scno = 88
+ const Sysclock_getres : scno = 89
+ const Sysdup2 : scno = 90
+ const Sysnanosleep : scno = 91
+ const Sysfcntl : scno = 92
+ const Sysaccept4 : scno = 93
+ const Sys__thrsleep : scno = 94
+ const Sysfsync : scno = 95
+ const Syssetpriority : scno = 96
+ const Syssocket : scno = 97
+ const Sysconnect : scno = 98
+ const Sysgetdents : scno = 99
+ const Sysgetpriority : scno = 100
+ const Syspipe2 : scno = 101
+ const Sysdup3 : scno = 102
+ const Syssigreturn : scno = 103
+ const Sysbind : scno = 104
+ const Syssetsockopt : scno = 105
+ const Syslisten : scno = 106
+ const Syschflagsat : scno = 107
+ const Syspledge : scno = 108
+ const Sysppoll : scno = 109
+ const Syspselect : scno = 110
+ const Syssigsuspend : scno = 111
+ const Syssendsyslog : scno = 112
+ const Sysgetsockopt : scno = 118
+ const Systhrkill : scno = 119
+ const Sysreadv : scno = 120
+ const Syswritev : scno = 121
+ const Syskill : scno = 122
+ const Sysfchown : scno = 123
+ const Sysfchmod : scno = 124
+ const Syssetreuid : scno = 126
+ const Syssetregid : scno = 127
+ const Sysrename : scno = 128
+ const Sysflock : scno = 131
+ const Sysmkfifo : scno = 132
+ const Syssendto : scno = 133
+ const Sysshutdown : scno = 134
+ const Syssocketpair : scno = 135
+ const Sysmkdir : scno = 136
+ const Sysrmdir : scno = 137
+ const Sysadjtime : scno = 140
+ const Sysgetlogin_r : scno = 141
+ const Syssetsid : scno = 147
+ const Sysquotactl : scno = 148
+ const Sysnfssvc : scno = 155
+ const Sysgetfh : scno = 161
+ const Syssysarch : scno = 165
+ const Syspread : scno = 173
+ const Syspwrite : scno = 174
+ const Syssetgid : scno = 181
+ const Syssetegid : scno = 182
+ const Sysseteuid : scno = 183
+ const Syspathconf : scno = 191
+ const Sysfpathconf : scno = 192
+ const Sysswapctl : scno = 193
+ const Sysgetrlimit : scno = 194
+ const Syssetrlimit : scno = 195
+ const Sysmmap : scno = 197
+ const Syslseek : scno = 199
+ const Systruncate : scno = 200
+ const Sysftruncate : scno = 201
+ const Syssysctl : scno = 202
+ const Sysmlock : scno = 203
+ const Sysmunlock : scno = 204
+ const Sysgetpgid : scno = 207
+ const Sysutrace : scno = 209
+ const Syssemget : scno = 221
+ const Sysmsgget : scno = 225
+ const Sysmsgsnd : scno = 226
+ const Sysmsgrcv : scno = 227
+ const Sysshmat : scno = 228
+ const Sysshmdt : scno = 230
+ const Sysminherit : scno = 250
+ const Syspoll : scno = 252
+ const Sysissetugid : scno = 253
+ const Syslchown : scno = 254
+ const Sysgetsid : scno = 255
+ const Sysmsync : scno = 256
+ const Syspipe : scno = 263
+ const Sysfhopen : scno = 264
+ const Syspreadv : scno = 267
+ const Syspwritev : scno = 268
+ const Syskqueue : scno = 269
+ const Sysmlockall : scno = 271
+ const Sysmunlockall : scno = 272
+ const Sysgetresuid : scno = 281
+ const Syssetresuid : scno = 282
+ const Sysgetresgid : scno = 283
+ const Syssetresgid : scno = 284
+ const Sysmquery : scno = 286
+ const Sysclosefrom : scno = 287
+ const Syssigaltstack : scno = 288
+ const Sysshmget : scno = 289
+ const Syssemop : scno = 290
+ const Sysfhstat : scno = 294
+ const Sys__semctl : scno = 295
+ const Sysshmctl : scno = 296
+ const Sysmsgctl : scno = 297
+ const Syssched_yield : scno = 298
+ const Sysgetthrid : scno = 299
+ const Sys__thrwakeup : scno = 301
+ const Sys__threxit : scno = 302
+ const Sys__thrsigdivert : scno = 303
+ const Sys__getcwd : scno = 304
+ const Sysadjfreq : scno = 305
+ const Syssetrtable : scno = 310
+ const Sysgetrtable : scno = 311
+ const Sysfaccessat : scno = 313
+ const Sysfchmodat : scno = 314
+ const Sysfchownat : scno = 315
+ const Syslinkat : scno = 317
+ const Sysmkdirat : scno = 318
+ const Sysmkfifoat : scno = 319
+ const Sysmknodat : scno = 320
+ const Sysopenat : scno = 321
+ const Sysreadlinkat : scno = 322
+ const Sysrenameat : scno = 323
+ const Syssymlinkat : scno = 324
+ const Sysunlinkat : scno = 325
+ const Sys__set_tcb : scno = 329
+ const Sys__get_tcb : scno = 330
+
+ /* start manual overrides { */
+ const exit : (status:int -> void)
+ const getpid : ( -> pid)
+ const kill : (pid:pid, sig:int64 -> int64)
+ const fork : (-> pid)
+ const wait4 : (pid:pid, loc:int32#, opt : int64, usage:rusage# -> int64)
+ const waitpid : (pid:pid, loc:int32#, opt : int64 -> int64)
+ const execv : (cmd : byte[:], args : byte[:][:] -> int64)
+ const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
+ const waitstatus : (st : int32 -> waitstatus)
+ extern const __tfork_thread : (tfp : tforkparams#, sz : size, fn : void#, arg : void# -> pid)
+ const open : (path:byte[:], opts:fdopt -> fd)
+ const openmode : (path:byte[:], opts:fdopt, mode:int64 -> fd)
+ const close : (fd:fd -> int64)
+ const creat : (path:byte[:], mode:int64 -> fd)
+ const unlink : (path:byte[:] -> int)
+ const read : (fd:fd, buf:byte[:] -> size)
+ const pread : (fd:fd, buf:byte[:], off : off -> size)
+ const readv : (fd:fd, iov:iovec[:] -> size)
+ const write : (fd:fd, buf:byte[:] -> size)
+ const pwrite : (fd:fd, buf:byte[:], off : off -> size)
+ const writev : (fd:fd, iov:iovec[:] -> size)
+ const lseek : (fd:fd, off : off, whence : whence -> int64)
+ const stat : (path:byte[:], sb:statbuf# -> int64)
+ const lstat : (path:byte[:], sb:statbuf# -> int64)
+ const fstat : (fd:fd, sb:statbuf# -> int64)
+ const mkdir : (path : byte[:], mode : int64 -> int64)
+ generic ioctl : (fd:fd, req : int64, arg:@a# -> int64)
+ const getdents : (fd : fd, buf : byte[:] -> int64)
+ const chdir : (p : byte[:] -> int64)
+ const __getcwd : (buf : byte[:] -> int64)
+ const poll : (pfd : pollfd[:], tm : int -> int)
+ const sigaction : (sig : signo, act : sigaction#, oact : sigaction# -> int)
+ const sigprocmask : (how : int32, set : sigset#, oset : sigset# -> int)
+ const pipe : (fds : fd[2]# -> int64)
+ const dup : (fd : fd -> fd)
+ const dup2 : (src : fd, dst : fd -> fd)
+ const fcntl : (fd : fd, cmd : fcntlcmd, args : byte# -> int64)
+ const socket : (dom : sockfam, stype : socktype, proto : sockproto -> fd)
+ const connect : (sock : fd, addr : sockaddr#, len : size -> int)
+ const accept : (sock : fd, addr : sockaddr#, len : size# -> fd)
+ const listen : (sock : fd, backlog : int -> int)
+ const bind : (sock : fd, addr : sockaddr#, len : size -> int)
+ const setsockopt : (sock : fd, lev : sockproto, opt : sockopt, val : void#, len : size -> int)
+ const getsockopt : (sock : fd, lev : sockproto, opt : sockopt, val : void#, len : size# -> int)
+ const munmap : (addr:byte#, len:size -> int64)
+ const mmap : (addr:byte#, len:size, prot:mprot, flags:mopt, fd:fd, off:off -> byte#)
+ const clock_getres : (clk : clock, ts : timespec# -> int32)
+ const clock_gettime : (clk : clock, ts : timespec# -> int32)
+ const clock_settime : (clk : clock, ts : timespec# -> int32)
+ const sleep : (time : uint64 -> int32)
+ const nanosleep : (req : timespec#, rem : timespec# -> int32)
+ const uname : (buf : utsname# -> int)
+ const sysctl : (mib : int[:], \
+ old : void#, oldsz : size#, \
+ new : void#, newsz : size# \
+ -> int)
+ extern const cstring : (str : byte[:] -> byte#)
+ extern const alloca : (sz : size -> byte#)
+ extern const __freebsd_pipe : (fds : fd[2]# -> int64)
+ /* } end manual overrides */
+
+ const getentropy : (buf : void#, nbyte : size -> int)
+ const __tfork : (param : tfork#, psize : size -> int)
+ const link : (path : byte#, link : byte# -> int)
+ const fchdir : (fd : int -> int)
+ const mknod : (path : byte#, mode : filemode, dev : dev -> int)
+ const chmod : (path : byte#, mode : filemode -> int)
+ const chown : (path : byte#, uid : uid, gid : gid -> int)
+ const obreak : (nsize : byte# -> int)
+ const getdtablecount : ( -> int)
+ const getrusage : (who : int, rusage : rusage# -> int)
+ const mount : (kind : byte#, path : byte#, flags : int, data : void# -> int)
+ const unmount : (path : byte#, flags : int -> int)
+ const setuid : (uid : uid -> int)
+ const getuid : ( -> uid)
+ const geteuid : ( -> uid)
+ const ptrace : (req : int, pid : pid, addr : void#, data : int -> int)
+ const recvmsg : (s : int, msg : msghdr#, flags : int -> size)
+ const sendmsg : (s : int, msg : msghdr#, flags : int -> size)
+ const recvfrom : (s : int, buf : void#, len : size, flags : int, from : sockaddr#, fromlenaddr : int32# -> size)
+ const getpeername : (fdes : int, asa : sockaddr#, alen : int32# -> int)
+ const getsockname : (fdes : int, asa : sockaddr#, alen : int32# -> int)
+ const access : (path : byte#, amode : int -> int)
+ const chflags : (path : byte#, flags : uint -> int)
+ const fchflags : (fd : int, flags : uint -> int)
+ const sync : ( -> void)
+ const getppid : ( -> pid)
+ const fstatat : (fd : int, path : byte#, buf : statbuf#, flag : int -> int)
+ const getegid : ( -> gid)
+ const profil : (samples : void#, size : size, offset : uint64, scale : uint -> int)
+ const ktrace : (fname : byte#, ops : int, facs : int, pid : pid -> int)
+ const getgid : ( -> gid)
+ const setlogin : (namebuf : byte# -> int)
+ const acct : (path : byte# -> int)
+ const sigpending : ( -> int)
+ const reboot : (opt : int -> int)
+ const revoke : (path : byte# -> int)
+ const symlink : (path : byte#, link : byte# -> int)
+ const readlink : (path : byte#, buf : byte#, count : size -> size)
+ const umask : (newmask : filemode -> filemode)
+ const chroot : (path : byte# -> int)
+ const getfsstat : (buf : statfs#, bufsize : size, flags : int -> int)
+ const statfs : (path : byte#, buf : statfs# -> int)
+ const fstatfs : (fd : int, buf : statfs# -> int)
+ const fhstatfs : (fhp : fhandle#, buf : statfs# -> int)
+ const vfork : ( -> int)
+ const gettimeofday : (tp : timeval#, tzp : timezone# -> int)
+ const settimeofday : (tv : timeval#, tzp : timezone# -> int)
+ const setitimer : (which : int, itv : itimerval#, oitv : itimerval# -> int)
+ const getitimer : (which : int, itv : itimerval# -> int)
+ const select : (nd : int, _in : fdset#, ou : fdset#, ex : fdset#, tv : timeval# -> int)
+ const kevent : (fd : int, changelist : kevent#, nchanges : int, eventlist : kevent#, nevents : int, timeout : timespec# -> int)
+ const mprotect : (addr : void#, len : size, prot : int -> int)
+ const madvise : (addr : void#, len : size, behav : int -> int)
+ const utimes : (path : byte#, tptr : timeval# -> int)
+ const futimes : (fd : int, tptr : timeval# -> int)
+ const mincore : (addr : void#, len : size, vec : byte# -> int)
+ const getgroups : (gidsetsize : int, gidset : gid# -> int)
+ const setgroups : (gidsetsize : int, gidset : gid# -> int)
+ const getpgrp : ( -> int)
+ const setpgid : (pid : pid, pgid : pid -> int)
+ const futex : (f : uint32#, op : int, val : int, timeout : timespec#, g : uint32# -> int)
+ const utimensat : (fd : int, path : byte#, times : timespec#, flag : int -> int)
+ const futimens : (fd : int, times : timespec# -> int)
+ const kbind : (param : kbind#, psize : size, proc_cookie : int64 -> int)
+ const accept4 : (s : int, name : sockaddr#, anamelen : int32#, flags : int -> int)
+ const __thrsleep : (ident : void#, clock_id : clockid, tp : timespec#, lock : void#, abort : int# -> int)
+ const fsync : (fd : int -> int)
+ const setpriority : (which : int, who : id, prio : int -> int)
+ const getpriority : (which : int, who : id -> int)
+ const pipe2 : (fdp : int#, flags : int -> int)
+ const dup3 : (from : int, to : int, flags : int -> int)
+ const sigreturn : (sigcntxp : sigcontext# -> int)
+ const chflagsat : (fd : int, path : byte#, flags : uint, atflags : int -> int)
+ const pledge : (promises : byte#, execpromises : byte# -> int)
+ const ppoll : (fds : pollfd#, nfds : uint, ts : timespec#, mask : sigset# -> int)
+ const pselect : (nd : int, _in : fdset#, ou : fdset#, ex : fdset#, ts : timespec#, mask : sigset# -> int)
+ const sigsuspend : (mask : int -> int)
+ const sendsyslog : (buf : byte#, nbyte : size, flags : int -> int)
+ const thrkill : (tid : pid, signum : int, tcb : void# -> int)
+ const fchown : (fd : int, uid : uid, gid : gid -> int)
+ const fchmod : (fd : int, mode : filemode -> int)
+ const setreuid : (ruid : uid, euid : uid -> int)
+ const setregid : (rgid : gid, egid : gid -> int)
+ const rename : (from : byte#, to : byte# -> int)
+ const flock : (fd : int, how : int -> int)
+ const mkfifo : (path : byte#, mode : filemode -> int)
+ const sendto : (s : int, buf : void#, len : size, flags : int, to : sockaddr#, tolen : int32 -> size)
+ const shutdown : (s : int, how : int -> int)
+ const socketpair : (domain : int, kind : int, protocol : int, rsv : int# -> int)
+ const rmdir : (path : byte# -> int)
+ const adjtime : (delta : timeval#, olddelta : timeval# -> int)
+ const getlogin_r : (namebuf : byte#, namelen : uint -> int)
+ const setsid : ( -> int)
+ const quotactl : (path : byte#, cmd : int, uid : int, arg : byte# -> int)
+ const nfssvc : (flag : int, argp : void# -> int)
+ const getfh : (fname : byte#, fhp : fhandle# -> int)
+ const sysarch : (op : int, parms : void# -> int)
+ const setgid : (gid : gid -> int)
+ const setegid : (egid : gid -> int)
+ const seteuid : (euid : uid -> int)
+ const pathconf : (path : byte#, name : int -> int64)
+ const fpathconf : (fd : int, name : int -> int64)
+ const swapctl : (cmd : int, arg : void#, misc : int -> int)
+ const getrlimit : (which : int, rlp : rlimit# -> int)
+ const setrlimit : (which : int, rlp : rlimit# -> int)
+ const truncate : (path : byte#, pad : int, length : off -> int)
+ const ftruncate : (fd : int, pad : int, length : off -> int)
+ const mlock : (addr : void#, len : size -> int)
+ const munlock : (addr : void#, len : size -> int)
+ const getpgid : (pid : pid -> pid)
+ const utrace : (label : byte#, addr : void#, len : size -> int)
+ const semget : (key : key, nsems : int, semflg : int -> int)
+ const msgget : (key : key, msgflg : int -> int)
+ const msgsnd : (msqid : int, msgp : void#, msgsz : size, msgflg : int -> int)
+ const msgrcv : (msqid : int, msgp : void#, msgsz : size, msgtyp : int64, msgflg : int -> int)
+ const shmat : (shmid : int, shmaddr : void#, shmflg : int -> void)
+ const shmdt : (shmaddr : void# -> int)
+ const minherit : (addr : void#, len : size, inherit : int -> int)
+ const issetugid : ( -> int)
+ const lchown : (path : byte#, uid : uid, gid : gid -> int)
+ const getsid : (pid : pid -> pid)
+ const msync : (addr : void#, len : size, flags : int -> int)
+ const fhopen : (fhp : fhandle#, flags : int -> int)
+ const preadv : (fd : int, iovp : iovec#, iovcnt : int, pad : int, offset : off -> size)
+ const pwritev : (fd : int, iovp : iovec#, iovcnt : int, pad : int, offset : off -> size)
+ const kqueue : ( -> int)
+ const mlockall : (flags : int -> int)
+ const munlockall : ( -> int)
+ const getresuid : (ruid : uid#, euid : uid#, suid : uid# -> int)
+ const setresuid : (ruid : uid, euid : uid, suid : uid -> int)
+ const getresgid : (rgid : gid#, egid : gid#, sgid : gid# -> int)
+ const setresgid : (rgid : gid, egid : gid, sgid : gid -> int)
+ const mquery : (addr : void#, len : size, prot : int, flags : int, fd : int, pad : int64, pos : off -> void)
+ const closefrom : (fd : int -> int)
+ const sigaltstack : (nss : sigaltstack#, oss : sigaltstack# -> int)
+ const shmget : (key : key, size : size, shmflg : int -> int)
+ const semop : (semid : int, sops : sembuf#, nsops : size -> int)
+ const fhstat : (fhp : fhandle#, sb : statbuf# -> int)
+ const __semctl : (semid : int, semnum : int, cmd : int, arg : semun# -> int)
+ const shmctl : (shmid : int, cmd : int, buf : shmid_ds# -> int)
+ const msgctl : (msqid : int, cmd : int, buf : msqid_ds# -> int)
+ const sched_yield : ( -> int)
+ const getthrid : ( -> pid)
+ const __thrwakeup : (ident : void#, n : int -> int)
+ const __threxit : (notdead : pid# -> void)
+ const __thrsigdivert : (sigmask : sigset, info : siginfo#, timeout : timespec# -> int)
+ const adjfreq : (freq : int64#, oldfreq : int64# -> int)
+ const setrtable : (rtableid : int -> int)
+ const getrtable : ( -> int)
+ const faccessat : (fd : int, path : byte#, amode : int, flag : int -> int)
+ const fchmodat : (fd : int, path : byte#, mode : filemode, flag : int -> int)
+ const fchownat : (fd : int, path : byte#, uid : uid, gid : gid, flag : int -> int)
+ const linkat : (fd1 : int, path1 : byte#, fd2 : int, path2 : byte#, flag : int -> int)
+ const mkdirat : (fd : int, path : byte#, mode : filemode -> int)
+ const mkfifoat : (fd : int, path : byte#, mode : filemode -> int)
+ const mknodat : (fd : int, path : byte#, mode : filemode, dev : dev -> int)
+ const openat : (fd : int, path : byte#, flags : int, mode : filemode -> int)
+ const readlinkat : (fd : int, path : byte#, buf : byte#, count : size -> size)
+ const renameat : (fromfd : int, from : byte#, tofd : int, to : byte# -> int)
+ const symlinkat : (path : byte#, fd : int, link : byte# -> int)
+ const unlinkat : (fd : int, path : byte#, flag : int -> int)
+ const __set_tcb : (tcb : void# -> void)
+ const __get_tcb : ( -> void)
+;;
+
+ /* start manual overrides { */
+ /* process control */
+ /* wrappers to extract wait status */
+
+ /* fd manipulation */
+
+ /* signals */
+
+ /* fd stuff */
+ /* NB: the C ABI uses '...' for the args. */
+
+ /* networking */
+
+ /* memory mapping */
+
+ /* time - doublecheck if this is right */
+
+ /* system information */
+
+ /*
+ wraps a syscall argument, converting it to 64 bits for the syscall function. This is
+ the same as casting, but more concise than writing a cast to uint64
+ */
+ generic a = {x : @t; -> (x : uint64)}
+
+
+
+ /* process management */
+ const exit = {status; syscall(Sysexit, a(status))}
+ const getpid = {; -> (syscall(Sysgetpid, 1) : pid)}
+ const kill = {pid, sig; -> syscall(Syskill, pid, sig)}
+ const fork = {; -> (syscall(Sysfork) : pid)}
+ const wait4 = {pid, loc, opt, usage; -> syscall(Syswait4, pid, loc, opt, usage)}
+ const waitpid = {pid, loc, opt;
+ -> wait4(pid, loc, opt, (0 : rusage#))
+ }
+
+ const execv = {cmd, args
+ var p, cargs, i
+
+ /* of course we fucking have to duplicate this code everywhere,
+ * since we want to stack allocate... */
+ p = alloca((args.len + 1)*sizeof(byte#))
+ cargs = (p : byte##)[:args.len + 1]
+ for i = 0; i < args.len; i++
+ cargs[i] = cstring(args[i])
+ ;;
+ cargs[args.len] = (0 : byte#)
+ -> syscall(Sysexecve, cstring(cmd), a(p), a(__cenvp))
+ }
+
+ const execve = {cmd, args, env
+ var cargs, cenv, i
+ var p
+
+ /* copy the args */
+ p = alloca((args.len + 1)*sizeof(byte#))
+ cargs = (p : byte##)[:args.len]
+ for i = 0; i < args.len; i++
+ cargs[i] = cstring(args[i])
+ ;;
+ cargs[args.len] = (0 : byte#)
+
+ /*
+ copy the env.
+ of course we fucking have to duplicate this code everywhere,
+ since we want to stack allocate...
+ */
+ p = alloca((env.len + 1)*sizeof(byte#))
+ cenv = (p : byte##)[:env.len]
+ for i = 0; i < env.len; i++
+ cenv[i] = cstring(env[i])
+ ;;
+ cenv[env.len] = (0 : byte#)
+
+ -> syscall(Sysexecve, cstring(cmd), a(p), a(cenv))
+ }
+
+ /* fd manipulation */
+ const open = {path, opts; -> (syscall(Sysopen, cstring(path), a(opts), a(0o777)) : fd)}
+ const openmode = {path, opts, mode; -> (syscall(Sysopen, cstring(path), a(opts), a(mode)) : fd)}
+ const close = {fd; -> syscall(Sysclose, a(fd))}
+ const creat = {path, mode; -> (openmode(path, Ocreat | Otrunc | Owronly, mode) : fd)}
+ const unlink = {path; -> (syscall(Sysunlink, cstring(path)) : int)}
+ const read = {fd, buf; -> (syscall(Sysread, a(fd), (buf : byte#), a(buf.len)) : size)}
+ const pread = {fd, buf, off; -> (syscall(Syspread, a(fd), (buf : byte#), a(buf.len), a(off)) : size)}
+ const readv = {fd, vec; -> (syscall(Sysreadv, a(fd), (vec : iovec#), a(vec.len)) : size)}
+ const write = {fd, buf; -> (syscall(Syswrite, a(fd), (buf : byte#), a(buf.len)) : size)}
+ const pwrite = {fd, buf, off; -> (syscall(Syspwrite, a(fd), (buf : byte#), a(buf.len), a(off)) : size)}
+ const writev = {fd, vec; -> (syscall(Syswritev, a(fd), (vec : iovec#), a(vec.len)) : size)}
+ const lseek = {fd, off, whence; -> syscall(Syslseek, a(fd), a(off), a(whence))}
+ const stat = {path, sb; -> syscall(Sysstat, cstring(path), a(sb))}
+ const lstat = {path, sb; -> syscall(Syslstat, cstring(path), a(sb))}
+ const fstat = {fd, sb; -> syscall(Sysfstat, a(fd), a(sb))}
+ const mkdir = {path, mode; -> (syscall(Sysmkdir, cstring(path), a(mode)) : int64)}
+ generic ioctl = {fd, req, arg; -> (syscall(Sysioctl, a(fd), a(req), a(arg)) : int64)}
+ const chdir = {dir; -> syscall(Syschdir, cstring(dir))}
+ const __getcwd = {buf; -> syscall(Sys__getcwd, a(buf), a(buf.len))}
+ const getdents = {fd, buf; -> (syscall(Sysgetdents, a(fd), a(buf), a(buf.len)) : int64)}
+
+ /* signals */
+ const sigaction = {sig, act, oact; -> (syscall(Syssigaction, a(sig), a(act), a(oact)) : int)}
+ const sigprocmask = {sig, act, oact; -> (syscall(Syssigprocmask, a(sig), a(act), a(oact)) : int)}
+
+ /* file stuff */
+ const pipe = {fds; -> syscall(Syspipe, fds)}
+ const dup = {fd; -> (syscall(Sysdup, a(fd)) : fd)}
+ const dup2 = {src, dst; -> (syscall(Sysdup2, a(src), a(dst)) : fd)}
+ const fcntl = {fd, cmd, args; -> syscall(Sysfcntl, a(fd), a(cmd), a(args))}
+ const poll = {pfd, tm; -> (syscall(Syspoll, (pfd : byte#), a(pfd.len), a(tm)) : int)}
+
+ /* networking */
+ const socket = {dom, stype, proto; -> (syscall(Syssocket, a(dom), a(stype), a(proto)) : fd)}
+ const connect = {sock, addr, len; -> (syscall(Sysconnect, a(sock), a(addr), a(len)) : int)}
+ const accept = {sock, addr, len; -> (syscall(Sysaccept, a(sock), a(addr), a(len)) : fd)}
+ const listen = {sock, backlog; -> (syscall(Syslisten, a(sock), a(backlog)) : int)}
+ const bind = {sock, addr, len; -> (syscall(Sysbind, a(sock), a(addr), a(len)) : int)}
+ const setsockopt = {sock, lev, opt, val, len; -> (syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) : int)}
+ const getsockopt = {sock, lev, opt, val, len; -> (syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) : int)}
+
+ /* memory management */
+ const munmap = {addr, len; -> syscall(Sysmunmap, a(addr), a(len))}
+ const mmap = {addr, len, prot, flags, fd, off;
+ /* the actual syscall has padding on the offset arg */
+ -> (syscall(Sysmmap, a(addr), a(len), a(prot), a(flags), a(fd), a(0), a(off)) : byte#)
+ }
+
+ /* time */
+ const clock_getres = {clk, ts; -> (syscall(Sysclock_getres, clockid(clk), a(ts)) : int32)}
+ const clock_gettime = {clk, ts; -> (syscall(Sysclock_gettime, clockid(clk), a(ts)) : int32)}
+ const clock_settime = {clk, ts; -> (syscall(Sysclock_settime, clockid(clk), a(ts)) : int32)}
+
+ const sleep = {time
+ var req, rem
+ req = [.sec = time, .nsec = 0]
+ -> nanosleep(&req, &rem)
+ }
+
+ const nanosleep = {req, rem; -> (syscall(Sysnanosleep, a(req), a(rem)) : int32)}
+
+
+ /* system information */
+ const uname = {buf
+ var mib : int[2]
+ var ret
+ var sys, syssz
+ var nod, nodsz
+ var rel, relsz
+ var ver, versz
+ var mach, machsz
+
+ ret = 0
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 1 /* KERN_OSTYPE */
+ sys = (buf.system[:] : void#)
+ syssz = buf.system.len
+ ret = sysctl(mib[:], sys, &syssz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 10 /* KERN_HOSTNAME */
+ nod = (buf.node[:] : void#)
+ nodsz = buf.node.len
+ ret = sysctl(mib[:], nod, &nodsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 2 /* KERN_OSRELEASE */
+ rel = (buf.release[:] : void#)
+ relsz = buf.release.len
+ ret = sysctl(mib[:], rel, &relsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 27 /* KERN_OSVERSION */
+ ver = (buf.version[:] : void#)
+ versz = buf.version.len
+ ret = sysctl(mib[:], ver, &versz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 6 /* CTL_HW */
+ mib[1] = 1 /* HW_MACHINE */
+ mach = (buf.machine[:] : void#)
+ machsz = buf.machine.len
+ ret = sysctl(mib[:], mach, &machsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ -> 0
+ }
+
+ const sysctl = {mib, old, oldsz, new, newsz
+ /* all args already passed through a() or ar ptrs */
+ -> (syscall(Syssysctl, \
+ (mib : int#), a(mib.len), old, oldsz, new, newsz) : int)
+ }
+
+ const clockid = {clk
+ match clk
+ | `Clockrealtime: -> 0
+ | `Clockproccputime: -> 2
+ | `Clockmonotonic: -> 3
+ | `Clockthreadcputime: -> 4
+ | `Clockuptime: -> 5
+ ;;
+ -> -1
+ }
+
+ const waitstatus = {st
+ if st < 0
+ -> `Waitfail st
+ ;;
+ match st & 0o177
+ | 0: -> `Waitexit (st >> 8)
+ | 0x7f:-> `Waitstop (st >> 8)
+ | sig: -> `Waitsig sig
+ ;;
+ }
+
+ /* } end manual overrides */
+const getentropy = {buf, nbyte
+ -> (syscall(Sysgetentropy, a(buf), a(nbyte)) : int)
+}
+const __tfork = {param, psize
+ -> (syscall(Sys__tfork, a(param), a(psize)) : int)
+}
+const link = {path, link
+ -> (syscall(Syslink, a(path), a(link)) : int)
+}
+const fchdir = {fd
+ -> (syscall(Sysfchdir, a(fd)) : int)
+}
+const mknod = {path, mode, dev
+ -> (syscall(Sysmknod, a(path), a(mode), a(dev)) : int)
+}
+const chmod = {path, mode
+ -> (syscall(Syschmod, a(path), a(mode)) : int)
+}
+const chown = {path, uid, gid
+ -> (syscall(Syschown, a(path), a(uid), a(gid)) : int)
+}
+const obreak = {nsize
+ -> (syscall(Sysobreak, a(nsize)) : int)
+}
+const getdtablecount = {
+ -> (syscall(Sysgetdtablecount) : int)
+}
+const getrusage = {who, rusage
+ -> (syscall(Sysgetrusage, a(who), a(rusage)) : int)
+}
+const mount = {kind, path, flags, data
+ -> (syscall(Sysmount, a(kind), a(path), a(flags), a(data)) : int)
+}
+const unmount = {path, flags
+ -> (syscall(Sysunmount, a(path), a(flags)) : int)
+}
+const setuid = {uid
+ -> (syscall(Syssetuid, a(uid)) : int)
+}
+const getuid = {
+ -> (syscall(Sysgetuid) : uid)
+}
+const geteuid = {
+ -> (syscall(Sysgeteuid) : uid)
+}
+const ptrace = {req, pid, addr, data
+ -> (syscall(Sysptrace, a(req), a(pid), a(addr), a(data)) : int)
+}
+const recvmsg = {s, msg, flags
+ -> (syscall(Sysrecvmsg, a(s), a(msg), a(flags)) : size)
+}
+const sendmsg = {s, msg, flags
+ -> (syscall(Syssendmsg, a(s), a(msg), a(flags)) : size)
+}
+const recvfrom = {s, buf, len, flags, from, fromlenaddr
+ -> (syscall(Sysrecvfrom, a(s), a(buf), a(len), a(flags), a(from), a(fromlenaddr)) : size)
+}
+const getpeername = {fdes, asa, alen
+ -> (syscall(Sysgetpeername, a(fdes), a(asa), a(alen)) : int)
+}
+const getsockname = {fdes, asa, alen
+ -> (syscall(Sysgetsockname, a(fdes), a(asa), a(alen)) : int)
+}
+const access = {path, amode
+ -> (syscall(Sysaccess, a(path), a(amode)) : int)
+}
+const chflags = {path, flags
+ -> (syscall(Syschflags, a(path), a(flags)) : int)
+}
+const fchflags = {fd, flags
+ -> (syscall(Sysfchflags, a(fd), a(flags)) : int)
+}
+const sync = {
+ -> (syscall(Syssync) : void)
+}
+const getppid = {
+ -> (syscall(Sysgetppid) : pid)
+}
+const fstatat = {fd, path, buf, flag
+ -> (syscall(Sysfstatat, a(fd), a(path), a(buf), a(flag)) : int)
+}
+const getegid = {
+ -> (syscall(Sysgetegid) : gid)
+}
+const profil = {samples, size, offset, scale
+ -> (syscall(Sysprofil, a(samples), a(size), a(offset), a(scale)) : int)
+}
+const ktrace = {fname, ops, facs, pid
+ -> (syscall(Sysktrace, a(fname), a(ops), a(facs), a(pid)) : int)
+}
+const getgid = {
+ -> (syscall(Sysgetgid) : gid)
+}
+const setlogin = {namebuf
+ -> (syscall(Syssetlogin, a(namebuf)) : int)
+}
+const acct = {path
+ -> (syscall(Sysacct, a(path)) : int)
+}
+const sigpending = {
+ -> (syscall(Syssigpending) : int)
+}
+const reboot = {opt
+ -> (syscall(Sysreboot, a(opt)) : int)
+}
+const revoke = {path
+ -> (syscall(Sysrevoke, a(path)) : int)
+}
+const symlink = {path, link
+ -> (syscall(Syssymlink, a(path), a(link)) : int)
+}
+const readlink = {path, buf, count
+ -> (syscall(Sysreadlink, a(path), a(buf), a(count)) : size)
+}
+const umask = {newmask
+ -> (syscall(Sysumask, a(newmask)) : filemode)
+}
+const chroot = {path
+ -> (syscall(Syschroot, a(path)) : int)
+}
+const getfsstat = {buf, bufsize, flags
+ -> (syscall(Sysgetfsstat, a(buf), a(bufsize), a(flags)) : int)
+}
+const statfs = {path, buf
+ -> (syscall(Sysstatfs, a(path), a(buf)) : int)
+}
+const fstatfs = {fd, buf
+ -> (syscall(Sysfstatfs, a(fd), a(buf)) : int)
+}
+const fhstatfs = {fhp, buf
+ -> (syscall(Sysfhstatfs, a(fhp), a(buf)) : int)
+}
+const vfork = {
+ -> (syscall(Sysvfork) : int)
+}
+const gettimeofday = {tp, tzp
+ -> (syscall(Sysgettimeofday, a(tp), a(tzp)) : int)
+}
+const settimeofday = {tv, tzp
+ -> (syscall(Syssettimeofday, a(tv), a(tzp)) : int)
+}
+const setitimer = {which, itv, oitv
+ -> (syscall(Syssetitimer, a(which), a(itv), a(oitv)) : int)
+}
+const getitimer = {which, itv
+ -> (syscall(Sysgetitimer, a(which), a(itv)) : int)
+}
+const select = {nd, _in, ou, ex, tv
+ -> (syscall(Sysselect, a(nd), a(_in), a(ou), a(ex), a(tv)) : int)
+}
+const kevent = {fd, changelist, nchanges, eventlist, nevents, timeout
+ -> (syscall(Syskevent, a(fd), a(changelist), a(nchanges), a(eventlist), a(nevents), a(timeout)) : int)
+}
+const mprotect = {addr, len, prot
+ -> (syscall(Sysmprotect, a(addr), a(len), a(prot)) : int)
+}
+const madvise = {addr, len, behav
+ -> (syscall(Sysmadvise, a(addr), a(len), a(behav)) : int)
+}
+const utimes = {path, tptr
+ -> (syscall(Sysutimes, a(path), a(tptr)) : int)
+}
+const futimes = {fd, tptr
+ -> (syscall(Sysfutimes, a(fd), a(tptr)) : int)
+}
+const mincore = {addr, len, vec
+ -> (syscall(Sysmincore, a(addr), a(len), a(vec)) : int)
+}
+const getgroups = {gidsetsize, gidset
+ -> (syscall(Sysgetgroups, a(gidsetsize), a(gidset)) : int)
+}
+const setgroups = {gidsetsize, gidset
+ -> (syscall(Syssetgroups, a(gidsetsize), a(gidset)) : int)
+}
+const getpgrp = {
+ -> (syscall(Sysgetpgrp) : int)
+}
+const setpgid = {pid, pgid
+ -> (syscall(Syssetpgid, a(pid), a(pgid)) : int)
+}
+const futex = {f, op, val, timeout, g
+ -> (syscall(Sysfutex, a(f), a(op), a(val), a(timeout), a(g)) : int)
+}
+const utimensat = {fd, path, times, flag
+ -> (syscall(Sysutimensat, a(fd), a(path), a(times), a(flag)) : int)
+}
+const futimens = {fd, times
+ -> (syscall(Sysfutimens, a(fd), a(times)) : int)
+}
+const kbind = {param, psize, proc_cookie
+ -> (syscall(Syskbind, a(param), a(psize), a(proc_cookie)) : int)
+}
+const accept4 = {s, name, anamelen, flags
+ -> (syscall(Sysaccept4, a(s), a(name), a(anamelen), a(flags)) : int)
+}
+const __thrsleep = {ident, clock_id, tp, lock, abort
+ -> (syscall(Sys__thrsleep, a(ident), a(clock_id), a(tp), a(lock), a(abort)) : int)
+}
+const fsync = {fd
+ -> (syscall(Sysfsync, a(fd)) : int)
+}
+const setpriority = {which, who, prio
+ -> (syscall(Syssetpriority, a(which), a(who), a(prio)) : int)
+}
+const getpriority = {which, who
+ -> (syscall(Sysgetpriority, a(which), a(who)) : int)
+}
+const pipe2 = {fdp, flags
+ -> (syscall(Syspipe2, a(fdp), a(flags)) : int)
+}
+const dup3 = {from, to, flags
+ -> (syscall(Sysdup3, a(from), a(to), a(flags)) : int)
+}
+const sigreturn = {sigcntxp
+ -> (syscall(Syssigreturn, a(sigcntxp)) : int)
+}
+const chflagsat = {fd, path, flags, atflags
+ -> (syscall(Syschflagsat, a(fd), a(path), a(flags), a(atflags)) : int)
+}
+const pledge = {promises, execpromises
+ -> (syscall(Syspledge, a(promises), a(execpromises)) : int)
+}
+const ppoll = {fds, nfds, ts, mask
+ -> (syscall(Sysppoll, a(fds), a(nfds), a(ts), a(mask)) : int)
+}
+const pselect = {nd, _in, ou, ex, ts, mask
+ -> (syscall(Syspselect, a(nd), a(_in), a(ou), a(ex), a(ts), a(mask)) : int)
+}
+const sigsuspend = {mask
+ -> (syscall(Syssigsuspend, a(mask)) : int)
+}
+const sendsyslog = {buf, nbyte, flags
+ -> (syscall(Syssendsyslog, a(buf), a(nbyte), a(flags)) : int)
+}
+const thrkill = {tid, signum, tcb
+ -> (syscall(Systhrkill, a(tid), a(signum), a(tcb)) : int)
+}
+const fchown = {fd, uid, gid
+ -> (syscall(Sysfchown, a(fd), a(uid), a(gid)) : int)
+}
+const fchmod = {fd, mode
+ -> (syscall(Sysfchmod, a(fd), a(mode)) : int)
+}
+const setreuid = {ruid, euid
+ -> (syscall(Syssetreuid, a(ruid), a(euid)) : int)
+}
+const setregid = {rgid, egid
+ -> (syscall(Syssetregid, a(rgid), a(egid)) : int)
+}
+const rename = {from, to
+ -> (syscall(Sysrename, a(from), a(to)) : int)
+}
+const flock = {fd, how
+ -> (syscall(Sysflock, a(fd), a(how)) : int)
+}
+const mkfifo = {path, mode
+ -> (syscall(Sysmkfifo, a(path), a(mode)) : int)
+}
+const sendto = {s, buf, len, flags, to, tolen
+ -> (syscall(Syssendto, a(s), a(buf), a(len), a(flags), a(to), a(tolen)) : size)
+}
+const shutdown = {s, how
+ -> (syscall(Sysshutdown, a(s), a(how)) : int)
+}
+const socketpair = {domain, kind, protocol, rsv
+ -> (syscall(Syssocketpair, a(domain), a(kind), a(protocol), a(rsv)) : int)
+}
+const rmdir = {path
+ -> (syscall(Sysrmdir, a(path)) : int)
+}
+const adjtime = {delta, olddelta
+ -> (syscall(Sysadjtime, a(delta), a(olddelta)) : int)
+}
+const getlogin_r = {namebuf, namelen
+ -> (syscall(Sysgetlogin_r, a(namebuf), a(namelen)) : int)
+}
+const setsid = {
+ -> (syscall(Syssetsid) : int)
+}
+const quotactl = {path, cmd, uid, arg
+ -> (syscall(Sysquotactl, a(path), a(cmd), a(uid), a(arg)) : int)
+}
+const nfssvc = {flag, argp
+ -> (syscall(Sysnfssvc, a(flag), a(argp)) : int)
+}
+const getfh = {fname, fhp
+ -> (syscall(Sysgetfh, a(fname), a(fhp)) : int)
+}
+const sysarch = {op, parms
+ -> (syscall(Syssysarch, a(op), a(parms)) : int)
+}
+const setgid = {gid
+ -> (syscall(Syssetgid, a(gid)) : int)
+}
+const setegid = {egid
+ -> (syscall(Syssetegid, a(egid)) : int)
+}
+const seteuid = {euid
+ -> (syscall(Sysseteuid, a(euid)) : int)
+}
+const pathconf = {path, name
+ -> (syscall(Syspathconf, a(path), a(name)) : int64)
+}
+const fpathconf = {fd, name
+ -> (syscall(Sysfpathconf, a(fd), a(name)) : int64)
+}
+const swapctl = {cmd, arg, misc
+ -> (syscall(Sysswapctl, a(cmd), a(arg), a(misc)) : int)
+}
+const getrlimit = {which, rlp
+ -> (syscall(Sysgetrlimit, a(which), a(rlp)) : int)
+}
+const setrlimit = {which, rlp
+ -> (syscall(Syssetrlimit, a(which), a(rlp)) : int)
+}
+const truncate = {path, pad, length
+ -> (syscall(Systruncate, a(path), a(pad), a(length)) : int)
+}
+const ftruncate = {fd, pad, length
+ -> (syscall(Sysftruncate, a(fd), a(pad), a(length)) : int)
+}
+const mlock = {addr, len
+ -> (syscall(Sysmlock, a(addr), a(len)) : int)
+}
+const munlock = {addr, len
+ -> (syscall(Sysmunlock, a(addr), a(len)) : int)
+}
+const getpgid = {pid
+ -> (syscall(Sysgetpgid, a(pid)) : pid)
+}
+const utrace = {label, addr, len
+ -> (syscall(Sysutrace, a(label), a(addr), a(len)) : int)
+}
+const semget = {key, nsems, semflg
+ -> (syscall(Syssemget, a(key), a(nsems), a(semflg)) : int)
+}
+const msgget = {key, msgflg
+ -> (syscall(Sysmsgget, a(key), a(msgflg)) : int)
+}
+const msgsnd = {msqid, msgp, msgsz, msgflg
+ -> (syscall(Sysmsgsnd, a(msqid), a(msgp), a(msgsz), a(msgflg)) : int)
+}
+const msgrcv = {msqid, msgp, msgsz, msgtyp, msgflg
+ -> (syscall(Sysmsgrcv, a(msqid), a(msgp), a(msgsz), a(msgtyp), a(msgflg)) : int)
+}
+const shmat = {shmid, shmaddr, shmflg
+ -> (syscall(Sysshmat, a(shmid), a(shmaddr), a(shmflg)) : void)
+}
+const shmdt = {shmaddr
+ -> (syscall(Sysshmdt, a(shmaddr)) : int)
+}
+const minherit = {addr, len, inherit
+ -> (syscall(Sysminherit, a(addr), a(len), a(inherit)) : int)
+}
+const issetugid = {
+ -> (syscall(Sysissetugid) : int)
+}
+const lchown = {path, uid, gid
+ -> (syscall(Syslchown, a(path), a(uid), a(gid)) : int)
+}
+const getsid = {pid
+ -> (syscall(Sysgetsid, a(pid)) : pid)
+}
+const msync = {addr, len, flags
+ -> (syscall(Sysmsync, a(addr), a(len), a(flags)) : int)
+}
+const fhopen = {fhp, flags
+ -> (syscall(Sysfhopen, a(fhp), a(flags)) : int)
+}
+const preadv = {fd, iovp, iovcnt, pad, offset
+ -> (syscall(Syspreadv, a(fd), a(iovp), a(iovcnt), a(pad), a(offset)) : size)
+}
+const pwritev = {fd, iovp, iovcnt, pad, offset
+ -> (syscall(Syspwritev, a(fd), a(iovp), a(iovcnt), a(pad), a(offset)) : size)
+}
+const kqueue = {
+ -> (syscall(Syskqueue) : int)
+}
+const mlockall = {flags
+ -> (syscall(Sysmlockall, a(flags)) : int)
+}
+const munlockall = {
+ -> (syscall(Sysmunlockall) : int)
+}
+const getresuid = {ruid, euid, suid
+ -> (syscall(Sysgetresuid, a(ruid), a(euid), a(suid)) : int)
+}
+const setresuid = {ruid, euid, suid
+ -> (syscall(Syssetresuid, a(ruid), a(euid), a(suid)) : int)
+}
+const getresgid = {rgid, egid, sgid
+ -> (syscall(Sysgetresgid, a(rgid), a(egid), a(sgid)) : int)
+}
+const setresgid = {rgid, egid, sgid
+ -> (syscall(Syssetresgid, a(rgid), a(egid), a(sgid)) : int)
+}
+const mquery = {addr, len, prot, flags, fd, pad, pos
+ -> (syscall(Sysmquery, a(addr), a(len), a(prot), a(flags), a(fd), a(pad), a(pos)) : void)
+}
+const closefrom = {fd
+ -> (syscall(Sysclosefrom, a(fd)) : int)
+}
+const sigaltstack = {nss, oss
+ -> (syscall(Syssigaltstack, a(nss), a(oss)) : int)
+}
+const shmget = {key, size, shmflg
+ -> (syscall(Sysshmget, a(key), a(size), a(shmflg)) : int)
+}
+const semop = {semid, sops, nsops
+ -> (syscall(Syssemop, a(semid), a(sops), a(nsops)) : int)
+}
+const fhstat = {fhp, sb
+ -> (syscall(Sysfhstat, a(fhp), a(sb)) : int)
+}
+const __semctl = {semid, semnum, cmd, arg
+ -> (syscall(Sys__semctl, a(semid), a(semnum), a(cmd), a(arg)) : int)
+}
+const shmctl = {shmid, cmd, buf
+ -> (syscall(Sysshmctl, a(shmid), a(cmd), a(buf)) : int)
+}
+const msgctl = {msqid, cmd, buf
+ -> (syscall(Sysmsgctl, a(msqid), a(cmd), a(buf)) : int)
+}
+const sched_yield = {
+ -> (syscall(Syssched_yield) : int)
+}
+const getthrid = {
+ -> (syscall(Sysgetthrid) : pid)
+}
+const __thrwakeup = {ident, n
+ -> (syscall(Sys__thrwakeup, a(ident), a(n)) : int)
+}
+const __threxit = {notdead
+ -> (syscall(Sys__threxit, a(notdead)) : void)
+}
+const __thrsigdivert = {sigmask, info, timeout
+ -> (syscall(Sys__thrsigdivert, a(sigmask), a(info), a(timeout)) : int)
+}
+const adjfreq = {freq, oldfreq
+ -> (syscall(Sysadjfreq, a(freq), a(oldfreq)) : int)
+}
+const setrtable = {rtableid
+ -> (syscall(Syssetrtable, a(rtableid)) : int)
+}
+const getrtable = {
+ -> (syscall(Sysgetrtable) : int)
+}
+const faccessat = {fd, path, amode, flag
+ -> (syscall(Sysfaccessat, a(fd), a(path), a(amode), a(flag)) : int)
+}
+const fchmodat = {fd, path, mode, flag
+ -> (syscall(Sysfchmodat, a(fd), a(path), a(mode), a(flag)) : int)
+}
+const fchownat = {fd, path, uid, gid, flag
+ -> (syscall(Sysfchownat, a(fd), a(path), a(uid), a(gid), a(flag)) : int)
+}
+const linkat = {fd1, path1, fd2, path2, flag
+ -> (syscall(Syslinkat, a(fd1), a(path1), a(fd2), a(path2), a(flag)) : int)
+}
+const mkdirat = {fd, path, mode
+ -> (syscall(Sysmkdirat, a(fd), a(path), a(mode)) : int)
+}
+const mkfifoat = {fd, path, mode
+ -> (syscall(Sysmkfifoat, a(fd), a(path), a(mode)) : int)
+}
+const mknodat = {fd, path, mode, dev
+ -> (syscall(Sysmknodat, a(fd), a(path), a(mode), a(dev)) : int)
+}
+const openat = {fd, path, flags, mode
+ -> (syscall(Sysopenat, a(fd), a(path), a(flags), a(mode)) : int)
+}
+const readlinkat = {fd, path, buf, count
+ -> (syscall(Sysreadlinkat, a(fd), a(path), a(buf), a(count)) : size)
+}
+const renameat = {fromfd, from, tofd, to
+ -> (syscall(Sysrenameat, a(fromfd), a(from), a(tofd), a(to)) : int)
+}
+const symlinkat = {path, fd, link
+ -> (syscall(Syssymlinkat, a(path), a(fd), a(link)) : int)
+}
+const unlinkat = {fd, path, flag
+ -> (syscall(Sysunlinkat, a(fd), a(path), a(flag)) : int)
+}
+const __set_tcb = {tcb
+ -> (syscall(Sys__set_tcb, a(tcb)) : void)
+}
+const __get_tcb = {
+ -> (syscall(Sys__get_tcb) : void)
+}
diff --git a/lib/testr/testr.myr b/lib/testr/testr.myr
index bbb99fe..9d8c55f 100644
--- a/lib/testr/testr.myr
+++ b/lib/testr/testr.myr
@@ -149,21 +149,21 @@ const benchspec = {ts, sub
const testspec = {ts, sub
var ctx : ctx
- var dorun, jmpbuf
+ var jmpbuf
ctx.ok = true
ctx.reason = ""
ctx.jmpbuf = &jmpbuf
- dorun = matchtest(ts.name, sub)
+ if !matchtest(ts.name, sub)
+ -> void
+ ;;
std.put("test {} <<{{!\n", ts.name)
- if !std.setjmp(&jmpbuf) && dorun
+ if !std.setjmp(&jmpbuf)
ts.fn(&ctx)
;;
- if !dorun
- std.put("!}}>> skip filtered\n")
- elif ctx.ok
+ if ctx.ok
std.put("!}}>> ok\n")
else
std.put("!}}>> fail {}\n", ctx.reason)
diff --git a/lib/thread/spawn+openbsd.myr b/lib/thread/spawn+openbsd.myr
index 1cdf230..c925349 100644
--- a/lib/thread/spawn+openbsd.myr
+++ b/lib/thread/spawn+openbsd.myr
@@ -53,7 +53,7 @@ const spawnstk = {fn, sz
const getstk = {sz
var p, m
- p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0)
+ p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon | sys.Mstack, -1, 0)
if p == sys.Mapbad
-> p
;;
diff --git a/mbld/bld.sub b/mbld/bld.sub
index 7374bb3..7e9bda3 100644
--- a/mbld/bld.sub
+++ b/mbld/bld.sub
@@ -1,6 +1,7 @@
bin mbld =
build.myr
- cpufeatures+x64.s
+ cpufeatures+posixy-x64.s
+ cpufeatures+plan9-x64.s
deps.myr
libs.myr
install.myr
diff --git a/mbld/cpufeatures+plan9-x64.s b/mbld/cpufeatures+plan9-x64.s
new file mode 100644
index 0000000..645d01a
--- /dev/null
+++ b/mbld/cpufeatures+plan9-x64.s
@@ -0,0 +1,8 @@
+TEXT bld$cpufeatures+0(SB),$0
+ MOVL $0x1,AX
+ CPUID
+ MOVL CX, AX
+ MOVL DX, DX
+ ROLQ $32, DX
+ ORQ DX, AX
+ RET
diff --git a/mbld/cpufeatures+x64.s b/mbld/cpufeatures+posixy-x64.s
index 8202ca1..889c6f1 100644
--- a/mbld/cpufeatures+x64.s
+++ b/mbld/cpufeatures+posixy-x64.s
@@ -1,7 +1,7 @@
.globl bld$cpufeatures
-.globl bld$_cpufeatures
+.globl _bld$cpufeatures
bld$cpufeatures:
-bld$_cpufeatures:
+_bld$cpufeatures:
mov $0x1, %eax
cpuid
mov %ecx, %eax
diff --git a/mbld/deps.myr b/mbld/deps.myr
index 51bddb0..53b5a8f 100644
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -333,7 +333,6 @@ const addalt = {b, mt, kind, f
std.slpush(&libs, d)
;;
myrcmd(b, n, mt, sp, true)
- std.slfree(mt.incpath)
n = node(g, tp)
generates(g, n, tp)
@@ -484,6 +483,7 @@ const myrcmd = {b, n, mt, src, istest
pushopt(&n.cmd, "-I", inc)
;;
if istest
+ std.slpush(&n.cmd, "-T")
for (dir, _, _) : mt.tstdeps
pushopt(&n.cmd, "-I", std.pathcat(opt_objdir, dir))
;;
diff --git a/mbld/test.myr b/mbld/test.myr
index 4d4b2ed..bf666fd 100644
--- a/mbld/test.myr
+++ b/mbld/test.myr
@@ -28,21 +28,11 @@ const go = {b, targs, kind, isbench
if !buildtarg(b, kind)
std.exit(1)
;;
- if targs.len == 0
- tests = std.htgetv(b.deps.targs, kind, [][:])
- else
- tests = [][:]
- for t : targs
- match std.htget(b.deps.targs, t)
- | `std.Some tl: std.sljoin(&tests, tl)
- | `std.None: std.fatal("unknown test {}\n", t)
- ;;
- ;;
- ;;
+ tests = std.htgetv(b.deps.targs, kind, [][:])
ok = true
failed = [][:]
for t : tests
- if !runtest(b, t, isbench, &failed)
+ if !runtest(b, t, targs, isbench, &failed)
ok = false
;;
;;
@@ -71,14 +61,30 @@ const printfailed = {failed
;;
}
-const runtest = {b, n, isbench, failed
+const runtest = {b, n, targs, isbench, failed
var dir, res, log, logfd
- var sub
+ var sub, found
+ if targs.len > 0
+ found = false
+ for t : targs
+ found = found || matchtest(n.lbl, t)
+ ;;
+ if !found
+ -> true
+ ;;
+ ;;
mbldput("run {}: ", n.lbl)
dir = std.pathcat(b.basedir, n.wdir)
std.chdir(dir)
std.slfree(dir)
+
+ if targs.len > 0
+ match std.strfind(targs[0], ":")
+ | `std.Some i: std.setenv("MTEST_SUBSET", targs[0][i+1:])
+ | `std.None: /* ok */
+ ;;
+ ;;
match std.spork(n.cmd)
| `std.Err m:
std.fatal("\nunable to run test: {}\n", m)
@@ -116,3 +122,9 @@ const runtest = {b, n, isbench, failed
-> res
}
+const matchtest = {name, pat
+ match std.strfind(pat, ":")
+ | `std.Some i: -> std.strhas(name, pat[:i])
+ | `std.None: -> std.strhas(name, pat)
+ ;;
+}
diff --git a/mk/bootstrap/bootstrap+Darwin-x86_64.sh b/mk/bootstrap/bootstrap+Darwin-x86_64.sh
index ae2dbce..220420d 100755
--- a/mk/bootstrap/bootstrap+Darwin-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Darwin-x86_64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr
- as -g -o mbld/cpufeatures.o mbld/cpufeatures+x64.s
+ as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s
as -g -o lib/thread/start.o lib/thread/start+osx-x64.s
as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s
as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s
diff --git a/mk/bootstrap/bootstrap+FreeBSD-amd64.sh b/mk/bootstrap/bootstrap+FreeBSD-amd64.sh
index 63c27dc..fe149c9 100755
--- a/mk/bootstrap/bootstrap+FreeBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+FreeBSD-amd64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr
- as -g -o mbld/cpufeatures.o mbld/cpufeatures+x64.s
+ as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s
as -g -o lib/thread/exit.o lib/thread/exit+freebsd-x64.s
as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s
as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s
diff --git a/mk/bootstrap/bootstrap+Linux-x86_64.sh b/mk/bootstrap/bootstrap+Linux-x86_64.sh
index 91c5c38..c27e044 100755
--- a/mk/bootstrap/bootstrap+Linux-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Linux-x86_64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr
- as -g -o mbld/cpufeatures.o mbld/cpufeatures+x64.s
+ as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s
as -g -o lib/thread/exit.o lib/thread/exit+linux-x64.s
as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s
as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s
diff --git a/mk/bootstrap/bootstrap+NetBSD-amd64.sh b/mk/bootstrap/bootstrap+NetBSD-amd64.sh
index 54d79c4..e089748 100755
--- a/mk/bootstrap/bootstrap+NetBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+NetBSD-amd64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr
- as -g -o mbld/cpufeatures.o mbld/cpufeatures+x64.s
+ as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s
as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s
as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s
$pwd/6/6m -I . -I lib/sys lib/std/option.myr
diff --git a/mk/bootstrap/bootstrap+OpenBSD-amd64.sh b/mk/bootstrap/bootstrap+OpenBSD-amd64.sh
index ecda364..bcd0b7d 100755
--- a/mk/bootstrap/bootstrap+OpenBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+OpenBSD-amd64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr
- as -g -o mbld/cpufeatures.o mbld/cpufeatures+x64.s
+ as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s
as -g -o lib/thread/exit.o lib/thread/exit+openbsd-x64.s
as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s
as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s
@@ -142,5 +142,5 @@ set -x
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/test.myr
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/deps.myr
$pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/main.myr
- ld -nopie --gc-sections -o mbld/mbld $pwd/rt/_myrrt.o mbld/deps.o mbld/main.o mbld/util.o mbld/cpufeatures+x64.s mbld/libs.o mbld/syssel.o mbld/config.o mbld/opts.o mbld/subtest.o mbld/types.o mbld/test.o mbld/install.o mbld/parse.o mbld/build.o -Llib/thread -lthread -Llib/bio -lbio -Llib/regex -lregex -Llib/std -lstd -Llib/sys -lsys
+ ld -nopie --gc-sections -o mbld/mbld $pwd/rt/_myrrt.o mbld/deps.o mbld/main.o mbld/util.o mbld/cpufeatures.o mbld/libs.o mbld/syssel.o mbld/config.o mbld/opts.o mbld/subtest.o mbld/types.o mbld/test.o mbld/install.o mbld/parse.o mbld/build.o -Llib/thread -lthread -Llib/bio -lbio -Llib/regex -lregex -Llib/std -lstd -Llib/sys -lsys
true
diff --git a/mk/bootstrap/bootstrap+Plan9-amd64.sh b/mk/bootstrap/bootstrap+Plan9-amd64.sh
index 8b45e53..cce2b4c 100755
--- a/mk/bootstrap/bootstrap+Plan9-amd64.sh
+++ b/mk/bootstrap/bootstrap+Plan9-amd64.sh
@@ -4,7 +4,7 @@
pwd=`pwd`
set -x
$pwd/6/6.out -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config+plan9-x64.myr
- 6a -o mbld/cpufeatures.6 mbld/cpufeatures+x64.s
+ 6a -o mbld/cpufeatures.6 mbld/cpufeatures+plan9-x64.s
6a -o lib/thread/atomic-impl.6 lib/thread/atomic-impl+plan9-x64.s
6a -o lib/std/getbp.6 lib/std/getbp+plan9-x64.s
$pwd/6/6.out -I lib/sys lib/std/errno+plan9.myr
diff --git a/parse/infer.c b/parse/infer.c
index bb1ea59..58399b0 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -29,6 +29,7 @@ struct Traitmap {
size_t nfiltertr;
};
+int allowhidden;
static void infernode(Node **np, Type *ret, int *sawret);
static void inferexpr(Node **np, Type *ret, int *sawret);
@@ -69,6 +70,8 @@ static size_t nspecializations;
static Stab **specializationscope;
static size_t nspecializationscope;
static Traitmap *traitmap;
+static Bitset *tytraits[Ntypes];
+
static void
ctxstrcall(char *buf, size_t sz, Node *n)
@@ -685,7 +688,7 @@ mktylike(Srcloc l, Ty other)
t = mktyvar(l);
/* not perfect in general, but good enough for all places mktylike is used. */
- t->trneed = bsdup(traitmap->sub[other]->traits);
+ t->trneed = bsdup(tytraits[other]);
return t;
}
@@ -958,7 +961,7 @@ static void
verifytraits(Node *ctx, Type *a, Type *b)
{
char traitbuf[64], abuf[64], bbuf[64];
- char asrc[64], bsrc[64];
+ char asrc[128], bsrc[128];
Bitset *abs, *bbs;
size_t i, n;
Srcloc l;
@@ -979,10 +982,11 @@ verifytraits(Node *ctx, Type *a, Type *b)
n = 0;
*traitbuf = 0;
for (i = 0; bsiter(abs, &i); i++) {
- if (!bshas(bbs, i))
+ if (!bshas(bbs, i)) {
n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep,
- namestr(traittab[i]->name));
- sep = ",";
+ namestr(traittab[i]->name));
+ sep = ",";
+ }
}
tyfmt(abuf, sizeof abuf, a);
tyfmt(bbuf, sizeof bbuf, b);
@@ -1320,7 +1324,7 @@ initvar(Node *n, Node *s)
Type *t, *param;
Tysubst *subst;
- if (s->decl.ishidden)
+ if (s->decl.ishidden && !allowhidden)
fatal(n, "attempting to refer to hidden decl %s", ctxstr(n));
param = n->expr.param;
@@ -2787,41 +2791,47 @@ builtintraits(void)
/* char::(numeric,integral) */
for (i = 0; i < Ntypes; i++)
- traitmap->sub[i] = mktraitmap();
+ tytraits[i] = mkbs();
- bsput(traitmap->sub[Tychar]->traits, Tcnum);
- bsput(traitmap->sub[Tychar]->traits, Tcint);
+ bsput(tytraits[Tychar], Tcnum);
+ bsput(tytraits[Tychar], Tcint);
- bsput(traitmap->sub[Tybyte]->traits, Tcnum);
- bsput(traitmap->sub[Tybyte]->traits, Tcint);
+ bsput(tytraits[Tybyte], Tcnum);
+ bsput(tytraits[Tybyte], Tcint);
/* <integer types>::(numeric,integral) */
for (i = Tyint8; i < Tyflt32; i++) {
- bsput(traitmap->sub[i]->traits, Tcnum);
- bsput(traitmap->sub[i]->traits, Tcint);
+ bsput(tytraits[i], Tcnum);
+ bsput(tytraits[i], Tcint);
}
/* <floats>::(numeric,floating) */
- bsput(traitmap->sub[Tyflt32]->traits, Tcnum);
- bsput(traitmap->sub[Tyflt32]->traits, Tcflt);
- bsput(traitmap->sub[Tyflt64]->traits, Tcnum);
- bsput(traitmap->sub[Tyflt64]->traits, Tcflt);
+ bsput(tytraits[Tyflt32], Tcnum);
+ bsput(tytraits[Tyflt32], Tcflt);
+ bsput(tytraits[Tyflt64], Tcnum);
+ bsput(tytraits[Tyflt64], Tcflt);
/* @a*::(sliceable) */
- bsput(traitmap->sub[Typtr]->traits, Tcslice);
+ bsput(tytraits[Typtr], Tcslice);
/* @a[:]::(indexable,sliceable) */
- bsput(traitmap->sub[Tyslice]->traits, Tcidx);
- bsput(traitmap->sub[Tyslice]->traits, Tcslice);
- bsput(traitmap->sub[Tyslice]->traits, Tciter);
+ bsput(tytraits[Tyslice], Tcidx);
+ bsput(tytraits[Tyslice], Tcslice);
+ bsput(tytraits[Tyslice], Tciter);
/* @a[SZ]::(indexable,sliceable) */
- bsput(traitmap->sub[Tyarray]->traits, Tcidx);
- bsput(traitmap->sub[Tyarray]->traits, Tcslice);
- bsput(traitmap->sub[Tyarray]->traits, Tciter);
+ bsput(tytraits[Tyarray], Tcidx);
+ bsput(tytraits[Tyarray], Tcslice);
+ bsput(tytraits[Tyarray], Tciter);
/* @a::function */
- bsput(traitmap->sub[Tyfunc]->traits, Tcfunc);
+ bsput(tytraits[Tyfunc], Tcfunc);
+
+ for (i = 0; i < Ntypes; i++) {
+ traitmap->sub[i] = mktraitmap();
+ bsunion(traitmap->sub[i]->traits, tytraits[i]);
+ }
+
}
static Trait*
diff --git a/parse/parse.h b/parse/parse.h
index 11b28ac..62392ca 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -378,6 +378,7 @@ extern Node **nodes; /* node id -> node map */
extern size_t ndecls;
extern Node **exportimpls;
extern size_t nexportimpls;
+extern int allowhidden;
/* property tables */
extern int opispure[];
diff --git a/parse/stab.c b/parse/stab.c
index 7e1b8c0..0319d13 100644
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -663,13 +663,17 @@ bindtype_rec(Tyenv *e, Type *t, Bitset *visited)
switch (t->type) {
case Typaram:
tt = htget(e->tab, t);
- if (tt && tt != t)
+ if (tt && tt != t) {
tytab[t->tid] = tt;
- else if (!boundtype(t))
+ for (i = 0; i < t->nspec; i++)
+ lappend(&tt->spec, &tt->nspec, t->spec[i]);
+ } else if (!boundtype(t)) {
htput(e->tab, t, t);
- for (i = 0; i < t->nspec; i++)
+ }
+ for (i = 0; i < t->nspec; i++) {
if (t->spec[i]->aux)
bindtype_rec(e, t->spec[i]->aux, visited);
+ }
break;
case Tygeneric:
for (i = 0; i < t->ngparam; i++)
diff --git a/support/syscall-gen/gensys.sh b/support/syscall-gen/gensys.sh
index c703642..51415a4 100755
--- a/support/syscall-gen/gensys.sh
+++ b/support/syscall-gen/gensys.sh
@@ -37,7 +37,7 @@ hdrgen() {
' < syscalls+$1.h | tee sysjoined.txt | awk -f gencalls.awk $1 $2 > sys+$1-$2.myr
}
-rm -f have.txt want.txt gentypes+$1-$2.frag
+#rm -f have.txt want.txt gentypes+$1-$2.frag
touch have.txt
if [ `uname` = Linux ]; then
diff --git a/support/syscall-gen/gentypes+openbsd:6.3-x64.frag b/support/syscall-gen/gentypes+openbsd:6.3-x64.frag
new file mode 100644
index 0000000..00f9cd1
--- /dev/null
+++ b/support/syscall-gen/gentypes+openbsd:6.3-x64.frag
@@ -0,0 +1,119 @@
+type dev = int32
+type uid = uint32
+type fd_mask = uint32
+type uintptr = uint64
+type clockid = int32
+type id = uint32
+type key = int64
+type shmatt = int16
+
+type tfork = struct
+ tcb : void#
+ tid : pid#
+ stack : void#
+
+;;
+
+type msghdr = struct
+ name : void#
+ namelen : int32
+ iov : iovec#
+ iovlen : uint
+ control : void#
+ controllen : int32
+ flags : int
+
+;;
+
+type fsid = struct
+ val : int32[2]
+
+;;
+
+type fid = struct
+ len : uint16
+ reserved : uint16
+ data : byte[16]
+
+;;
+
+type fhandle = struct
+ fsid : fsid
+ fid : fid
+
+;;
+
+type fdset = struct
+ bits : fd_mask[32]
+
+;;
+
+type kevent = struct
+ ident : uintptr
+ filter : int16
+ flags : uint16
+ fflags : uint
+ data : int64
+ udata : void#
+
+;;
+
+type kbind = struct
+ addr : void#
+ size : size
+
+;;
+
+type sembuf = struct
+ num : uint16
+ op : int16
+ flg : int16
+
+;;
+
+type ipc_perm = struct
+ cuid : uid
+ cgid : gid
+ uid : uid
+ gid : gid
+ mode : filemode
+ seq : uint16
+ key : key
+
+;;
+
+type shmid_ds = struct
+ perm : ipc_perm
+ segsz : int
+ lpid : pid
+ cpid : pid
+ nattch : shmatt
+ atime : time
+ atimensec : int64
+ dtime : time
+ dtimensec : int64
+ ctime : time
+ ctimensec : int64
+ internal : void#
+
+;;
+
+type msqid_ds = struct
+ perm : ipc_perm
+ first : msg#
+ last : msg#
+ cbytes : uint64
+ qnum : uint64
+ qbytes : uint64
+ lspid : pid
+ lrpid : pid
+ stime : time
+ pad1 : int64
+ rtime : time
+ pad2 : int64
+ ctime : time
+ pad3 : int64
+ pad4 : int64[4]
+
+;;
+
diff --git a/support/syscall-gen/specials+openbsd:6.3-x64.frag b/support/syscall-gen/specials+openbsd:6.3-x64.frag
new file mode 100644
index 0000000..4cc3843
--- /dev/null
+++ b/support/syscall-gen/specials+openbsd:6.3-x64.frag
@@ -0,0 +1,286 @@
+/* process control */
+const exit : (status:int -> void)
+const getpid : ( -> pid)
+const kill : (pid:pid, sig:int64 -> int64)
+const fork : (-> pid)
+const wait4 : (pid:pid, loc:int32#, opt : int64, usage:rusage# -> int64)
+const waitpid : (pid:pid, loc:int32#, opt : int64 -> int64)
+const execv : (cmd : byte[:], args : byte[:][:] -> int64)
+const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
+/* wrappers to extract wait status */
+const waitstatus : (st : int32 -> waitstatus)
+extern const __tfork_thread : (tfp : tforkparams#, sz : size, fn : void#, arg : void# -> pid)
+
+/* fd manipulation */
+const open : (path:byte[:], opts:fdopt -> fd)
+const openmode : (path:byte[:], opts:fdopt, mode:int64 -> fd)
+const close : (fd:fd -> int64)
+const creat : (path:byte[:], mode:int64 -> fd)
+const unlink : (path:byte[:] -> int)
+const read : (fd:fd, buf:byte[:] -> size)
+const pread : (fd:fd, buf:byte[:], off : off -> size)
+const readv : (fd:fd, iov:iovec[:] -> size)
+const write : (fd:fd, buf:byte[:] -> size)
+const pwrite : (fd:fd, buf:byte[:], off : off -> size)
+const writev : (fd:fd, iov:iovec[:] -> size)
+const lseek : (fd:fd, off : off, whence : whence -> int64)
+const stat : (path:byte[:], sb:statbuf# -> int64)
+const lstat : (path:byte[:], sb:statbuf# -> int64)
+const fstat : (fd:fd, sb:statbuf# -> int64)
+const mkdir : (path : byte[:], mode : int64 -> int64)
+generic ioctl : (fd:fd, req : int64, arg:@a# -> int64)
+const getdents : (fd : fd, buf : byte[:] -> int64)
+const chdir : (p : byte[:] -> int64)
+const __getcwd : (buf : byte[:] -> int64)
+const poll : (pfd : pollfd[:], tm : int -> int)
+
+/* signals */
+const sigaction : (sig : signo, act : sigaction#, oact : sigaction# -> int)
+const sigprocmask : (how : int32, set : sigset#, oset : sigset# -> int)
+
+/* fd stuff */
+const pipe : (fds : fd[2]# -> int64)
+const dup : (fd : fd -> fd)
+const dup2 : (src : fd, dst : fd -> fd)
+/* NB: the C ABI uses '...' for the args. */
+const fcntl : (fd : fd, cmd : fcntlcmd, args : byte# -> int64)
+
+/* networking */
+const socket : (dom : sockfam, stype : socktype, proto : sockproto -> fd)
+const connect : (sock : fd, addr : sockaddr#, len : size -> int)
+const accept : (sock : fd, addr : sockaddr#, len : size# -> fd)
+const listen : (sock : fd, backlog : int -> int)
+const bind : (sock : fd, addr : sockaddr#, len : size -> int)
+const setsockopt : (sock : fd, lev : sockproto, opt : sockopt, val : void#, len : size -> int)
+const getsockopt : (sock : fd, lev : sockproto, opt : sockopt, val : void#, len : size# -> int)
+
+/* memory mapping */
+const munmap : (addr:byte#, len:size -> int64)
+const mmap : (addr:byte#, len:size, prot:mprot, flags:mopt, fd:fd, off:off -> byte#)
+
+/* time - doublecheck if this is right */
+const clock_getres : (clk : clock, ts : timespec# -> int32)
+const clock_gettime : (clk : clock, ts : timespec# -> int32)
+const clock_settime : (clk : clock, ts : timespec# -> int32)
+const sleep : (time : uint64 -> int32)
+const nanosleep : (req : timespec#, rem : timespec# -> int32)
+
+/* system information */
+const uname : (buf : utsname# -> int)
+const sysctl : (mib : int[:], \
+ old : void#, oldsz : size#, \
+ new : void#, newsz : size# \
+ -> int)
+
+/*
+wraps a syscall argument, converting it to 64 bits for the syscall function. This is
+the same as casting, but more concise than writing a cast to uint64
+*/
+generic a = {x : @t; -> (x : uint64)}
+
+extern const cstring : (str : byte[:] -> byte#)
+extern const alloca : (sz : size -> byte#)
+
+extern const __freebsd_pipe : (fds : fd[2]# -> int64)
+
+/* process management */
+const exit = {status; syscall(Sysexit, a(status))}
+const getpid = {; -> (syscall(Sysgetpid, 1) : pid)}
+const kill = {pid, sig; -> syscall(Syskill, pid, sig)}
+const fork = {; -> (syscall(Sysfork) : pid)}
+const wait4 = {pid, loc, opt, usage; -> syscall(Syswait4, pid, loc, opt, usage)}
+const waitpid = {pid, loc, opt;
+ -> wait4(pid, loc, opt, (0 : rusage#))
+}
+
+const execv = {cmd, args
+ var p, cargs, i
+
+ /* of course we fucking have to duplicate this code everywhere,
+ * since we want to stack allocate... */
+ p = alloca((args.len + 1)*sizeof(byte#))
+ cargs = (p : byte##)[:args.len + 1]
+ for i = 0; i < args.len; i++
+ cargs[i] = cstring(args[i])
+ ;;
+ cargs[args.len] = (0 : byte#)
+ -> syscall(Sysexecve, cstring(cmd), a(p), a(__cenvp))
+}
+
+const execve = {cmd, args, env
+ var cargs, cenv, i
+ var p
+
+ /* copy the args */
+ p = alloca((args.len + 1)*sizeof(byte#))
+ cargs = (p : byte##)[:args.len]
+ for i = 0; i < args.len; i++
+ cargs[i] = cstring(args[i])
+ ;;
+ cargs[args.len] = (0 : byte#)
+
+ /*
+ copy the env.
+ of course we fucking have to duplicate this code everywhere,
+ since we want to stack allocate...
+ */
+ p = alloca((env.len + 1)*sizeof(byte#))
+ cenv = (p : byte##)[:env.len]
+ for i = 0; i < env.len; i++
+ cenv[i] = cstring(env[i])
+ ;;
+ cenv[env.len] = (0 : byte#)
+
+ -> syscall(Sysexecve, cstring(cmd), a(p), a(cenv))
+}
+
+/* fd manipulation */
+const open = {path, opts; -> (syscall(Sysopen, cstring(path), a(opts), a(0o777)) : fd)}
+const openmode = {path, opts, mode; -> (syscall(Sysopen, cstring(path), a(opts), a(mode)) : fd)}
+const close = {fd; -> syscall(Sysclose, a(fd))}
+const creat = {path, mode; -> (openmode(path, Ocreat | Otrunc | Owronly, mode) : fd)}
+const unlink = {path; -> (syscall(Sysunlink, cstring(path)) : int)}
+const read = {fd, buf; -> (syscall(Sysread, a(fd), (buf : byte#), a(buf.len)) : size)}
+const pread = {fd, buf, off; -> (syscall(Syspread, a(fd), (buf : byte#), a(buf.len), a(off)) : size)}
+const readv = {fd, vec; -> (syscall(Sysreadv, a(fd), (vec : iovec#), a(vec.len)) : size)}
+const write = {fd, buf; -> (syscall(Syswrite, a(fd), (buf : byte#), a(buf.len)) : size)}
+const pwrite = {fd, buf, off; -> (syscall(Syspwrite, a(fd), (buf : byte#), a(buf.len), a(off)) : size)}
+const writev = {fd, vec; -> (syscall(Syswritev, a(fd), (vec : iovec#), a(vec.len)) : size)}
+const lseek = {fd, off, whence; -> syscall(Syslseek, a(fd), a(off), a(whence))}
+const stat = {path, sb; -> syscall(Sysstat, cstring(path), a(sb))}
+const lstat = {path, sb; -> syscall(Syslstat, cstring(path), a(sb))}
+const fstat = {fd, sb; -> syscall(Sysfstat, a(fd), a(sb))}
+const mkdir = {path, mode; -> (syscall(Sysmkdir, cstring(path), a(mode)) : int64)}
+generic ioctl = {fd, req, arg; -> (syscall(Sysioctl, a(fd), a(req), a(arg)) : int64)}
+const chdir = {dir; -> syscall(Syschdir, cstring(dir))}
+const __getcwd = {buf; -> syscall(Sys__getcwd, a(buf), a(buf.len))}
+const getdents = {fd, buf; -> (syscall(Sysgetdents, a(fd), a(buf), a(buf.len)) : int64)}
+
+/* signals */
+const sigaction = {sig, act, oact; -> (syscall(Syssigaction, a(sig), a(act), a(oact)) : int)}
+const sigprocmask = {sig, act, oact; -> (syscall(Syssigprocmask, a(sig), a(act), a(oact)) : int)}
+
+/* file stuff */
+const pipe = {fds; -> syscall(Syspipe, fds)}
+const dup = {fd; -> (syscall(Sysdup, a(fd)) : fd)}
+const dup2 = {src, dst; -> (syscall(Sysdup2, a(src), a(dst)) : fd)}
+const fcntl = {fd, cmd, args; -> syscall(Sysfcntl, a(fd), a(cmd), a(args))}
+const poll = {pfd, tm; -> (syscall(Syspoll, (pfd : byte#), a(pfd.len), a(tm)) : int)}
+
+/* networking */
+const socket = {dom, stype, proto; -> (syscall(Syssocket, a(dom), a(stype), a(proto)) : fd)}
+const connect = {sock, addr, len; -> (syscall(Sysconnect, a(sock), a(addr), a(len)) : int)}
+const accept = {sock, addr, len; -> (syscall(Sysaccept, a(sock), a(addr), a(len)) : fd)}
+const listen = {sock, backlog; -> (syscall(Syslisten, a(sock), a(backlog)) : int)}
+const bind = {sock, addr, len; -> (syscall(Sysbind, a(sock), a(addr), a(len)) : int)}
+const setsockopt = {sock, lev, opt, val, len; -> (syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) : int)}
+const getsockopt = {sock, lev, opt, val, len; -> (syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) : int)}
+
+/* memory management */
+const munmap = {addr, len; -> syscall(Sysmunmap, a(addr), a(len))}
+const mmap = {addr, len, prot, flags, fd, off;
+ /* the actual syscall has padding on the offset arg */
+ -> (syscall(Sysmmap, a(addr), a(len), a(prot), a(flags), a(fd), a(0), a(off)) : byte#)
+}
+
+/* time */
+const clock_getres = {clk, ts; -> (syscall(Sysclock_getres, clockid(clk), a(ts)) : int32)}
+const clock_gettime = {clk, ts; -> (syscall(Sysclock_gettime, clockid(clk), a(ts)) : int32)}
+const clock_settime = {clk, ts; -> (syscall(Sysclock_settime, clockid(clk), a(ts)) : int32)}
+
+const sleep = {time
+ var req, rem
+ req = [.sec = time, .nsec = 0]
+ -> nanosleep(&req, &rem)
+}
+
+const nanosleep = {req, rem; -> (syscall(Sysnanosleep, a(req), a(rem)) : int32)}
+
+
+/* system information */
+const uname = {buf
+ var mib : int[2]
+ var ret
+ var sys, syssz
+ var nod, nodsz
+ var rel, relsz
+ var ver, versz
+ var mach, machsz
+
+ ret = 0
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 1 /* KERN_OSTYPE */
+ sys = (buf.system[:] : void#)
+ syssz = buf.system.len
+ ret = sysctl(mib[:], sys, &syssz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 10 /* KERN_HOSTNAME */
+ nod = (buf.node[:] : void#)
+ nodsz = buf.node.len
+ ret = sysctl(mib[:], nod, &nodsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 2 /* KERN_OSRELEASE */
+ rel = (buf.release[:] : void#)
+ relsz = buf.release.len
+ ret = sysctl(mib[:], rel, &relsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 1 /* CTL_KERN */
+ mib[1] = 27 /* KERN_OSVERSION */
+ ver = (buf.version[:] : void#)
+ versz = buf.version.len
+ ret = sysctl(mib[:], ver, &versz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ mib[0] = 6 /* CTL_HW */
+ mib[1] = 1 /* HW_MACHINE */
+ mach = (buf.machine[:] : void#)
+ machsz = buf.machine.len
+ ret = sysctl(mib[:], mach, &machsz, (0 : void#), (0 : size#))
+ if ret < 0
+ -> ret
+ ;;
+
+ -> 0
+}
+
+const sysctl = {mib, old, oldsz, new, newsz
+ /* all args already passed through a() or ar ptrs */
+ -> (syscall(Syssysctl, \
+ (mib : int#), a(mib.len), old, oldsz, new, newsz) : int)
+}
+
+const clockid = {clk
+ match clk
+ | `Clockrealtime: -> 0
+ | `Clockproccputime: -> 2
+ | `Clockmonotonic: -> 3
+ | `Clockthreadcputime: -> 4
+ | `Clockuptime: -> 5
+ ;;
+ -> -1
+}
+
+const waitstatus = {st
+ if st < 0
+ -> `Waitfail st
+ ;;
+ match st & 0o177
+ | 0: -> `Waitexit (st >> 8)
+ | 0x7f:-> `Waitstop (st >> 8)
+ | sig: -> `Waitsig sig
+ ;;
+}
+
diff --git a/support/syscall-gen/types+openbsd:6.2-x64.frag b/support/syscall-gen/types+openbsd:6.2-x64.frag
index 0d28f2e..8d48229 100644
--- a/support/syscall-gen/types+openbsd:6.2-x64.frag
+++ b/support/syscall-gen/types+openbsd:6.2-x64.frag
@@ -17,7 +17,7 @@ type sockfam = uint8 /* socket family */
type filemode = uint32
type filetype = uint8
type fcntlcmd = int64
-ype signo = int32
+type signo = int32
type sigflags = int32
type sigset = uint32
type msg = void
diff --git a/support/syscall-gen/types+openbsd:6.3-x64.frag b/support/syscall-gen/types+openbsd:6.3-x64.frag
new file mode 100644
index 0000000..cd204e5
--- /dev/null
+++ b/support/syscall-gen/types+openbsd:6.3-x64.frag
@@ -0,0 +1,479 @@
+type size = int64 /* spans entire address space */
+type usize = uint64 /* unsigned size */
+type off = int64 /* file offsets */
+type intptr = uint64/* can hold any pointer losslessly */
+type time = int64 /* milliseconds since epoch */
+type pid = int32 /* process id */
+type scno = int64 /*syscall*/
+type fdopt = int64 /* fd options */
+type fd = int32 /* fd */
+type whence = uint64 /* seek from whence */
+type mprot = int64 /* memory protection */
+type mopt = int64 /* memory mapping options */
+type socktype = int64 /* socket type */
+type sockproto = int64 /* socket protocol */
+type sockopt = int32 /* socket option */
+type sockfam = uint8 /* socket family */
+type filemode = uint32
+type filetype = uint8
+type fcntlcmd = int64
+type signo = int32
+type sigflags = int32
+type sigset = uint32
+type msg = void
+type gid = uint32
+
+const Futexwait : int = 1
+const Futexwake : int = 2
+const Futexrequeue : int = 3
+
+
+type clock = union
+ `Clockrealtime
+ `Clockmonotonic
+ `Clockproccputime
+ `Clockthreadcputime
+ `Clockuptime
+;;
+
+type waitstatus = union
+ `Waitfail int32
+ `Waitexit int32
+ `Waitsig int32
+ `Waitstop int32
+;;
+
+type rlimit = struct
+ cur : uint64 /* current (soft) limit */
+ max : uint64 /* maximum value for rlim_cur */
+;;
+
+type timespec = struct
+ sec : uint64
+ nsec : uint64
+;;
+
+type timeval = struct
+ sec : uint64
+ usec : uint64
+;;
+
+type timezone = struct
+ minwest : int32 /* minutes west of Greenwich */
+ dsttime : int32 /* type of dst correction */
+;;
+
+type pollfd = struct
+ fd : fd
+ events : uint16
+ revents : uint16
+;;
+
+type itimerval = struct
+ interval : timeval /* timer interval */
+ value : timeval /* current value */
+;;
+
+type sigaction = struct
+ handler : byte# /* code pointer */
+ mask : sigset
+ flags : sigflags
+;;
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+type sigcontext = struct
+ /* plain match trapframe */
+ rdi : int64
+ rsi : int64
+ rdx : int64
+ rcx : int64
+ r8 : int64
+ r9 : int64
+ r10 : int64
+ r11 : int64
+ r12 : int64
+ r13 : int64
+ r14 : int64
+ r15 : int64
+ rbp : int64
+ rbx : int64
+ rax : int64
+ gs : int64
+ fs : int64
+ es : int64
+ ds : int64
+ trapno : int64
+ err : int64
+ rip : int64
+ cs : int64
+ rflags : int64
+ rsp : int64
+ ss : int64
+
+ fpstate : fxsave64#
+ __pad : int32
+ mask : int32
+ cookie : int64
+;;
+
+type sigaltstack = struct
+ sp : void#
+ size : size
+ flags : int32
+;;
+
+type fxsave64 = struct
+ fcw : int16
+ fsw : int16
+ ftw : int8
+ unused1 : int8
+ fop : int16
+ rip : int64
+ rdp : int64
+ mxcsr : int32
+ mxcsrmask : int32
+ st : int64[8][2] /* 8 normal FP regs */
+ xmm : int64[16][2] /* 16 SSE2 registers */
+ unused3 : int8[96]
+;;
+
+const Simaxsz = 128
+const Sipad = (Simaxsz / 4) - 3
+type siginfo = struct
+ signo : int
+ code : int
+ errno : int
+ pad : int[Sipad]
+;;
+
+type rusage = struct
+ utime : timeval /* user time */
+ stime : timeval /* system time */
+ maxrss : uint64 /* max resident set size*/
+ ixrss : uint64 /* shared text size */
+ idrss : uint64 /* unshared data size */
+ isrss : uint64 /* unshared stack size */
+ minflt : uint64 /* page reclaims */
+ majflt : uint64 /* page faults */
+ nswap : uint64 /* swaps */
+ inblock : uint64 /* block input ops */
+ oublock : uint64 /* block output ops */
+ msgsnd : uint64 /* messages sent */
+ msgrcv : uint64 /* messages received */
+ nsignals : uint64 /* signals received */
+ nvcsw : uint64 /* voluntary context switches */
+ nivcsw : uint64 /* involuntary context switches */
+;;
+
+type tforkparams = struct
+ tcb : void#
+ tid : pid#
+ stk : byte#
+;;
+
+type statbuf = struct
+ mode : filemode
+ dev : uint32
+ ino : uint64
+ nlink : uint32
+ uid : uint32
+ gid : uint32
+ rdev : uint32
+ atime : timespec
+ mtime : timespec
+ ctime : timespec
+ size : off
+ blocks : int64
+ blksize : uint32
+ flags : uint32
+ gen : uint32
+ birthtim : timespec
+;;
+
+type semun = struct
+ semarr : void#
+;;
+
+const Mfsnamelen = 16 /* length of fs type name, including nul */
+const Mnamelen = 90 /* length of buffer for returned name */
+
+type statfs = struct
+ flags : uint32 /* copy of mount flags */
+ bsize : uint32 /* file system block size */
+ iosize : uint32 /* optimal transfer block size */
+
+ /* unit is f_bsize */
+ blocks : uint64 /* total data blocks in file system */
+ bfree : uint64 /* free blocks in fs */
+ bavail : int64 /* free blocks avail to non-superuser */
+
+ files : int64 /* total file nodes in file system */
+ ffree : int64 /* free file nodes in fs */
+ favail : int64 /* free file nodes avail to non-root */
+
+ syncwr : int64 /* count of sync writes since mount */
+ syncrd : int64 /* count of sync reads since mount */
+ asyncwr : int64 /* count of async writes since mount */
+ asyncrd : int64 /* count of async reads since mount */
+
+ fsid : fsid /* file system id */
+ namemax : uint32 /* maximum filename length */
+ owner : uid /* user that mounted the file system */
+ ctime : uint64 /* last mount [-u] time */
+
+ fstypename : byte[Mfsnamelen]; /* fs type name */
+ mntonname : byte[Mnamelen]; /* directory on which mounted */
+ mntfromname : byte[Mnamelen]; /* mounted file system */
+ mntfromspec : byte[Mnamelen]; /* special for mount request */
+ ///union mount_info mount_info; /* per-filesystem mount options */
+ __mountinfo : byte[160]; /* storage for 'union mount_info' */
+;;
+
+type utsname = struct
+ system : byte[32]
+ node : byte[32]
+ release : byte[32]
+ version : byte[32]
+ machine : byte[32]
+;;
+
+type sockaddr = struct
+ len : byte
+ fam : sockfam
+ data : byte[14] /* what is the *actual* length? */
+;;
+
+type sockaddr_in = struct
+ len : byte
+ fam : sockfam
+ port : uint16
+ addr : byte[4]
+ zero : byte[8]
+;;
+
+type sockaddr_in6 = struct
+ len : byte
+ fam : sockfam
+ port : uint16
+ flow : uint32
+ addr : byte[16]
+ scope : uint32
+;;
+
+type sockaddr_un = struct
+ len : uint8
+ fam : sockfam
+ path : byte[104]
+;;
+
+type sockaddr_storage = struct
+ len : byte
+ fam : sockfam
+ __pad1 : byte[6]
+ __align : int64
+ __pad2 : byte[240]
+;;
+
+type dirent = struct
+ fileno : uint64
+ off : uint64
+ reclen : uint16
+ ftype : uint8
+ namlen : uint8
+ __pad : byte[4]
+ name : byte[256]
+;;
+
+type iovec = struct
+ base : byte#
+ len : uint64
+;;
+
+/* open options */
+const Ordonly : fdopt = 0x0
+const Owronly : fdopt = 0x1
+const Ordwr : fdopt = 0x2
+const Oappend : fdopt = 0x8
+const Ondelay : fdopt = 0x4
+const Oshlock : fdopt = 0x10 /* open with shared file lock */
+const Oexlock : fdopt = 0x20 /* open with exclusive file lock */
+const Oasync : fdopt = 0x40 /* signal pgrp when data ready */
+const Osync : fdopt = 0x80 /* backwards compatibility */
+const Onofollow : fdopt = 0x100
+const Ocreat : fdopt = 0x200
+const Otrunc : fdopt = 0x400
+const Oexcl : fdopt = 0x800
+const Ocloexec : fdopt = 0x10000
+const Odsync : fdopt = Osync /* synchronous data writes */
+const Orsync : fdopt = Osync /* synchronous reads */
+const Odir : fdopt = 0x20000
+
+/* poll options */
+const Pollin : uint16 = 0x0001
+const Pollpri : uint16 = 0x0002
+const Pollout : uint16 = 0x0004
+const Pollerr : uint16 = 0x0008
+const Pollhup : uint16 = 0x0010
+const Pollnval : uint16 = 0x0020
+const Pollnorm : uint16 = 0x0040
+const Pollrdband: uint16 = 0x0080
+const Pollwrband: uint16 = 0x0100
+
+/* stat modes */
+const Sifmt : filemode = 0xf000
+const Sififo : filemode = 0x1000
+const Sifchr : filemode = 0x2000
+const Sifdir : filemode = 0x4000
+const Sifblk : filemode = 0x6000
+const Sifreg : filemode = 0x8000
+const Siflnk : filemode = 0xa000
+const Sifsock : filemode = 0xc000
+const Sisvtx : filemode = 0x0200
+
+/* mmap protection */
+const Mprotnone : mprot = 0x0
+const Mprotrd : mprot = 0x1
+const Mprotwr : mprot = 0x2
+const Mprotexec : mprot = 0x4
+const Mprotrw : mprot = 0x3
+
+/* mmap options */
+const Mshared : mopt = 0x1
+const Mpriv : mopt = 0x2
+const Mfixed : mopt = 0x10
+const Mfile : mopt = 0x0
+const Manon : mopt = 0x1000
+const Mstack : mopt = 0x4000
+const Mnoreplace : mopt = 0x0800
+
+/* file types */
+const Dtunknown : filetype = 0
+const Dtfifo : filetype = 1
+const Dtchr : filetype = 2
+const Dtdir : filetype = 4
+const Dtblk : filetype = 6
+const Dtreg : filetype = 8
+const Dtlnk : filetype = 10
+const Dtsock : filetype = 12
+
+/* socket families. INCOMPLETE. */
+const Afunspec : sockfam = 0
+const Afunix : sockfam = 1
+const Afinet : sockfam = 2
+const Afinet6 : sockfam = 24
+
+/* socket types. */
+const Sockstream : socktype = 1
+const Sockdgram : socktype = 2
+const Sockraw : socktype = 3
+const Sockrdm : socktype = 4
+const Sockseqpacket : socktype = 5
+
+/* socket options */
+const Sodebug : sockopt = 0x0001 /* turn on debugging info recording */
+const Soacceptconn : sockopt = 0x0002 /* socket has had listen() */
+const Soreuseaddr : sockopt = 0x0004 /* allow local address reuse */
+const Sokeepalive : sockopt = 0x0008 /* keep connections alive */
+const Sodontroute : sockopt = 0x0010 /* just use interface addresses */
+const Sobroadcast : sockopt = 0x0020 /* permit sending of broadcast msgs */
+const Souseloopback : sockopt = 0x0040 /* bypass hardware when possible */
+const Solinger : sockopt = 0x0080 /* linger on close if data present */
+const Sooobinline : sockopt = 0x0100 /* leave received OOB data in line */
+const Soreuseport : sockopt = 0x0200 /* allow local address & port reuse */
+const Sotimestamp : sockopt = 0x0800 /* timestamp received dgram traffic */
+const Sobindany : sockopt = 0x1000 /* allow bind to any address */
+const Sosndbuf : sockopt = 0x1001 /* send buffer size */
+const Sorcvbuf : sockopt = 0x1002 /* receive buffer size */
+const Sosndlowat : sockopt = 0x1003 /* send low-water mark */
+const Sorcvlowat : sockopt = 0x1004 /* receive low-water mark */
+const Sosndtimeo : sockopt = 0x1005 /* send timeout */
+const Sorcvtimeo : sockopt = 0x1006 /* receive timeout */
+const Soerror : sockopt = 0x1007 /* get error status and clear */
+const Sotype : sockopt = 0x1008 /* get socket type */
+const Sonetproc : sockopt = 0x1020 /* multiplex; network processing */
+const Sortable : sockopt = 0x1021 /* routing table to be used */
+const Sopeercred : sockopt = 0x1022 /* get connect-time credentials */
+const Sosplice : sockopt = 0x1023 /* splice data to other socket */
+
+/* socket option levels */
+const Solsocket : sockproto = 0xffff
+
+/* network protocols */
+const Ipproto_ip : sockproto = 0
+const Ipproto_icmp : sockproto = 1
+const Ipproto_tcp : sockproto = 6
+const Ipproto_udp : sockproto = 17
+const Ipproto_raw : sockproto = 255
+
+const Seekset : whence = 0
+const Seekcur : whence = 1
+const Seekend : whence = 2
+
+/* system specific constants */
+const Maxpathlen : size = 1024
+
+/* fcntl constants */
+const Fdupfd : fcntlcmd = 0 /* duplicate file descriptor */
+const Fgetfd : fcntlcmd = 1 /* get file descriptor flags */
+const Fsetfd : fcntlcmd = 2 /* set file descriptor flags */
+const Fgetfl : fcntlcmd = 3 /* get file status flags */
+const Fsetfl : fcntlcmd = 4 /* set file status flags */
+const Fgetown : fcntlcmd = 5 /* get SIGIO/SIGURG proc/pgrp */
+const Fsetown : fcntlcmd = 6 /* set SIGIO/SIGURG proc/pgrp */
+const Fogetlk : fcntlcmd = 7 /* get record locking information */
+const Fosetlk : fcntlcmd = 8 /* set record locking information */
+
+/* return value for a failed mapping */
+const Mapbad : byte# = (-1 : byte#)
+
+/* signal flags */
+const Saonstack : sigflags = 0x0001 /* take signal on signal stack */
+const Sarestart : sigflags = 0x0002 /* restart system on signal return */
+const Saresethand : sigflags = 0x0004 /* reset to SIG_DFL when taking signal */
+const Sanodefer : sigflags = 0x0010 /* don't mask the signal we're delivering */
+const Sanocldwait : sigflags = 0x0020 /* don't create zombies (assign to pid 1) */
+const Sanocldstop : sigflags = 0x0008 /* do not generate SIGCHLD on child stop */
+const Sasiginfo : sigflags = 0x0040 /* generate siginfo_t */
+
+/* signals */
+const Sighup : signo = 1 /* hangup */
+const Sigint : signo = 2 /* interrupt */
+const Sigquit : signo = 3 /* quit */
+const Sigill : signo = 4 /* illegal instruction (not reset when caught) */
+const Sigtrap : signo = 5 /* trace trap (not reset when caught) */
+const Sigabrt : signo = 6 /* abort() */
+const Sigiot : signo = Sigabrt /* compatibility */
+const Sigemt : signo = 7 /* EMT instruction */
+const Sigfpe : signo = 8 /* floating point exception */
+const Sigkill : signo = 9 /* kill (cannot be caught or ignored) */
+const Sigbus : signo = 10 /* bus error */
+const Sigsegv : signo = 11 /* segmentation violation */
+const Sigsys : signo = 12 /* bad argument to system call */
+const Sigpipe : signo = 13 /* write on a pipe with no one to read it */
+const Sigalrm : signo = 14 /* alarm clock */
+const Sigterm : signo = 15 /* software termination signal from kill */
+const Sigurg : signo = 16 /* urgent condition on IO channel */
+const Sigstop : signo = 17 /* sendable stop signal not from tty */
+const Sigtstp : signo = 18 /* stop signal from tty */
+const Sigcont : signo = 19 /* continue a stopped process */
+const Sigchld : signo = 20 /* to parent on child stop or exit */
+const Sigttin : signo = 21 /* to readers pgrp upon background tty read */
+const Sigttou : signo = 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
+const Sigio : signo = 23 /* input/output possible signal */
+const Sigxcpu : signo = 24 /* exceeded CPU time limit */
+const Sigxfsz : signo = 25 /* exceeded file size limit */
+const Sigvtalrm : signo = 26 /* virtual time alarm */
+const Sigprof : signo = 27 /* profiling time alarm */
+const Sigwinch : signo = 28 /* window size changes */
+const Siginfo : signo = 29 /* information request */
+const Sigusr1 : signo = 30 /* user defined signal 1 */
+const Sigusr2 : signo = 31 /* user defined signal 2 */
+const Sigthr : signo = 32 /* thread library AST */
+
+extern const syscall : (sc:scno, args:... -> int64)
+extern var __cenvp : byte##
diff --git a/test/data/strfind-expected b/test/data/strfind-expected
index 04e7a1c..4e6ab82 100644
--- a/test/data/strfind-expected
+++ b/test/data/strfind-expected
@@ -1,4 +1,4 @@
-No match
+Found 0
No match
No match
Found 0