shithub: mc

Download patch

ref: 9aabbe574e648e0a462b211c62da5eb5875343b7
parent: 4acd9ee51a541f94e81457b1a7fb3accbd790696
parent: 3d71446ecb6569add0d9eaf2e7e4a05d99bd2625
author: S. Gilles <sgilles@math.umd.edu>
date: Wed Apr 18 04:30:41 EDT 2018

Merge remote-tracking branch 'ori/master' into HEAD

--- a/6/main.c
+++ b/6/main.c
@@ -41,6 +41,7 @@
 	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 @@
 
 	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)) {
@@ -239,6 +240,9 @@
 			break;
 		case 'I':
 			lappend(&incpaths, &nincpaths, ctx.optarg);
+			break;
+		case 'T':
+			allowhidden++;
 			break;
 		default:
 			usage(argv[0]);
--- a/6/simp.c
+++ b/6/simp.c
@@ -1006,6 +1006,15 @@
 		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;
--- a/Makefile
+++ b/Makefile
@@ -41,4 +41,4 @@
 	./mbldwrap.sh uninstall
 
 release:
-	./support/release.sh 0.2.0
+	./support/release.sh $(VERSION)
--- a/doc/6m.1
+++ b/doc/6m.1
@@ -65,6 +65,15 @@
 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.
 
--- a/lib/crypto/bld.sub
+++ b/lib/crypto/bld.sub
@@ -12,10 +12,13 @@
 	# 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
@@ -22,11 +25,13 @@
 
 	# utilities for subtle bits
 	ct.myr
+	ctbig.myr
 	clear.myr
 
 	lib ../std:std
 	lib ../sys:sys
 	lib ../thread:thread
+	lib ../iter:iter
 ;;
 
 
--- a/lib/crypto/ct.myr
+++ b/lib/crypto/ct.myr
@@ -53,7 +53,7 @@
 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
--- a/lib/crypto/ctbig.myr
+++ b/lib/crypto/ctbig.myr
@@ -1,4 +1,5 @@
 use std
+use iter
 
 use "ct"
 
@@ -9,32 +10,64 @@
 	;;
 
 	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#)
+	pkglocal const ct2big	: (v : ctbig# -> std.bigint#)
+	pkglocal const big2ct	: (v : std.bigint#, nbit : 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)
+	/* 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)
 
-	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 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,9 +83,23 @@
 	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
 	-> std.mk([
 		.sign=1,
@@ -60,17 +107,17 @@
 	])
 }
 
-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,28 +131,91 @@
 	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
 	-> std.mk([
 		.nbit=v.nbit,
@@ -119,21 +229,29 @@
 }
 
 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 @@
 	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,18 +295,202 @@
 		std.slfree(a.dig)
 	;;
 	r.dig = w[:a.dig.len]
+	clip(r)
 }
 
-//const ctmodpow = {res, a, b
-//	/* find rinv, mprime */
-//	
-//	/* convert to monty space */
-//
-//	/* do the modpow */
-//
-//	/* and come back */
-//}
+/*
+ * 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))
+}
+
+/*
+ * 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 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 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 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,7 +543,7 @@
 }
 
 const ndig = {nbit
-	-> (nbit + 8*sizeof(uint32) - 1)/sizeof(uint32)
+	-> (nbit + 8*sizeof(uint32) - 1)/(8*sizeof(uint32))
 }
 
 const checksz = {a, b
@@ -270,3 +550,13 @@
 	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
+}
+
--- /dev/null
+++ b/lib/crypto/rsa.myr
@@ -1,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
+}
--- /dev/null
+++ b/lib/crypto/test/ctbig.myr
@@ -1,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)
+}
+
+
--- /dev/null
+++ b/lib/crypto/test/rsa.myr
@@ -1,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",
+	]
+][:]
+
--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -173,7 +173,13 @@
 	-> `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 @@
 	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 @@
 			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 @@
 	-> 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 @@
 		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 @@
 		;;
 		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 @@
 		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 @@
 	;;
 }
 
-/* must be called with i >= 1 */
 const prevchar = {s, i
 	std.assert(i != 0, "prevchar must be called with i >= 1\n")
 	i--
--- a/lib/regex/redump.myr
+++ b/lib/regex/redump.myr
@@ -68,6 +68,21 @@
 	;;
 }
 
+/*
+ * 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 @@
 	| `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 @@
 	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
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -741,7 +741,6 @@
 	;;
 	/* undo the biasing for remainder */
 	bigshri(u, shift)
-	trim(q)
 	bigfree(v)
 	-> (trim(q), trim(u))
 }
--- a/lib/std/env+posixy.myr
+++ b/lib/std/env+posixy.myr
@@ -59,21 +59,25 @@
 
 	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)
 }
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -492,7 +492,12 @@
 		| ("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")
--- a/lib/std/hashfuncs.myr
+++ b/lib/std/hashfuncs.myr
@@ -18,6 +18,12 @@
 		}
 	;;
 
+	impl equatable bool =
+		eq = {a, b
+			-> a == b
+		}
+	;;
+
 	impl equatable @a :: integral,numeric @a =
 		eq = {a, b
 			-> a == b
--- a/lib/std/strfind.myr
+++ b/lib/std/strfind.myr
@@ -8,19 +8,16 @@
 ;;
 
 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 @@
 		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
--- 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 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 @@
 		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 @@
 		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))
--- a/lib/sys/bld.sub
+++ b/lib/sys/bld.sub
@@ -5,10 +5,13 @@
 	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
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -215,6 +215,7 @@
 	const Mfixed	: mopt = 0x10
 	const Mfile	: mopt = 0x0
 	const Manon	: mopt = 0x1000
+	const Mstack	: mopt = 0x4000
 	const Mnoreplace	: mopt = 0x0800
 
 	/* file types */
--- a/lib/sys/sys+openbsd:6.2-x64.myr
+++ b/lib/sys/sys+openbsd:6.2-x64.myr
@@ -348,6 +348,7 @@
 	const Mfixed	: mopt = 0x10
 	const Mfile	: mopt = 0x0
 	const Manon	: mopt = 0x1000
+	const Mstack	: mopt = 0x4000
 	const Mnoreplace	: mopt = 0x0800
 	
 	/* file types */
--- /dev/null
+++ b/lib/sys/sys+openbsd:6.3-x64.myr
@@ -1,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)
+}
--- a/lib/testr/testr.myr
+++ b/lib/testr/testr.myr
@@ -149,21 +149,21 @@
 
 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)
--- a/lib/thread/spawn+openbsd.myr
+++ b/lib/thread/spawn+openbsd.myr
@@ -53,7 +53,7 @@
 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
 	;;
--- 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
--- /dev/null
+++ b/mbld/cpufeatures+plan9-x64.s
@@ -1,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
--- /dev/null
+++ b/mbld/cpufeatures+posixy-x64.s
@@ -1,0 +1,10 @@
+.globl bld$cpufeatures
+.globl _bld$cpufeatures
+bld$cpufeatures:
+_bld$cpufeatures:
+	mov	$0x1, %eax
+	cpuid
+	mov	%ecx, %eax
+	rol	$32, %rax
+	shrd	$32, %rdx, %rax
+	ret
--- a/mbld/cpufeatures+x64.s
+++ /dev/null
@@ -1,10 +1,0 @@
-.globl bld$cpufeatures
-.globl bld$_cpufeatures
-bld$cpufeatures:
-bld$_cpufeatures:
-	mov	$0x1, %eax
-	cpuid
-	mov	%ecx, %eax
-	rol	$32, %rax
-	shrd	$32, %rdx, %rax
-	ret
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -333,7 +333,6 @@
 		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 @@
 		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))
 		;;
--- a/mbld/test.myr
+++ b/mbld/test.myr
@@ -28,21 +28,11 @@
 	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 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 @@
 	-> res
 }
 
+const matchtest = {name, pat
+	match std.strfind(pat, ":")
+	| `std.Some i:	-> std.strhas(name, pat[:i])
+	| `std.None:	-> std.strhas(name, pat)
+	;;
+}
--- 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
--- 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
--- 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
--- 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
--- 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 @@
 	$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
--- 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
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -29,6 +29,7 @@
 	size_t nfiltertr;
 };
 
+int allowhidden;
 
 static void infernode(Node **np, Type *ret, int *sawret);
 static void inferexpr(Node **np, Type *ret, int *sawret);
@@ -69,7 +70,9 @@
 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 @@
 
 	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 @@
 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 @@
 		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 @@
 	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 @@
 
 	/* 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*
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -378,6 +378,7 @@
 extern size_t ndecls;
 extern Node **exportimpls;
 extern size_t nexportimpls;
+extern int allowhidden;
 
 /* property tables */
 extern int opispure[];
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -663,13 +663,17 @@
 	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++)
--- a/support/syscall-gen/gensys.sh
+++ b/support/syscall-gen/gensys.sh
@@ -37,7 +37,7 @@
 	' < 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
--- /dev/null
+++ b/support/syscall-gen/gentypes+openbsd:6.3-x64.frag
@@ -1,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]
+
+;;
+
--- /dev/null
+++ b/support/syscall-gen/specials+openbsd:6.3-x64.frag
@@ -1,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
+	;;
+}
+
--- 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 filemode	= uint32
 type filetype	= uint8
 type fcntlcmd	= int64
-ype signo	= int32
+type signo	= int32
 type sigflags	= int32
 type sigset	= uint32
 type msg	= void
--- /dev/null
+++ b/support/syscall-gen/types+openbsd:6.3-x64.frag
@@ -1,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##
--- a/test/data/strfind-expected
+++ b/test/data/strfind-expected
@@ -1,4 +1,4 @@
-No match
+Found 0
 No match
 No match
 Found 0