shithub: mc

Download patch

ref: 21b91ad9fa7ae830272dc67fbe3150dc30921702
parent: 96c8217e913d8d6de22bbb1aa3624c26e66838fc
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Jun 12 08:46:50 EDT 2015

Move fmt to fmt2.

    Shit seems to work.

--- a/libbio/bio.myr
+++ b/libbio/bio.myr
@@ -109,7 +109,7 @@
 	| Rd:	-> std.Ordonly
 	| Wr:	-> std.Owronly
 	| Rw:	-> std.Ordwr
-	| _:	std.f2fatal("bio: bad file mode")
+	| _:	std.fatal("bio: bad file mode")
 	;;
 	-> 0
 }
@@ -407,7 +407,7 @@
 
 	ap = std.vastart(&args)
 	sb = std.mksb()
-	sl = std.f2fmt(fmt, &ap)
+	sl = std.fmt(fmt, &ap)
 	n = write(f, sl)
 	std.slfree(sl)
 	-> n
--- a/libregex/compile.myr
+++ b/libregex/compile.myr
@@ -168,21 +168,21 @@
 	var l, h
 
 	indent(ind)
-	std.f2put("Range (end = {}) {{\n", rt.end)
+	std.put("Range (end = {}) {{\n", rt.end)
 	for i = 0; i < rt.ranges.len; i++
 		indent(ind + 1)
 		(l, h) = rt.ranges[i]
-		std.f2put("0x{x}-0x{x}: \n", l, h)
+		std.put("0x{x}-0x{x}: \n", l, h)
 		rtdump(rt.link[i], ind + 1)
 	;;
 	indent(ind)
-	std.f2put("}\n")
+	std.put("}\n")
 }
 
 const indent = {ind
 	var i
 	for i = 0; i < ind; i++
-		std.f2put("\t")
+		std.put("\t")
 	;;
 }
 
@@ -373,28 +373,28 @@
 		->
 	;;
 	for i = 0; i < re.proglen; i++
-		std.f2put("{}:\t", i)
+		std.put("{}:\t", i)
 		match re.prog[i]
 		/* Char matching. Consume exactly one byte from the string. */
-		| `Ibyte b:		std.f2put("`Ibyte {} ({})\n", b, b castto(char)) 
+		| `Ibyte b:		std.put("`Ibyte {} ({})\n", b, b castto(char)) 
 		| `Irange (start, end):	
-			std.f2put("`Irange ({},{})", start, end) 
+			std.put("`Irange ({},{})", start, end) 
 			if std.isalnum(start castto(char)) && std.isalnum(end castto(char))
-				std.f2put("\t/* {}-{} */", start castto(char), end castto(char))
+				std.put("\t/* {}-{} */", start castto(char), end castto(char))
 			;;
-			std.f2put("\n")
+			std.put("\n")
 		/* capture groups */
-		| `Ilbra m:		std.f2put("`Ilbra {}\n", m) 
-		| `Irbra m:		std.f2put("`Irbra {}\n", m) 
+		| `Ilbra m:		std.put("`Ilbra {}\n", m) 
+		| `Irbra m:		std.put("`Irbra {}\n", m) 
 		/* anchors */
-		| `Ibol:			std.f2put("`Ibol\n")
-		| `Ieol:			std.f2put("`Ieol\n")
-		| `Ibow:			std.f2put("`Ibow\n")
-		| `Ieow:			std.f2put("`Ieow\n")
+		| `Ibol:			std.put("`Ibol\n")
+		| `Ieol:			std.put("`Ieol\n")
+		| `Ibow:			std.put("`Ibow\n")
+		| `Ieow:			std.put("`Ieow\n")
 		/* control flow */
-		| `Ifork	(lip, rip):	std.f2put("`Ifork ({},{})\n", lip, rip) 
-		| `Ijmp ip:		std.f2put("`Ijmp {}\n", ip) 
-		| `Imatch id:		std.f2put("`Imatch {}\n", id) 
+		| `Ifork	(lip, rip):	std.put("`Ifork ({},{})\n", lip, rip) 
+		| `Ijmp ip:		std.put("`Ijmp {}\n", ip) 
+		| `Imatch id:		std.put("`Imatch {}\n", id) 
 		;;
 	;;
 }
@@ -407,58 +407,58 @@
 		->
 	;;
 	for i = 0; i < indent; i++
-		std.f2put("  ")
+		std.put("  ")
 	;;
 	match t#
 	| `Alt	(a, b):
-		std.f2put("Alt\n")
+		std.put("Alt\n")
 		dump(re, a, indent + 1)
 		dump(re, b, indent + 1)
 	| `Cat	(a, b):
-		std.f2put("Cat\n")
+		std.put("Cat\n")
 		dump(re, a, indent + 1)
 		dump(re, b, indent + 1)
 	/* repetition */
 	| `Star	a:
-		std.f2put("Star\n")
+		std.put("Star\n")
 		dump(re, a, indent + 1)
 	| `Rstar a:
-		std.f2put("Rstar\n")
+		std.put("Rstar\n")
 		dump(re, a, indent + 1)
 	| `Plus	a:
-		std.f2put("Plus\n")
+		std.put("Plus\n")
 		dump(re, a, indent + 1)
 	| `Rplus a:
-		std.f2put("Rplus\n")
+		std.put("Rplus\n")
 		dump(re, a, indent + 1)
 	| `Quest	a:
-		std.f2put("Quest\n")
+		std.put("Quest\n")
 		dump(re, a, indent + 1)
 	| `Bol:
-		std.f2put("Bol\n")
+		std.put("Bol\n")
 	| `Eol:
-		std.f2put("Eol\n")
+		std.put("Eol\n")
 	| `Bow:
-		std.f2put("Bow\n")
+		std.put("Bow\n")
 	| `Eow:
-		std.f2put("Eow\n")
+		std.put("Eow\n")
 	/* end matches */
 	| `Byte	b:
-		std.f2put("Byte {}\n", b)
+		std.put("Byte {}\n", b)
 	| `Chr	c:
-		std.f2put("Char {}\n", c)
+		std.put("Char {}\n", c)
 	| `Ranges rl:
-                std.f2put("Ranges")
+                std.put("Ranges")
 		for r in rl
 			for i = 0; i < indent + 1; i++
-				std.f2put("  ")
+				std.put("  ")
 			;;
-			std.f2put("\t({}-{})\n", r[0], r[1])
+			std.put("\t({}-{})\n", r[0], r[1])
 		;;
 
 	/* meta */
 	| `Cap	(m, a):
-		std.f2put("Cap {}\n", m)
+		std.put("Cap {}\n", m)
 		dump(re, a, indent + 1)
 	;;
 }
--- a/libregex/interp.myr
+++ b/libregex/interp.myr
@@ -289,7 +289,7 @@
 
 	if re.debug
 		ap = std.vastart(&args)
-		std.f2putv(msg, &ap)
+		std.putv(msg, &ap)
 	;;
 }
 
--- a/libregex/redump.myr
+++ b/libregex/redump.myr
@@ -13,7 +13,7 @@
 	cmd = std.optparse(args, &opts)
 	match regex.dbgcompile(cmd.args[0])
 	| `std.Fail m:	
-		std.f2fatal("unable to compile regex: {}\n", regex.failmsg(m))
+		std.fatal("unable to compile regex: {}\n", regex.failmsg(m))
 	| `std.Ok re:
 		if cmd.args.len > 1
 			runall(re, cmd.args)
@@ -33,7 +33,7 @@
 			dump(re, fd)
 			bio.close(fd)
 		| `std.None:
-			std.f2fatal("failed to open {}\n", f)
+			std.fatal("failed to open {}\n", f)
 		;;
 	;;
 }
@@ -55,11 +55,11 @@
 
 	match mg
 	| `std.Some rl:
-		std.f2put("Matched: {}\n", rl[0])
+		std.put("Matched: {}\n", rl[0])
 		for i = 1; i < rl.len; i++
-			std.f2put("group {}: {}\n", i, rl[i])
+			std.put("group {}: {}\n", i, rl[i])
 		;;
 	| `std.None:
-		std.f2put("Match failed\n")
+		std.put("Match failed\n")
 	;;
 }
--- a/libstd/blat.myr
+++ b/libstd/blat.myr
@@ -1,5 +1,4 @@
 use "syswrap.use"
-use "fmt.use"
 
 pkg std =
 	const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
--- a/libstd/bld.sub
+++ b/libstd/bld.sub
@@ -39,8 +39,7 @@
 	extremum.myr
 	fltbits.myr
 	fltfmt.myr
-	fmt.myr
-        fmt2.myr
+        fmt.myr
 	getcwd.myr
 	getint.myr
 	hashfuncs.myr
--- a/libstd/dial+plan9.myr
+++ b/libstd/dial+plan9.myr
@@ -40,10 +40,10 @@
 	var buf	: byte[Maxpath]
 
 	/* Try using the connection server */
-	dir = fmt("%s/cs", netdir)
+	dir = fmt("{}/cs", netdir)
 	csfd = open(dir, Ordwr)
 	if csfd < 0
-		clone = fmt("%s/%s/clone", netdir, proto)
+		clone = fmt("{}/{}/clone", netdir, proto)
 		ret = call(clone, rem, netdir)
 		slfree(clone)
 		if ret == -1
@@ -54,7 +54,7 @@
 	;;
 	slfree(dir)
 
-	csaddr = fmt("%s!%s", proto, rem)
+	csaddr = fmt("{}!{}", proto, rem)
 	if write(csfd, csaddr) < 0
 		close(csfd)
 		-> `Fail "couldn't blah cs"
@@ -106,13 +106,13 @@
 	if n < 0
 		goto cleanup
 	;;
-	fput(cfd, "connect %s", addr)
+	fput(cfd, "connect {}", addr)
 	name = strstrip(namebuf[:n])
 	match strrfind(c, "/")
 	| `None:	die("there should be a '/' here\n")
 	| `Some i:	base = c[:i]
 	;;
-	dpath = bfmt(databuf[:], "%s/%s/data", base, name)
+	dpath = bfmt(databuf[:], "{}/{}/data", base, name)
 	datafd = open(dpath, Ordwr)
 :cleanup
 	close(cfd)
--- a/libstd/dial+posixy.myr
+++ b/libstd/dial+posixy.myr
@@ -4,7 +4,6 @@
 use "chartype.use"
 use "die.use"
 use "endian.use"
-use "fmt.use"
 use "hasprefix.use"
 use "intparse.use"
 use "ipparse.use"
--- a/libstd/execvp.myr
+++ b/libstd/execvp.myr
@@ -21,7 +21,7 @@
 	| `None:
 		paths = getpaths()
 		for p in paths
-			binpath = bfmt(buf[:], "%s/%s", p, cmd)
+			binpath = bfmt(buf[:], "{}/{}", p, cmd)
 			execv(binpath, args)
 		;;
 		slfree(paths)
@@ -39,7 +39,7 @@
 	| `None:
 		paths = getpaths()
 		for p in paths
-			binpath = bfmt(buf[:], "%s/%s", p, cmd)
+			binpath = bfmt(buf[:], "{}/{}", p, cmd)
 			execve(binpath, args, env)
 		;;
 		slfree(paths)
--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -1,10 +1,12 @@
-use sys
 use "alloc.use"
 use "chartype.use"
 use "die.use"
 use "extremum.use"
 use "fltfmt.use"
+use "htab.use"
+use "hashfuncs.use"
 use "introspect.use"
+use "option.use"
 use "strbuf.use"
 use "syswrap-ss.use"
 use "syswrap.use"
@@ -12,100 +14,348 @@
 use "utf.use"
 use "varargs.use"
 
-/*
-  printf-like functions. These use a different syntax from the C printf,
-  as described below:
-
-	  %s	- A string, ie, a utf8 encoded byte slice.
-	  %t	- A boolean
-	  %b	- A byte.
-	  %w	- A 16 bit integer
-	  %i	- A 32 bit integer
-	  %l	- A 64 bit integer
-	  %z	- A size
-	  %p	- A pointer
-	  %c	- A char
-*/
-
 pkg std =
+	/* write to fd */
 	const put	: (fmt : byte[:], args : ... -> size)
 	const fput	: (fd : fd, fmt : byte[:], args : ... -> size)
-	const putv	: (fmt : byte[:], ap : valist -> size)
-	const fputv	: (fd : fd, fmt : byte[:], ap : valist -> size)
+	const putv	: (fmt : byte[:], ap : valist# -> size)
+	const fputv	: (fd : fd, fmt : byte[:], ap : valist# -> size)
 
+	/* write to buffer */
 	const fmt	: (fmt : byte[:], args : ... -> byte[:])
-	const fmtv	: (fmt : byte[:], ap : valist -> byte[:])
+	const fmtv	: (fmt : byte[:], ap : valist# -> byte[:])
 	const bfmt	: (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
-	const bfmtv	: (buf : byte[:], fmt : byte[:], ap : valist -> byte[:])
+	const bfmtv	: (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:])
 
+	/* write to strbuf */
+	const sbfmt	: (buf : strbuf#, fmt : byte[:], args : ... -> size)
+	const sbfmtv	: (buf : strbuf#, fmt : byte[:], ap : valist# -> size)
+
+	/* add a formatter function */
+	const fmtinstall	: (ty : byte[:], \
+		fn : (sb : strbuf#, ap : valist#, opts : byte[:] -> void) \
+		-> void)
+
 	$noret const fatal	: (fmt : byte[:], args : ... -> void)
-	$noret const fatalv	: (fmt : byte[:], ap : valist -> void)
+	$noret const fatalv	: (fmt : byte[:], ap : valist# -> void)
 ;;
 
-/* Writes a string of text up to 2 kb in size to stdout */
-const put = {fmt, args
-	-> fputv(1, fmt, vastart(&args))
+/* same as 'put', but exits the program after printing */
+const fatal = {fmt, args
+	var ap
+
+	ap = vastart(&args)
+	putv(fmt, &ap)
+	exit(1)
 }
 
-const fput = {fd, fmt, args
-	-> fputv(fd, fmt, vastart(&args))
+/* same as 'putv', but exits the program after printing */
+const fatalv = {fmt, ap
+	putv(fmt, ap)
+	exit(1)
 }
 
+var fmtmapinited : bool = false
+var fmtmap : htab(byte[:], (sb : strbuf#, ap : valist#, opts : byte[:] -> void))#
+
+const fmtinstall = {ty, fn
+	if !fmtmapinited
+		fmtmapinited = true
+		fmtmap = mkht(strhash, streq)
+	;;
+	htput(fmtmap, ty, fn)
+}
+
+const put = {fmt, args
+	var ap
+
+	ap = vastart(&args)
+	-> fputv(1, fmt, &ap)
+}
+
 const putv = {fmt, ap
 	-> fputv(1, fmt, ap)
 }
 
-/* Writes a string of text up to 2kb long to stdout, using a valist
-   as the source of the arguments */
-const fputv = {fd, fmt, ap
-	var buf : byte[2048]
-	
-	-> write(fd, bfmtv(buf[:], fmt, ap))
-}
+const fput = {fd, fmt, args
+	var ap
 
-/* same as 'put', but exits the program after printing */
-const fatal = {fmt, args
-	putv(fmt, vastart(&args))
-	exit(1)
+	ap = vastart(&args)
+	-> fputv(fd, fmt, &ap)
 }
 
-/* same as 'putv', but exits the program after printing */
-const fatalv = {fmt, ap
-	putv(fmt, ap)
-	exit(1)
+const fputv = {fd, fmt, ap
+	var sb, s
+
+	sb = mksb()
+	sbfmtv(sb, fmt, ap)
+	s = sbfin(sb)
+	-> writeall(fd, s)
 }
 
-/* formats a string, allocating the slice. FIXME: calculate the
-   size needed. */
 const fmt = {fmt, args
-	-> fmtv(fmt, vastart(&args))
+	var ap
+
+	ap = vastart(&args)
+	-> fmtv(fmt, &ap)
 }
 
-/* formats a string, allocating the slice. FIXME: calculate the
-   size needed. Takes a valist as it's last argument. */
 const fmtv = {fmt, ap
-	var buf
+	var sb
 
-	buf = slalloc(2048)
-	-> bfmtv(buf, fmt, ap)
+	sb = mksb()
+	sbfmtv(sb, fmt, ap)
+	-> sbfin(sb)
 }
 
-/* formats a string of text as specified by 'fmt' into 'buf' */
 const bfmt = {buf, fmt, args
-	-> bfmtv(buf, fmt, vastart(&args))
+	var ap
+
+	ap = vastart(&args)
+	-> bfmtv(buf, fmt, &ap)
 }
 
+const bfmtv = {buf, fmt, ap
+	var sb
+
+	sb = mkbufsb(buf)
+	sbfmtv(sb, fmt, ap)
+	-> sbfin(sb)
+}
+
+const sbfmt = {sb, fmt, args
+	var ap
+
+	ap = vastart(&args)
+	-> sbfmtv(sb, fmt, &ap)
+}
+
+const sbfmtv = {sb, fmt, ap -> size
+	var c, params, ty
+	var nfmt, nparams
+
+	nparams = ap.tc.nelt
+	nfmt = 0
+	if !fmtmapinited
+		fmtmapinited = true
+		fmtmap = mkht(strhash, streq)
+	;;
+	while fmt.len != 0
+		(c, fmt) = striter(fmt)
+		match c
+		| '{':
+			if decode(fmt) == '{'
+				(c, fmt) = striter(fmt)
+				sbputc(sb, '{')
+			else
+				(params, fmt) = getparams(fmt)
+				nfmt++
+				if nfmt > nparams
+					die("too few params for fmt\n")
+				;;
+
+				ty = vatype(ap)
+				match htget(fmtmap, ty)
+				| `Some func:
+					func(sb, ap, params)
+				| `None:
+					fallbackfmt(sb, params, ty, ap)
+				;;
+			;;
+		| '}':
+			if decode(fmt) == '}'
+				sbputc(sb, '}')
+			;;
+		| chr:
+			sbputc(sb, chr)
+		;;
+:fmtdone
+	;;
+	if nfmt != nparams
+		die("too many params for fmt\n")
+	;;
+	-> sb.len
+}
+
+const fallbackfmt = {sb, params, tyenc, ap : valist# -> void
+	/* value types */
+	var t_val : bool
+	var b_val : int8, ub_val : uint8
+	var w_val : int16, uw_val : uint16
+	var i_val : int32, ui_val : uint32
+	var l_val : int64, ul_val : uint64
+	var z_val : size
+	var p_val : byte#
+        var c_val : char
+	var s_val : byte[:]
+	var f32_val : flt32, f64_val : flt64
+	var i8 : int8, i16: int16, i32 : int32
+	var by : byte
+	var i : int, i64 : int64, l : long
+	var ui8 : int8, ui16: int16, ui32 : int32
+	var ui : int, ui64 : int64, ul : long
+
+	match typedesc(tyenc)
+	| `Tynone:	/* nothing */
+	/* atomic types */
+	| `Tyvoid:
+		sbputs(sb, "void")
+	| `Tybool:
+		t_val = vanext(ap)
+		if t_val
+			sbputs(sb ,"true")
+		else
+			sbputs(sb, "false")
+		;;
+	| `Tychar:
+		c_val = vanext(ap)
+		sbputc(sb, c_val)
+	| `Tyint8:
+		b_val = vanext(ap)
+		intfmt(sb, intparams(params), true, b_val)
+	| `Tyint16:
+		w_val = vanext(ap)
+		intfmt(sb, intparams(params), true, w_val)
+	| `Tyint:
+		i_val = vanext(ap)
+		intfmt(sb, intparams(params), true, i_val)
+	| `Tyint32:
+		i_val = vanext(ap)
+		intfmt(sb, intparams(params), true, i_val)
+	| `Tyint64:
+		l_val = vanext(ap)
+		intfmt(sb, intparams(params), true, l_val)
+	| `Tylong:
+		l_val = vanext(ap)
+		intfmt(sb, intparams(params), true, l_val)
+
+	| `Tybyte:
+		ub_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ub_val)
+	| `Tyuint8:
+		ub_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ub_val)
+	| `Tyuint16:
+		w_val = vanext(ap)
+		intfmt(sb, intparams(params), false, uw_val)
+	| `Tyuint:
+		i_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ui_val)
+	| `Tyuint32:
+		i_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ui_val)
+	| `Tyuint64:
+		l_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ul_val)
+	| `Tyulong:
+		l_val = vanext(ap)
+		intfmt(sb, intparams(params), false, ul_val)
+	| `Tyflt32:
+		f32_val = vanext(ap)
+		flt32bfmt(sb, f32_val, MNormal, 0)
+	| `Tyflt64:
+		f64_val = vanext(ap)
+		flt64bfmt(sb, f64_val, MNormal, 0)
+	| `Tyvalist:
+		sbputs(sb, "...")
+
+	/* compound types */
+	| `Typtr desc:
+		p_val = vanext(ap)
+		sbputs(sb, "0x")
+		intfmt(sb, \
+			[.base=16, .padto=2*sizeof(void#), .padfill='0'], \
+			false, p_val castto(intptr))
+	| `Tyslice desc:
+		match typedesc(desc)
+		| `Tybyte:
+			s_val = vanext(ap)
+			sbputs(sb, s_val)
+		| _:
+			sbputs(sb, "slice[:]")
+		;;
+	| `Tyfunc tc:
+		p_val = vanext(ap)
+		sbputs(sb, "func{")
+		intfmt(sb, \
+			[.base=16, .padto=2*sizeof(void#), .padfill='0'], \
+			false, p_val castto(intptr))
+		sbputs(sb, "}")
+	| `Tyarray (sz, data):
+		sbputs(sb, "array")
+	/* aggregate types */
+	| `Tytuple typecursor:
+		vabytes(ap)
+		sbputs(sb, "tuple")
+	| `Tystruct namecursor:
+		vabytes(ap)
+		sbputs(sb, "struct")
+	| `Tyunion namecursor:
+		vabytes(ap)
+		sbputs(sb, "union")
+	| `Tyname (name, desc):
+		fallbackfmt(sb, params, desc, ap)
+	;;
+}
+
+type intparams = struct
+	base	: size
+	padto	: size
+	padfill	: char
+;;
+
+const getparams = {fmt
+	var i
+
+	for i = 0; i < fmt.len; i++
+		if fmt[i] == '}' castto(byte)
+			goto foundparams
+		;;
+	;;
+	die("invalid format string")
+:foundparams
+	-> (fmt[:i], fmt[i+1:])
+}
+
+const intparams = {params
+	var ip : intparams
+	var c
+
+	ip = [
+		.base = 10,
+		.padfill = ' ',
+		.padto = 0
+	]
+
+	while params.len > 0
+		(c, params) = striter(params)
+		match c
+		| 'x':	ip.base = 16
+		| '0':	ip.padfill = '0'
+		| chr:
+			while isdigit(c)
+				ip.padto = ip.padto*10 + charval(c, 10)
+				(c, params) = striter(params)
+			;;
+		;;
+	;;
+	-> ip
+
+}
+
 const digitchars = [
-	'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
+	'0','1','2','3','4',
+	'5','6','7','8','9',
+	'a','b','c','d','e','f'
 ]
-generic intfmt = {buf : byte[:], bits : @a::(integral,numeric), base, signed, padto, padfill
+generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric)
 	var isneg
 	var val
 	var b : char[32]
-	var i, j, n, npad
+	var i, j, npad
+	var base
 
-	n = 0
-	i = 0
+	base = opts.base castto(uint64)
 	if signed && bits < 0
 		val = -bits castto(uint64)
 		isneg = true
@@ -115,6 +365,7 @@
 		isneg = false
 	;;
 
+	i = 0
 	if val == 0
 		b[0] = '0'
 		i++
@@ -125,192 +376,35 @@
 		i++
 	;;
 
-	npad = clamp(padto - i, 0, padto)
-	n = 0
+	npad = clamp(opts.padto - i, 0, opts.padto)
 	if isneg
 		npad--
 	;;
-	if padfill == '0' && isneg && n < buf.len
-		n += encode(buf[n:], '-')
+	if opts.padfill == '0' && isneg
+		sbputc(sb, '-')
 	;;
-	for j = 0; j < min(npad, buf.len); j++
-		if n >= buf.len
-			break
-		;;
-		n += encode(buf[n:], padfill)
+	for j = 0; j < npad; j++
+		sbputc(sb, opts.padfill)
 	;;
-	if padfill != '0' && isneg && n < buf.len
-		n += encode(buf[n:], '-')
+	if opts.padfill != '0' && isneg
+		sbputc(sb, '-')
 	;;
 	for j = i; j != 0; j--
-		if n >= buf.len
-			break
-		;;
-		n += encode(buf[n:], b[j - 1])
+		sbputc(sb, b[j - 1])
 	;;
-	-> n 
 }
 
-/* formats a string of text as specified by 'fmt' into 'buf',
-   using a valist for the arguments */
-const bfmtv = {buf, fmt, ap
-	var b
-	var c
-	var n
-	var padto
-	var base
-	var signed, padfill
-	var s_val : byte[:]
-	var t_val : bool
-	var b_val : int8, ub_val : uint8
-	var w_val : int16, uw_val : uint16
-	var i_val : int32, ui_val : uint32
-	var l_val : int64, ul_val : uint64
-	var z_val : size
-	var p_val : byte#
-        var c_val : char
-	var f_val : flt64, F_val : flt32
-	var sb
+const writeall = {fd, buf
+	var n, len
 
-	n = 0
-	while fmt.len != 0
-		(c, fmt) = striter(fmt)
-		if c == '%'
-			base = 10
-			padto = 0
-			signed = true
-			padfill = ' '
-			(c, fmt) = striter(fmt)
-			/* modifiers */
-			while fmt.len > 0
-				match c
-				| 'x':
-					(c, fmt) = striter(fmt)
-					base = 16
-					signed = false
-						
-				| 'u':
-					(c, fmt) = striter(fmt)
-					signed = false
-				| '0':
-					(c, fmt) = striter(fmt)
-					padfill = '0'
-				| _:	/* nothing */
-				;;
-				if isdigit(c) && padto == 0
-					/*
-					We can't get a 0 on the first iteration, since
-					that was matched above. So, no special checks
-					for nonzero on the first iteration.
-					*/
-					padto = 0
-					while isdigit(c)
-						padto = padto*10 + charval(c, 10)
-						(c, fmt) = striter(fmt)
-					;;
-				else
-					break
-				;;
-			;;
-			/* format specifiers */
-			match c
-			| 's':
-				s_val = vanext(&ap)
-				n += strfmt(buf[n:], s_val, padto, padfill)
-			| 't':
-				t_val = vanext(&ap)
-				n += boolfmt(buf[n:], t_val, padto, padfill)
-			| 'f':
-				f_val = vanext(&ap)
-				b = buf[n:]
-				sb = mkbufsb(b)
-				flt64bfmt(sb, f_val, 0, b.len)
-				n += sb.len
-				strfmt(buf[n:], sbfin(sb), 0, ' ')
-			| 'F':
-				F_val = vanext(&ap)
-				b = buf[n:]
-				sb = mkbufsb(b)
-				flt64bfmt(sb, F_val castto(flt64), 0, b.len)
-				n += sb.len
-				strfmt(buf[n:], sbfin(sb), 0, ' ')
-			/* format integers */
-			| 'b':
-				if signed
-					b_val = vanext(&ap)
-					n += intfmt(buf[n:], b_val, base, signed, padto, padfill)
-				else
-					ub_val = vanext(&ap)
-					n += intfmt(buf[n:], ub_val, base, signed, padto, padfill)
-				;;
-			| 'w':
-				if signed
-					w_val = vanext(&ap)
-					n += intfmt(buf[n:], w_val, base, signed, padto, padfill)
-				else
-					uw_val = vanext(&ap)
-					n += intfmt(buf[n:], uw_val, base, signed, padto, padfill)
-				;;
-			| 'i':
-				if signed
-					i_val = vanext(&ap)
-					n += intfmt(buf[n:], i_val, base, signed, padto, padfill)
-				else
-					ui_val = vanext(&ap)
-					n += intfmt(buf[n:], ui_val, base, signed, padto, padfill)
-				;;
-			| 'l':
-				if signed
-					l_val = vanext(&ap)
-					n += intfmt(buf[n:], l_val, base, signed, padto, padfill)
-				else
-					ul_val = vanext(&ap)
-					n += intfmt(buf[n:], ul_val, base, signed, padto, padfill)
-				;;
-
-			| 'z':
-				z_val = vanext(&ap)
-				n += intfmt(buf[n:], z_val castto(int64), base, signed, padto, padfill)
-			| 'p':
-				p_val = vanext(&ap)
-				n += intfmt(buf[n:], p_val castto(int64), 16, false, padto, padfill)
-			| 'c':
-				c_val = vanext(&ap)
-				n += encode(buf[n:], c_val)
-			| '%':
-				n += encode(buf[n:], '%')
-                        | _:
-                                die("Unknown format specifier\n")
-			;;
-		else
-			n += encode(buf[n:], c)
+	len = 0
+	while true
+		n = write(fd, buf)
+		if n <= 0 || n >= len
+			break
 		;;
+		len += n
 	;;
-	-> buf[:n]
-}
-
-const strfmt = {buf, str, padto, padfill
-	var i, n, npad
-
-	n = 0
-	npad = clamp(padto - str.len, 0, padto)
-	for i = 0; i < padto - str.len; i++
-		n += encode(buf[n:], padfill)
-	;;
-	for i = 0; i < min(str.len, buf.len); i++
-		buf[n++] = str[i]
-	;;
-	-> n
-}
-
-const boolfmt = {buf, val, padto, padfill
-	var s
-
-	if val
-		s = "true"
-	else
-		s = "false"
-	;;
-	-> strfmt(buf, s, padto, padfill)
+	-> len
 }
 
--- a/libstd/fmt2.myr
+++ /dev/null
@@ -1,412 +1,0 @@
-use "alloc.use"
-use "chartype.use"
-use "die.use"
-use "extremum.use"
-use "fltfmt.use"
-use "htab.use"
-use "hashfuncs.use"
-use "introspect.use"
-use "option.use"
-use "strbuf.use"
-use "syswrap-ss.use"
-use "syswrap.use"
-use "types.use"
-use "utf.use"
-use "varargs.use"
-
-use "fmt.use" 	/* FOR DEBUGGING */
-
-pkg std =
-	/* write to fd */
-	const f2put	: (fmt : byte[:], args : ... -> size)
-	const f2fput	: (fd : fd, fmt : byte[:], args : ... -> size)
-	const f2putv	: (fmt : byte[:], ap : valist# -> size)
-	const f2fputv	: (fd : fd, fmt : byte[:], ap : valist# -> size)
-
-	/* write to buffer */
-	const f2fmt	: (fmt : byte[:], args : ... -> byte[:])
-	const f2fmtv	: (fmt : byte[:], ap : valist# -> byte[:])
-	const f2bfmt	: (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
-	const f2bfmtv	: (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:])
-
-	/* write to strbuf */
-	const f2sbfmt	: (buf : strbuf#, fmt : byte[:], args : ... -> size)
-	const f2sbfmtv	: (buf : strbuf#, fmt : byte[:], ap : valist# -> size)
-
-	/* add a formatter function */
-	const f2fmtinstall	: (ty : byte[:], \
-		fn : (sb : strbuf#, ap : valist#, opts : byte[:] -> void) \
-		-> void)
-
-	$noret const f2fatal	: (fmt : byte[:], args : ... -> void)
-	$noret const f2fatalv	: (fmt : byte[:], ap : valist# -> void)
-;;
-
-/* same as 'put', but exits the program after printing */
-const f2fatal = {fmt, args
-	var ap
-
-	ap = vastart(&args)
-	f2putv(fmt, &ap)
-	exit(1)
-}
-
-/* same as 'putv', but exits the program after printing */
-const f2fatalv = {fmt, ap
-	f2putv(fmt, ap)
-	exit(1)
-}
-
-var fmtmapinited : bool = false
-var fmtmap : htab(byte[:], (sb : strbuf#, ap : valist#, opts : byte[:] -> void))#
-
-const f2fmtinstall = {ty, fn
-	if !fmtmapinited
-		fmtmapinited = true
-		fmtmap = mkht(strhash, streq)
-	;;
-	htput(fmtmap, ty, fn)
-}
-
-const f2put = {fmt, args
-	var ap
-
-	ap = vastart(&args)
-	-> f2fputv(1, fmt, &ap)
-}
-
-const f2putv = {fmt, ap
-	-> f2fputv(1, fmt, ap)
-}
-
-const f2fput = {fd, fmt, args
-	var ap
-
-	ap = vastart(&args)
-	-> f2fputv(fd, fmt, &ap)
-}
-
-const f2fputv = {fd, fmt, ap
-	var sb, s
-
-	sb = mksb()
-	f2sbfmtv(sb, fmt, ap)
-	s = sbfin(sb)
-	-> writeall(fd, s)
-}
-
-const f2fmt = {fmt, args
-	var ap
-
-	ap = vastart(&args)
-	-> f2fmtv(fmt, &ap)
-}
-
-const f2fmtv = {fmt, ap
-	var sb
-
-	sb = mksb()
-	f2sbfmtv(sb, fmt, ap)
-	-> sbfin(sb)
-}
-
-const f2bfmt = {buf, fmt, args
-	var ap
-
-	ap = vastart(&args)
-	-> f2bfmtv(buf, fmt, &ap)
-}
-
-const f2bfmtv = {buf, fmt, ap
-	var sb
-
-	sb = mkbufsb(buf)
-	f2sbfmtv(sb, fmt, ap)
-	-> sbfin(sb)
-}
-
-const f2sbfmt = {sb, fmt, args
-	var ap
-
-	ap = vastart(&args)
-	-> f2sbfmtv(sb, fmt, &ap)
-}
-
-const f2sbfmtv = {sb, fmt, ap -> size
-	var c, params, ty
-	var nfmt, nparams
-
-	nparams = ap.tc.nelt
-	nfmt = 0
-	if !fmtmapinited
-		fmtmapinited = true
-		fmtmap = mkht(strhash, streq)
-	;;
-	while fmt.len != 0
-		(c, fmt) = striter(fmt)
-		match c
-		| '{':
-			if decode(fmt) == '{'
-				(c, fmt) = striter(fmt)
-				sbputc(sb, '{')
-			else
-				(params, fmt) = f2getparams(fmt)
-				nfmt++
-				if nfmt > nparams
-					die("too few params for fmt\n")
-				;;
-
-				ty = vatype(ap)
-				match htget(fmtmap, ty)
-				| `Some func:
-					func(sb, ap, params)
-				| `None:
-					fallbackfmt(sb, params, ty, ap)
-				;;
-			;;
-		| '}':
-			if decode(fmt) == '}'
-				sbputc(sb, '}')
-			;;
-		| chr:
-			sbputc(sb, chr)
-		;;
-:fmtdone
-	;;
-	if nfmt != nparams
-		die("too many params for fmt\n")
-	;;
-	-> sb.len
-}
-
-const fallbackfmt = {sb, params, tyenc, ap : valist# -> void
-	/* value types */
-	var t_val : bool
-	var b_val : int8, ub_val : uint8
-	var w_val : int16, uw_val : uint16
-	var i_val : int32, ui_val : uint32
-	var l_val : int64, ul_val : uint64
-	var z_val : size
-	var p_val : byte#
-        var c_val : char
-	var s_val : byte[:]
-	var f32_val : flt32, f64_val : flt64
-	var i8 : int8, i16: int16, i32 : int32
-	var by : byte
-	var i : int, i64 : int64, l : long
-	var ui8 : int8, ui16: int16, ui32 : int32
-	var ui : int, ui64 : int64, ul : long
-
-	match typedesc(tyenc)
-	| `Tynone:	/* nothing */
-	/* atomic types */
-	| `Tyvoid:
-		sbputs(sb, "void")
-	| `Tybool:
-		t_val = vanext(ap)
-		if t_val
-			sbputs(sb ,"true")
-		else
-			sbputs(sb, "false")
-		;;
-	| `Tychar:
-		c_val = vanext(ap)
-		sbputc(sb, c_val)
-	| `Tyint8:
-		b_val = vanext(ap)
-		intfmt(sb, intparams(params), true, b_val)
-	| `Tyint16:
-		w_val = vanext(ap)
-		intfmt(sb, intparams(params), true, w_val)
-	| `Tyint:
-		i_val = vanext(ap)
-		intfmt(sb, intparams(params), true, i_val)
-	| `Tyint32:
-		i_val = vanext(ap)
-		intfmt(sb, intparams(params), true, i_val)
-	| `Tyint64:
-		l_val = vanext(ap)
-		intfmt(sb, intparams(params), true, l_val)
-	| `Tylong:
-		l_val = vanext(ap)
-		intfmt(sb, intparams(params), true, l_val)
-
-	| `Tybyte:
-		ub_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ub_val)
-	| `Tyuint8:
-		ub_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ub_val)
-	| `Tyuint16:
-		w_val = vanext(ap)
-		intfmt(sb, intparams(params), false, uw_val)
-	| `Tyuint:
-		i_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ui_val)
-	| `Tyuint32:
-		i_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ui_val)
-	| `Tyuint64:
-		l_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ul_val)
-	| `Tyulong:
-		l_val = vanext(ap)
-		intfmt(sb, intparams(params), false, ul_val)
-	| `Tyflt32:
-		f32_val = vanext(ap)
-		flt32bfmt(sb, f32_val, MNormal, 0)
-	| `Tyflt64:
-		f64_val = vanext(ap)
-		flt64bfmt(sb, f64_val, MNormal, 0)
-	| `Tyvalist:
-		sbputs(sb, "...")
-
-	/* compound types */
-	| `Typtr desc:
-		p_val = vanext(ap)
-		sbputs(sb, "0x")
-		intfmt(sb, \
-			[.base=16, .padto=2*sizeof(void#), .padfill='0'], \
-			false, p_val castto(intptr))
-	| `Tyslice desc:
-		match typedesc(desc)
-		| `Tybyte:
-			s_val = vanext(ap)
-			sbputs(sb, s_val)
-		| _:
-			sbputs(sb, "slice[:]")
-		;;
-	| `Tyfunc tc:
-		p_val = vanext(ap)
-		sbputs(sb, "func{")
-		intfmt(sb, \
-			[.base=16, .padto=2*sizeof(void#), .padfill='0'], \
-			false, p_val castto(intptr))
-		sbputs(sb, "}")
-	| `Tyarray (sz, data):
-		sbputs(sb, "array")
-	/* aggregate types */
-	| `Tytuple typecursor:
-		vabytes(ap)
-		sbputs(sb, "tuple")
-	| `Tystruct namecursor:
-		vabytes(ap)
-		sbputs(sb, "struct")
-	| `Tyunion namecursor:
-		vabytes(ap)
-		sbputs(sb, "union")
-	| `Tyname (name, desc):
-		fallbackfmt(sb, params, desc, ap)
-	;;
-}
-
-type intparams = struct
-	base	: size
-	padto	: size
-	padfill	: char
-;;
-
-const f2getparams = {fmt
-	var i
-
-	for i = 0; i < fmt.len; i++
-		if fmt[i] == '}' castto(byte)
-			goto foundparams
-		;;
-	;;
-	die("invalid format string")
-:foundparams
-	-> (fmt[:i], fmt[i+1:])
-}
-
-const intparams = {params
-	var ip : intparams
-	var c
-
-	ip = [
-		.base = 10,
-		.padfill = ' ',
-		.padto = 0
-	]
-
-	while params.len > 0
-		(c, params) = striter(params)
-		match c
-		| 'x':	ip.base = 16
-		| '0':	ip.padfill = '0'
-		| chr:
-			while isdigit(c)
-				ip.padto = ip.padto*10 + charval(c, 10)
-				(c, params) = striter(params)
-			;;
-		;;
-	;;
-	-> ip
-
-}
-
-const digitchars = [
-	'0','1','2','3','4',
-	'5','6','7','8','9',
-	'a','b','c','d','e','f'
-]
-generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric)
-	var isneg
-	var val
-	var b : char[32]
-	var i, j, npad
-	var base
-
-	base = opts.base castto(uint64)
-	if signed && bits < 0
-		val = -bits castto(uint64)
-		isneg = true
-	else
-		val = bits castto(uint64)
-		val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a)))
-		isneg = false
-	;;
-
-	i = 0
-	if val == 0
-		b[0] = '0'
-		i++
-	;;
-	while val != 0
-		b[i] = digitchars[val % base]
-		val /= base
-		i++
-	;;
-
-	npad = clamp(opts.padto - i, 0, opts.padto)
-	if isneg
-		npad--
-	;;
-	if opts.padfill == '0' && isneg
-		sbputc(sb, '-')
-	;;
-	for j = 0; j < npad; j++
-		sbputc(sb, opts.padfill)
-	;;
-	if opts.padfill != '0' && isneg
-		sbputc(sb, '-')
-	;;
-	for j = i; j != 0; j--
-		sbputc(sb, b[j - 1])
-	;;
-}
-
-const writeall = {fd, buf
-	var n, len
-
-	len = 0
-	while true
-		n = write(fd, buf)
-		if n <= 0 || n >= len
-			break
-		;;
-		len += n
-	;;
-	-> len
-}
-
--- a/libstd/htab.myr
+++ b/libstd/htab.myr
@@ -1,7 +1,6 @@
 use "alloc.use"
 use "die.use"
 use "extremum.use"
-use "fmt.use"
 use "option.use"
 use "types.use"
 
--- a/libstd/intparse.myr
+++ b/libstd/intparse.myr
@@ -1,6 +1,5 @@
 use "chartype.use"
 use "die.use"
-use "fmt.use"
 use "hasprefix.use"
 use "option.use"
 use "types.use"
--- a/libstd/optparse.myr
+++ b/libstd/optparse.myr
@@ -1,7 +1,7 @@
 use "alloc.use"
 use "die.use"
 use "extremum.use"
-use "fmt2.use"
+use "fmt.use"
 use "option.use"
 use "sleq.use"
 use "slpush.use"
@@ -62,7 +62,7 @@
 		parsed.opts = slpush(parsed.opts, optnext(&ctx))
 	;;
 	if ctx.args.len < def.minargs
-		f2put("error: expected at least {} args, got {}\n", def.minargs, ctx.args.len)
+		put("error: expected at least {} args, got {}\n", def.minargs, ctx.args.len)
 		optusage(ctx.optargs[0], ctx.optdef)
 		exit(1)
 	;;
@@ -97,7 +97,7 @@
 			optusage(ctx.optargs[0], ctx.optdef)
 			exit(0)
 		else
-			f2fatal("unexpected argument '{}'\n", c)
+			fatal("unexpected argument '{}'\n", c)
 		;;
 	| `Some (true, needed):
 		/* -arg => '-a' 'rg' */
@@ -111,7 +111,7 @@
 			ctx.argidx++
 			next(ctx)
 		elif needed
-			f2put("Expected argument for {}\n", c)
+			put("Expected argument for {}\n", c)
 			exit(1)
 		;;
 	| `Some (false, _):
@@ -162,15 +162,15 @@
 }
 
 const optusage = {prog, def
-	std.f2put("usage: {} [-h?] ", prog)
+	std.put("usage: {} [-h?] ", prog)
 	for o in def.opts
-		std.f2put("[-{}{}{}] ", o.opt, sep(o.arg), o.arg)
+		std.put("[-{}{}{}] ", o.opt, sep(o.arg), o.arg)
 	;;
-	std.f2put("{}\n", def.argdesc)
-	std.f2put("\t-h\tprint this help message\n")
-	std.f2put("\t-?\tprint this help message\n")
+	std.put("{}\n", def.argdesc)
+	std.put("\t-h\tprint this help message\n")
+	std.put("\t-?\tprint this help message\n")
 	for o in def.opts
-		std.f2put("\t-{}{}{}\t{}\n", o.opt, sep(o.arg), o.arg, o.desc)
+		std.put("\t-{}{}{}\t{}\n", o.opt, sep(o.arg), o.arg, o.desc)
 	;;
 }
 
--- a/libstd/pathjoin.myr
+++ b/libstd/pathjoin.myr
@@ -92,7 +92,7 @@
 			;;
 		;;
 		s = strjoin(comps[i:], "/")
-		ret = fmt("/%s", s)
+		ret = fmt("/{}", s)
 		slfree(s)
 	elif comps.len == 0
 		ret = sldup(".")
--- a/libstd/rand.myr
+++ b/libstd/rand.myr
@@ -1,5 +1,4 @@
 use "die.use"
-use "fmt.use"
 use "types.use"
 use "alloc.use"
 /*
--- a/libstd/resolve+posixy.myr
+++ b/libstd/resolve+posixy.myr
@@ -5,7 +5,6 @@
 use "endian.use"
 use "result.use"
 use "extremum.use"
-use "fmt.use"
 use "hashfuncs.use"
 use "htab.use"
 use "ipparse.use"
--- a/libstd/search.myr
+++ b/libstd/search.myr
@@ -1,6 +1,5 @@
 use "cmp.use"
 use "option.use"
-use "fmt.use"
 
 pkg std =
 	generic lsearch	: (sl : @t[:], val : @t, cmp : (a : @t, b : @t -> order) -> option(@idx::(integral,numeric)))
--- a/libstd/slput.myr
+++ b/libstd/slput.myr
@@ -1,7 +1,6 @@
 use "types.use"
 use "alloc.use"
 use "die.use"
-use "fmt.use"
 
 pkg std =
 	generic slput	: (sl : @a[:], idx : size, elt : @a	-> @a[:])
--- a/libstd/slurp.myr
+++ b/libstd/slurp.myr
@@ -2,7 +2,6 @@
 use "die.use"
 use "result.use"
 use "extremum.use"
-use "fmt.use"
 use "syswrap.use"
 use "types.use"
 
--- a/libstd/spork.myr
+++ b/libstd/spork.myr
@@ -53,7 +53,7 @@
 		close(infd)
 		close(outfd)
 		execvp(cmd[0], cmd) < 0
-		fatal("failed to exec %s\n")
+		fatal("failed to exec {}\n", cmd[0])
 	/* parent */
 	else
 		-> `Ok pid
--- a/libstd/strsplit.myr
+++ b/libstd/strsplit.myr
@@ -1,7 +1,6 @@
 use "alloc.use"
 use "die.use"
 use "extremum.use"
-use "fmt.use"
 use "option.use"
 use "slpush.use"
 use "strfind.use"
--- a/mbld/build.myr
+++ b/mbld/build.myr
@@ -52,7 +52,7 @@
 	| `std.Some (`Gen gt):	runin(b, gt.cmd, gt.dir)
 	| `std.Some (`Cmd ct):	runin(b, ct.cmd, ct.dir)
 	| `std.Some (`Man mt):	/* nothing needed */
-	| `std.None:	std.f2fatal("invalid target {}\n", targ)
+	| `std.None:	std.fatal("invalid target {}\n", targ)
 	;;
 	-> true
 }
@@ -67,10 +67,10 @@
 
 	setdir(b, targ.dir)
 	addincludes(b, targ)
-	std.f2put("{}...\n", targ.name)
+	std.put("{}...\n", targ.name)
 	dg = myrdeps(b, targ, false, addsrc)
 	if !std.hthas(dg.deps, targ.name)
-		std.f2fatal("no input files for {}\n", targ.name)
+		std.fatal("no input files for {}\n", targ.name)
 	;;
 	if builddep(b, dg, targ.name, targ.incpath) || !freshlibs(targ, dg.libs)
 		src = std.htkeys(dg.sources)
@@ -88,11 +88,11 @@
 	setdir(b, targ.dir)
 	addincludes(b, targ)
 	lib = targ.name
-	std.f2put("lib{}.a...\n", lib)
-	archive = std.f2fmt("lib{}.a", lib)
+	std.put("lib{}.a...\n", lib)
+	archive = std.fmt("lib{}.a", lib)
 	dg = myrdeps(b, targ, false, false)
 	if !std.hthas(dg.deps, lib)
-		std.f2fatal("no target declared for {}\n", lib)
+		std.fatal("no target declared for {}\n", lib)
 	;;
 	u = builddep(b, dg, targ.name, targ.incpath)
 	l = builddep(b, dg, archive, targ.incpath)
@@ -155,7 +155,7 @@
 				;;
 			| `std.None:
 				if !std.fexists(d)
-					std.f2fatal("no input file {}\n", d)
+					std.fatal("no input file {}\n", d)
 				;;
 			;;
 			if !isfresh(d, out)
@@ -204,7 +204,7 @@
 		run(cmd)
 		std.slfree(o)
 	else
-		std.f2fatal("Unknown file type for {}\n", src)
+		std.fatal("Unknown file type for {}\n", src)
 	;;
 }
 
@@ -257,7 +257,7 @@
 	for c in config.Arcmd
 		cmd = std.slpush(cmd, std.sldup(c))
 	;;
-	cmd = std.slpush(cmd, std.f2fmt("lib{}.a", lib))
+	cmd = std.slpush(cmd, std.fmt("lib{}.a", lib))
 	for f in files
 		obj = srcswapsuffix(f, config.Objsuffix)
 		cmd = std.slpush(cmd, obj)
@@ -277,7 +277,7 @@
 		if std.hassuffix(f, ".myr")
 			cmd = std.slpush(cmd, srcswapsuffix(f, ".use"))
 		elif !std.hassuffix(f, ".s")
-			std.f2fatal("unknown file type for {}\n", f)
+			std.fatal("unknown file type for {}\n", f)
 		;;
 	;;
 	run(cmd)
@@ -293,7 +293,7 @@
 	/* -L incpath... */
 	if !config.Directlib
 		for inc in incs
-			cmd = std.slpush(cmd, std.f2fmt("-L{}", inc))
+			cmd = std.slpush(cmd, std.fmt("-L{}", inc))
 		;;
 	;;
 
@@ -311,7 +311,7 @@
 
 const visit = {cmd, head, g, lib, looped, marked, incs
 	if std.hthas(looped, lib)
-		std.f2fatal("cycle in library graph involving \"{}\"\n", lib)
+		std.fatal("cycle in library graph involving \"{}\"\n", lib)
 	elif std.hthas(marked, lib)
 		-> cmd
 	;;
@@ -327,11 +327,11 @@
 
 const putlib = {cmd, head, lib, incs
 	if !config.Directlib
-		-> std.slput(cmd, head, std.f2fmt("-l", lib))
+		-> std.slput(cmd, head, std.fmt("-l{}", lib))
 	else
 		match findlib(lib, incs)
 		| `std.None:
-			std.f2fatal("could not find library lib{}.a\n", lib)
+			std.fatal("could not find library lib{}.a\n", lib)
 		| `std.Some p:
 			-> std.slput(cmd, head, p)
 		;;
@@ -342,7 +342,7 @@
 	var buf : byte[512]
 	var sl, p
 
-	sl = std.bfmt(buf[:], "lib%s.a", lib)
+	sl = std.bfmt(buf[:], "lib{}.a", lib)
 	for i in incs
 		p = std.pathcat(i, sl)
 		if std.fexists(p)
@@ -366,10 +366,10 @@
 			;;
 			std.slfree(lib)
 		| `std.None:
-			std.f2fput(1, "{}: could not find library lib{}.a\n", targ.name, l)
-			std.f2fput(1, "searched:\n")
+			std.fput(1, "{}: could not find library lib{}.a\n", targ.name, l)
+			std.fput(1, "searched:\n")
 			for inc in targ.incpath
-				std.f2fput(1, "\t{}\n", inc)
+				std.fput(1, "\t{}\n", inc)
 			;;
 			std.exit(1)
 		;;
@@ -401,7 +401,7 @@
 	*/
 	match std.fmtime(src)
 	| `std.Some mt:	srcmt = mt
-	| `std.None:	std.f2fatal("could not stat {}\n", src)
+	| `std.None:	std.fatal("could not stat {}\n", src)
 	;;
 	match std.fmtime(dst)
 	| `std.Some mt:	dstmt = mt
--- a/mbld/clean.myr
+++ b/mbld/clean.myr
@@ -24,7 +24,7 @@
 		| `Gen gt:
 			for f in gt.out
 				if !gt.durable && std.remove(f)
-					std.f2put("\tclean {}\n", f)
+					std.put("\tclean {}\n", f)
 				;;
 			;;
 		| `Cmd ct:	/* nothing to do */
@@ -52,7 +52,7 @@
 		| `Gen gt:
 			for f in gt.out
 				if !gt.durable && std.remove(f)
-					std.f2put("\tclean {}\n", f)
+					std.put("\tclean {}\n", f)
 				;;
 			;;
 		| `Cmd ct:
@@ -80,7 +80,7 @@
 	keys = std.htkeys(dg.deps)
 	for k in keys
 		if !std.htgetv(mchammer_files, k, false) && std.remove(k)
-			std.f2put("\tclean {}\n", k)
+			std.put("\tclean {}\n", k)
 		;;
 	;;
 }
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -48,7 +48,7 @@
 	])
 	/* direct dependencies of binary */
 	if mt.islib
-		out = std.f2fmt("lib{}.a", mt.name)
+		out = std.fmt("lib{}.a", mt.name)
 		useout = std.sldup(mt.name)
 	else
 		out = std.sldup(mt.name)
@@ -106,13 +106,13 @@
 		->
 	;;
 	keys = std.htkeys(dg.deps)
-	std.f2put("digraph dg {{\n")
+	std.put("digraph dg {{\n")
 	for k in keys
 		for v in std.htgetv(dg.deps, k, ["WTFUNKNOWN!"][:])
-			std.f2put("\t\"{}\" -> \"{}\";\n", k, v)
+			std.put("\t\"{}\" -> \"{}\";\n", k, v)
 		;;
 	;;
-	std.f2put("}\n")
+	std.put("}\n")
 }
 
 const srcdeps = {b, ds, g, path, obj, usefile
@@ -124,7 +124,7 @@
 
 	ds.depstk = std.slpush(ds.depstk, path)
 	if std.htgetv(g.seen, path, false)
-		std.f2fput(1, "dependency loop involving {}:\n", path)
+		std.fput(1, "dependency loop involving {}:\n", path)
 		for d in ds.depstk
 			std.fput(1, "\t{}\n", d)
 		;;
@@ -144,7 +144,7 @@
 			;;
 		| `Local (l, lnum):
 			if !std.hassuffix(l, ".use")
-				std.f2fatal("{}:{}: local dependency \"{}\" should end with .use\n", path, lnum, l)
+				std.fatal("{}:{}: local dependency \"{}\" should end with .use\n", path, lnum, l)
 			;;
 			if obj.len != 0
 				pushdep(g, l, obj)
@@ -165,7 +165,7 @@
 
 	if std.hthas(g.done, usefile)
 		if opt_debug
-			std.f2put("already loaded deps for {}\n", usefile)
+			std.put("already loaded deps for {}\n", usefile)
 		;;
 		->
 	;;
@@ -177,7 +177,7 @@
 		if ds.addsrc
 			std.htput(g.sources, src, true)
 		elif !std.hthas(g.input, usefile)
-			std.f2fatal("{}:{}: source file {} not listed in bldfile\n", f, line, src)
+			std.fatal("{}:{}: source file {} not listed in bldfile\n", f, line, src)
 		;;
 	;;
 	pushdep(g, src, usefile)
@@ -194,12 +194,12 @@
 	if !std.fexists(path)
 		match std.htget(b.gensrc, path)
 		| `std.Some gt:	run(gt.cmd)
-		| `std.None:	std.f2fatal("no input file {}\n", path)
+		| `std.None:	std.fatal("no input file {}\n", path)
 		;;
 	;;
 	match bio.open(path, bio.Rd)
 	| `std.Some fd:	f = fd
-	| `std.None:	std.f2fatal("could not open {}\n", path)
+	| `std.None:	std.fatal("could not open {}\n", path)
 	;;
 
 	lnum = 0
@@ -230,14 +230,14 @@
 	f = openlib(lib, incs)
 	match bio.getc(f)
 	| `std.Some 'U': /* nothing */
-	| `std.Some _:	std.f2fatal("library {}: corrupt or invalid usefile\n", lib)
-	| `std.None:	std.f2fatal("library {}: could not read usefile\n", lib)
+	| `std.Some _:	std.fatal("library {}: corrupt or invalid usefile\n", lib)
+	| `std.None:	std.fatal("library {}: could not read usefile\n", lib)
 	;;
 	match bio.getbe32(f)
 	| `std.Some 1:	/* nothing: version matches. */
-	| `std.Some 0:	std.f2fput(1, "library {}: warning: old usefile version\n", lib)
-	| `std.Some _:	std.f2fatal("library {}: usefile version unknown\n", lib)
-	| `std.None:	std.f2fatal("library {}: corrutpt or invalid usefile\n", lib)
+	| `std.Some 0:	std.fput(1, "library {}: warning: old usefile version\n", lib)
+	| `std.Some _:	std.fatal("library {}: usefile version unknown\n", lib)
+	| `std.None:	std.fatal("library {}: corrutpt or invalid usefile\n", lib)
 	;;
 	std.slfree(rdstr(f))
 	done = false
@@ -276,7 +276,7 @@
 	| `std.None:
 		/* nothing */
 	;;
-	std.f2fatal("could not find library {}.\n", lib)
+	std.fatal("could not find library {}.\n", lib)
 }
 
 const depname = {deps, ln, lnum
@@ -304,7 +304,7 @@
 	var sl
 
 	if opt_debug
-		std.f2put("{} <= {}\n", dst, src)
+		std.put("{} <= {}\n", dst, src)
 	;;
 	std.assert(dst.len < 200, "BUG!")
 	sl = std.htgetv(dg.deps, dst, [][:])
--- a/mbld/fsel.myr
+++ b/mbld/fsel.myr
@@ -35,11 +35,11 @@
 		basename = f[:i]
 		match std.strrfind(f[i+1:], ".")
 		| `std.Some j:	attrs = f[i+1:][:j]
-		| `std.None:	std.fatal("unrecognized type for file %s\n", f)
+		| `std.None:	std.fatal("unrecognized type for file {}\n", f)
 		;;
 	| `std.None:
 		match std.strrfind(f, ".")
-		| `std.None:	std.fatal("unrecognized type for file %s\n", f)
+		| `std.None:	std.fatal("unrecognized type for file {}\n", f)
 		| `std.Some i:
 			basename = f[:i]
 			attrs = ""
@@ -72,7 +72,7 @@
 	for k in keys
 		nmatch = std.htgetv(fsel._match, k, -1)
 		if nmatch == -1
-			std.fatal("no applicable file for '%s'\n", k)
+			std.fatal("no applicable file for '{}'\n", k)
 		;;
 		ret = std.slpush(ret, std.htgetv(fsel._best, k, ""))
 	;;
@@ -89,7 +89,7 @@
 	| "osx":	attrs = ["osx", "posixy"][:]
 	| "linux":	attrs = ["linux", "posixy"][:]
 	| "plan9":	attrs = ["plan9"][:]
-	| unknown:	std.fatal("unknown system \"%s\"\n", unknown)
+	| unknown:	std.fatal("unknown system \"{}\"\n", unknown)
 	;;
 	for a in attrs
 		std.htput(sa, a, true)
@@ -97,7 +97,7 @@
 
 	match opt_arch
 	| "x64":	attrs = ["x64"][:]
-	| unknown:	std.fatal("unknown arch %s\n", unknown)
+	| unknown:	std.fatal("unknown arch {}\n", unknown)
 	;;
 	for a in attrs
 		std.htput(sa, a, true)
--- a/mbld/install.myr
+++ b/mbld/install.myr
@@ -34,7 +34,7 @@
 		| `Lib lt:
 			if lt.install
 				movefile(b, rm, lt.dir, lt.name, config.Libpath, 0o644)
-				libarchive = std.f2fmt("lib{}.a", lt.name)
+				libarchive = std.fmt("lib{}.a", lt.name)
 				movefile(b, rm, lt.dir, libarchive, config.Libpath, 0o644)
 				std.slfree(libarchive)
 			;;
@@ -60,18 +60,18 @@
 	setdir(b, dir)
 	path = std.pathjoin([opt_destdir, opt_instroot, prefix, file][:])
 	if rm
-		std.f2put("\trm {}\n", path)
+		std.put("\trm {}\n", path)
 		if !std.remove(path)
-			std.f2put("\t\tno such file {}\n", file)
+			std.put("\t\tno such file {}\n", file)
 		;;
 	else
-		std.f2put("\t{} => {}\n", file, path)
+		std.put("\t{} => {}\n", file, path)
 		std.remove(path)
 		match std.slurp(file)
-		| `std.Fail m:	std.f2fatal("Could not open {} for reading\n", file)
+		| `std.Fail m:	std.fatal("Could not open {} for reading\n", file)
 		| `std.Ok buf:
 			if !std.blat(path, buf, perm)
-				std.f2put("Could not write {}\n", file)
+				std.put("Could not write {}\n", file)
 			;;
 			std.slfree(buf)
 		;;
@@ -84,15 +84,15 @@
 
 	match std.strrfind(man, ".")
 	| `std.None:
-		std.f2fatal("manpage {} has no section\n", man)
+		std.fatal("manpage {} has no section\n", man)
 	| `std.Some s:
 		sect = s + 1
 		if s + 1 == man.len
-			std.f2fatal("manpage {} missing suffix\n", man)
+			std.fatal("manpage {} missing suffix\n", man)
 		;;
 	;;
 
-	manrel = std.f2fmt("{}{}", opt_manpath, man[sect:])
+	manrel = std.fmt("{}{}", opt_manpath, man[sect:])
 	movefile(b, rm, dir, man, manrel, 0o644)
 	std.slfree(manrel)
 }
--- a/mbld/main.myr
+++ b/mbld/main.myr
@@ -96,7 +96,7 @@
 		findproj(b, "bld.proj")
 		bld.load(b)
 		for t in b.all
-			std.f2put("{}\n", t)
+			std.put("{}\n", t)
 		;;
 	else
 		findproj(b, "bld.proj")
@@ -133,7 +133,7 @@
 
 const findproj = {b, bldfile
 	if !findbase(b, bldfile) || !std.chdir(b.basedir)
-		std.f2fatal("could not find {}\n", bldfile)
+		std.fatal("could not find {}\n", bldfile)
 	;;
 	bld.setdir(b, "")
 }
--- a/mbld/opts.myr
+++ b/mbld/opts.myr
@@ -56,13 +56,13 @@
 	| "Darwin":	opt_sys = "osx"
 	| "FreeBSD":	opt_sys = "freebsd"
 	| "Plan9":	opt_sys = "plan9"
-	| unknown:	std.fatal("unknown system \"%s\"\n", unknown)
+	| unknown:	std.fatal("unknown system \"{}\"\n", unknown)
 	;;
 
 	match si.arch
 	| "x86_64":	opt_arch = "x64"
 	| "amd64":	opt_arch = "x64"
-	| unknown:	std.fatal("unknown architecture \"%s\"\n", unknown)
+	| unknown:	std.fatal("unknown architecture \"{}\"\n", unknown)
 	;;
 
 	opt_incpaths = [][:]
@@ -76,8 +76,8 @@
 		opt_runtime = std.pathjoin([opt_instroot, config.Libpath, config.Runtime][:]) 
 	;;
 
-	sysarchstr = std.fmt("+%s-%s", opt_sys, opt_arch)
-	sysstr = std.fmt("+%s", opt_sys)
-	archstr = std.fmt("+%s", opt_arch)
+	sysarchstr = std.fmt("+{}-{}", opt_sys, opt_arch)
+	sysstr = std.fmt("+{}", opt_sys)
+	archstr = std.fmt("+{}", opt_arch)
 }
 
--- a/mbld/parse.myr
+++ b/mbld/parse.myr
@@ -59,7 +59,7 @@
 			loadall(b, subproj, subpath)
 			b.basedir = curbase
 		else
-			std.f2fatal("could not open {} or {} \n", subbld, subproj)
+			std.fatal("could not open {} or {} \n", subbld, subproj)
 		;;
 		std.slfree(subbld)
 		std.slfree(subproj)
@@ -91,7 +91,7 @@
 
 const visit = {all, b, targ, looped, marked
 	if std.hthas(looped, targ)
-		std.f2fatal("cycle in build depgraph involving {}\n", targ)
+		std.fatal("cycle in build depgraph involving {}\n", targ)
 	elif std.hthas(marked, targ)
 		-> all
 	;;
@@ -109,7 +109,7 @@
 	match targ
 	| `Bin t:	-> t.libdeps
 	| `Lib t:	-> t.libdeps
-	| _:	std.f2fatal("depending on non-library target")
+	| _:	std.fatal("depending on non-library target")
 	;;
 }
 
@@ -123,7 +123,7 @@
 	p.basedir = std.sldup(basedir)
 	match std.slurp(path)
 	| `std.Ok d:	p.data = d
-	| `std.Fail _:	std.f2fatal("could not open '{}'\n", path)
+	| `std.Fail _:	std.fatal("could not open '{}'\n", path)
 	;;
 	p.rest = p.data
 	-> p
@@ -144,8 +144,8 @@
 	var sl
 
 	ap = std.vastart(&args)
-	sl = std.bfmtv(buf[:], msg, ap)
-	std.f2fput(1, "{}:{}: {}", p.fname, p.line, sl)
+	sl = std.bfmtv(buf[:], msg, &ap)
+	std.fput(1, "{}:{}: {}", p.fname, p.line, sl)
 	std.exit(1)
 }
 
@@ -353,7 +353,7 @@
 		| ("noinst", ""):	inst = false
 		| ("sys", tags):	systags = std.slpush(systags, tags)
 		| (invalid, _):
-			std.f2fatal("{}: got invalid attr '{}'\n", targ, invalid)
+			std.fatal("{}: got invalid attr '{}'\n", targ, invalid)
 		;;
 	;;
 	for inc in bld.opt_incpaths
@@ -596,7 +596,7 @@
 const addtarg = {p, b, name, targ
 	var tn
 
-	tn = std.f2fmt("{}:{}", p.fdir, name)
+	tn = std.fmt("{}:{}", p.fdir, name)
 	if std.hthas(b.targs, tn)
 		failparse(p, "duplicate target {}\n", tn)
 	;;
@@ -611,10 +611,10 @@
 	| `std.None:
 		dir = std.sldup(".")
 		lib = std.sldup(libpath)
-		targ = std.f2fmt("{}:{}", p.fdir, lib)
+		targ = std.fmt("{}:{}", p.fdir, lib)
 	| `std.Some idx:
 		if idx == libpath.len
-			std.f2fatal("libdep {} missing library after ':'\n")
+			std.fatal("libdep {} missing library after ':'\n")
 		;;
 		/* absolute path */
 		if std.hasprefix(libpath, "@/") || std.hasprefix(libpath, "@:")
@@ -627,7 +627,7 @@
 			lib = std.sldup(libpath[idx+1:])
 			targ = std.pathcat(p.fdir, libpath)
 			if std.hasprefix(targ, "../")
-				std.f2fatal("library {} outside of project\n", libpath)
+				std.fatal("library {} outside of project\n", libpath)
 			;;
 		;;
 	;;
--- a/mbld/test.myr
+++ b/mbld/test.myr
@@ -55,9 +55,9 @@
 	;;
 	if hastest
 		if ok
-			std.f2put("TESTS PASSED\n")
+			std.put("TESTS PASSED\n")
 		else
-			std.f2put("TESTS FAILED\n")
+			std.put("TESTS FAILED\n")
 			std.exit(1)
 		;;
 	;;
@@ -121,11 +121,11 @@
 const runtest = {bin
 	var r, log
 
-	std.f2put("run {}:\t", bin)
+	std.put("run {}:\t", bin)
 	log = std.strcat(bin, ".log")
 	match std.spork([bin][:])
 	| `std.Fail m:
-		std.f2fatal("unable to run test: {}\n", m)
+		std.fatal("unable to run test: {}\n", m)
 	| `std.Ok (pid, infd, outfd):
 		match std.fslurp(outfd)
 		| `std.Ok "":	/* empty output; nothing to log */
@@ -137,8 +137,8 @@
 
 		r = false
 		match std.wait(pid)
-		| `std.Wfailure:	std.f2put("FAIL\n")
-		| `std.Wsignalled:	std.f2put("CRASH\n")
+		| `std.Wfailure:	std.put("FAIL\n")
+		| `std.Wsignalled:	std.put("CRASH\n")
 		| `std.Wsuccess:
 			std.put("PASS\n")
 			r = true
--- a/mbld/util.myr
+++ b/mbld/util.myr
@@ -20,17 +20,17 @@
 	printcmd(cmd)
 	pid = std.fork()
 	if pid == -1
-		std.f2fatal("could not fork command\n")
+		std.fatal("could not fork command\n")
 	elif pid == 0
 		if std.execvp(cmd[0], cmd) < 0
-			std.f2fatal("failed to exec {}\n", cmd[0])
+			std.fatal("failed to exec {}\n", cmd[0])
 		;;
 	else
 		match std.wait(pid)
 		| `std.Wsuccess:	/* nothing */
-		| `std.Wfailure:	std.f2fatal("FAIL: \"{}\"\n", std.strjoin(cmd, " "))
-		| `std.Wsignalled:	std.f2fatal("CRASH: \"{}\"\n", std.strjoin(cmd, " "))
-		| `std.Waiterror:	std.f2fatal("WAT: \"{}\"\n", std.strjoin(cmd, " "))
+		| `std.Wfailure:	std.fatal("FAIL: \"{}\"\n", std.strjoin(cmd, " "))
+		| `std.Wsignalled:	std.fatal("CRASH: \"{}\"\n", std.strjoin(cmd, " "))
+		| `std.Waiterror:	std.fatal("WAT: \"{}\"\n", std.strjoin(cmd, " "))
 		;;
 	;;
 }
@@ -37,13 +37,13 @@
 
 const printcmd = {lst
 	if lst.len > 0
-		std.f2put("\t")
-		std.f2put("{}\t", lst[0])
+		std.put("\t")
+		std.put("{}\t", lst[0])
 		for l in lst[1:]
-			std.f2put("{} ", l)
+			std.put("{} ", l)
 		;;
 	;;
-	std.f2put("\n")
+	std.put("\n")
 }
 
 const srcsplit = {src
@@ -73,7 +73,7 @@
 	if std.hassuffix(f, suff)
 		f = f[:f.len - suff.len]
 	;;
-	-> std.f2fmt("{}{}", f, newsuff)
+	-> std.fmt("{}{}", f, newsuff)
 }
 
 const srcswapsuffix = {src, new
@@ -85,7 +85,7 @@
 	elif std.sleq(suff, ".s")
 		-> std.strcat(base, new)
 	else
-		std.f2fatal("unrecognized source {}\n", src)
+		std.fatal("unrecognized source {}\n", src)
 	;;
 }
 
@@ -98,7 +98,7 @@
 
 const gettarg = {tab, n
 	match std.htget(tab, n)
-	| `std.None:	std.f2fatal("internal: nonexistent {}\n", n)
+	| `std.None:	std.fatal("internal: nonexistent {}\n", n)
 	| `std.Some t:	-> t
 	;;
 }
@@ -109,12 +109,12 @@
 	if !std.sleq(b.curdir, dir)
 		p = std.pathcat(b.basedir, dir)
 		if b.curdir.len != 0
-			std.f2put("Leaving directory '{}'\n", b.curdir)
+			std.put("Leaving directory '{}'\n", b.curdir)
 		;;
 
-		std.f2put("Entering directory '{}'\n", dir)
+		std.put("Entering directory '{}'\n", dir)
 		if !std.chdir(p)
-			std.f2fatal("could not cd into {}\n", p)
+			std.fatal("could not cd into {}\n", p)
 		;;
 		b.curdir = dir
 		std.slfree(p)
--- a/test/align.myr
+++ b/test/align.myr
@@ -53,18 +53,18 @@
 ;;
 
 const main = {
-	std.put("size = %i\n", sizeof(alignstruct0))
-	std.put("size = %i\n", sizeof(alignstruct1))
-	std.put("size = %i\n", sizeof(alignstruct2))
-	std.put("size = %i\n", sizeof(alignstruct3))
-	std.put("size = %i\n", sizeof(alignstruct4))
-	std.put("size = %i\n", sizeof(alignstruct5))
-	std.put("size = %i\n", sizeof(alignstruct6))
-	std.put("size = %i\n", sizeof(alignstruct7))
+	std.put("size = {}\n", sizeof(alignstruct0))
+	std.put("size = {}\n", sizeof(alignstruct1))
+	std.put("size = {}\n", sizeof(alignstruct2))
+	std.put("size = {}\n", sizeof(alignstruct3))
+	std.put("size = {}\n", sizeof(alignstruct4))
+	std.put("size = {}\n", sizeof(alignstruct5))
+	std.put("size = {}\n", sizeof(alignstruct6))
+	std.put("size = {}\n", sizeof(alignstruct7))
 	/* size should be 8 */
-	std.put("size = %i\n", sizeof((int, byte, byte)))
+	std.put("size = {}\n", sizeof((int, byte, byte)))
 	/* size should be 16 */
-	std.put("size = %i\n", sizeof((int, byte, int, byte)))
+	std.put("size = {}\n", sizeof((int, byte, int, byte)))
 	/* size should be 12 */
-	std.put("size = %i\n", sizeof((int, int, byte, byte)))
+	std.put("size = {}\n", sizeof((int, int, byte, byte)))
 }
--- a/test/bigcondarg.myr
+++ b/test/bigcondarg.myr
@@ -21,9 +21,9 @@
 		actual = false
 	;;
 	if actual == expected
-		std.put("a == b: expected: %t, got, %t: pass\n", expected, actual)
+		std.put("a == b: expected: {}, got, {}: pass\n", expected, actual)
 	else
-		std.put("a == b: expected: %t, got, %t: fail\n", expected, actual)
+		std.put("a == b: expected: {}, got, {}: fail\n", expected, actual)
 	;;
 }
 
--- a/test/bigliteral.myr
+++ b/test/bigliteral.myr
@@ -1,5 +1,5 @@
 use std
 
 const main = {
-	std.put("%l\n", 34359738368 castto(int64))
+	std.put("{}\n", 34359738368 castto(int64))
 }
--- a/test/catfile.myr
+++ b/test/catfile.myr
@@ -7,7 +7,7 @@
 	r = std.slurp("data/catfile-in")
 	match r
 	| `std.Ok dat: 	std.write(1, dat)
-	| `std.Fail msg:	std.put("Failed to read file: %s\n", msg)
+	| `std.Fail msg:	std.put("Failed to read file: {}\n", msg)
 	;;
 	-> 0
 }
--- a/test/constslice.myr
+++ b/test/constslice.myr
@@ -8,15 +8,15 @@
 const main = {
 	/* expected output 23 */
 	for x in slpart
-		std.put("%i", x)
+		std.put("{}", x)
 	;;
 	/* expected output 12345 */
 	for x in slfull
-		std.put("%i", x)
+		std.put("{}", x)
 	;;
 	/* expected output 678 */
 	for x in slinline
-		std.put("%i", x)
+		std.put("{}", x)
 	;;
 	std.put("\n")
 }
--- a/test/doublecall.myr
+++ b/test/doublecall.myr
@@ -1,7 +1,7 @@
 use std
 
 const main = {
-	std.put("%i,%w\n", a(), b())
+	std.put("{},{}\n", a(), b())
 }
 
 const a = {
--- a/test/foldidx.myr
+++ b/test/foldidx.myr
@@ -11,6 +11,6 @@
 ]
 
 const main = {
-	std.put("%i,%i\n", z[0].x, z[0].y)
+	std.put("{},{}\n", z[0].x, z[0].y)
 }
 
--- a/test/genericmake.myr
+++ b/test/genericmake.myr
@@ -14,7 +14,7 @@
 
 	x = make(123)
 	match x
-	| `std.Some v:	std.put("val = %i\n", v)
+	| `std.Some v:	std.put("val = {}\n", v)
 	| `std.None:	std.die("Unreachable\n")
 	;;
 }
--- a/test/loop.myr
+++ b/test/loop.myr
@@ -6,19 +6,19 @@
 
 	n = 0
 	for i = 0; i < 5; ++i
-		std.put("%i", i)
+		std.put("{}", i)
 	;;
 	for i = 0; i < 5; ++i
 		if i > 3
 			break
 		;;
-		std.put("%i", i)
+		std.put("{}", i)
 	;;
 	for i = 0; i < 10; ++i
 		if i < 6
 			continue
 		;;
-		std.put("%i", i)
+		std.put("{}", i)
 	;;
 	std.put("\n")
 }
--- a/test/matchunion_sl.myr
+++ b/test/matchunion_sl.myr
@@ -13,7 +13,7 @@
 	v = `Str "foo"
 	match v
 	| `Int 127: std.exit(42)
-	| `Str s: std.put("%s\n", s)
+	| `Str s: std.put("{}\n", s)
 	| `Nil:
 	| _:	std.die("Impossible match failure\n")
 	;;
--- a/test/nestucon.myr
+++ b/test/nestucon.myr
@@ -12,7 +12,7 @@
 
 	a = [.x = `Str "asdf"]
 	match a
-	| [.x=`Str s]:	std.put("%s\n", s)
+	| [.x=`Str s]:	std.put("{}\n", s)
 	| _:	std.die("Impossible match failure\n")
 	;;
 }
--- a/test/patiter.myr
+++ b/test/patiter.myr
@@ -3,11 +3,11 @@
 const main = {
 	/* should print 1,3,5, skipping 4 */
 	for (1,x) in [(1,2),(1,3),(2,4),(1,5)]
-		std.put("%i", x)
+		std.put("{}", x)
 	;;
 	/* should print 1, 2 skipping `None */
 	for `std.Some v in [`std.None, `std.Some 1, `std.Some 2]
-		std.put("%i", v)
+		std.put("{}", v)
 	;;
 	std.put("\n")
 }
--- a/test/strfind.myr
+++ b/test/strfind.myr
@@ -15,7 +15,7 @@
 
 const printloc = {l
 	match l
-	| `std.Some loc:	std.put("Found %z\n", loc)
+	| `std.Some loc:	std.put("Found {}\n", loc)
 	| `std.None:	std.put("No match\n")
 	;;
 }
--- a/test/strjoin.myr
+++ b/test/strjoin.myr
@@ -7,7 +7,7 @@
 	    "z",
 	    "w"
 	]
-	std.put("%s\n", std.strcat("foo;", "bar"))
-	std.put("%s\n", std.strjoin(strings[:], ""))
-	std.put("%s\n", std.strjoin(strings[:], ":"))
+	std.put("{}\n", std.strcat("foo;", "bar"))
+	std.put("{}\n", std.strjoin(strings[:], ""))
+	std.put("{}\n", std.strjoin(strings[:], ":"))
 }
--- a/test/strsplit.myr
+++ b/test/strsplit.myr
@@ -6,19 +6,19 @@
 
 	sp = std.strsplit("a,b,c,d", ",")
 	for i = 0; i < sp.len; i++
-		std.put("\"%s\"\n", sp[i])
+		std.put("\"{}\"\n", sp[i])
 	;;
 	std.slfree(sp)
 
 	sp = std.strsplit("a,,b,c,,d", ",")
 	for i = 0; i < sp.len; i++
-		std.put("\"%s\"\n", sp[i])
+		std.put("\"{}\"\n", sp[i])
 	;;
 	std.slfree(sp)
 
 	sp = std.strsplit("a--b---b--c---c-d--d", "---")
 	for i = 0; i < sp.len; i++
-		std.put("\"%s\"\n", sp[i])
+		std.put("\"{}\"\n", sp[i])
 	;;
 	std.slfree(sp)
 }
--- a/test/strstrip.myr
+++ b/test/strstrip.myr
@@ -1,27 +1,27 @@
 use std
 
 const main = {
-	std.put("\"%s\"\n", std.strstrip("cccc"))
-	std.put("\"%s\"\n", std.strfstrip("cccc"))
-	std.put("\"%s\"\n", std.strrstrip("cccc"))
+	std.put("\"{}\"\n", std.strstrip("cccc"))
+	std.put("\"{}\"\n", std.strfstrip("cccc"))
+	std.put("\"{}\"\n", std.strrstrip("cccc"))
 
 	std.put("--\n")
-	std.put("\"%s\"\n", std.strstrip("  abc  "))
-	std.put("\"%s\"\n", std.strfstrip("  abc  "))
-	std.put("\"%s\"\n", std.strrstrip("  abc  "))
+	std.put("\"{}\"\n", std.strstrip("  abc  "))
+	std.put("\"{}\"\n", std.strfstrip("  abc  "))
+	std.put("\"{}\"\n", std.strrstrip("  abc  "))
 
 	std.put("--\n")
-	std.put("\"%s\"\n", std.strstrip("  世界  "))
-	std.put("\"%s\"\n", std.strfstrip("  世界  "))
-	std.put("\"%s\"\n", std.strrstrip("  世界  "))
+	std.put("\"{}\"\n", std.strstrip("  世界  "))
+	std.put("\"{}\"\n", std.strfstrip("  世界  "))
+	std.put("\"{}\"\n", std.strrstrip("  世界  "))
 
 	std.put("--\n")
-	std.put("\"%s\"\n", std.strstrip("    "))
-	std.put("\"%s\"\n", std.strfstrip("    "))
-	std.put("\"%s\"\n", std.strrstrip("    "))
+	std.put("\"{}\"\n", std.strstrip("    "))
+	std.put("\"{}\"\n", std.strfstrip("    "))
+	std.put("\"{}\"\n", std.strrstrip("    "))
 
 	std.put("--\n")
-	std.put("\"%s\"\n", std.strstrip(""))
-	std.put("\"%s\"\n", std.strfstrip(""))
-	std.put("\"%s\"\n", std.strrstrip(""))
+	std.put("\"{}\"\n", std.strstrip(""))
+	std.put("\"{}\"\n", std.strfstrip(""))
+	std.put("\"{}\"\n", std.strrstrip(""))
 }
--- a/test/strtab.myr
+++ b/test/strtab.myr
@@ -10,7 +10,7 @@
 const main = {
 	var i
 	for i = 0; i < strtab.len; i++
-		std.put("%i: %s\n", i, strtab[i])
+		std.put("{}: {}\n", i, strtab[i])
 	;;
 	std.exit(0)
 }
--- a/test/subrangefor.myr
+++ b/test/subrangefor.myr
@@ -2,7 +2,7 @@
 
 const main = {
 	for i in [1,2,3,4][:2]
-		std.put("%i", i)
+		std.put("{}", i)
 	;;
 	std.put("\n")
 }
--- a/test/traitimpl.myr
+++ b/test/traitimpl.myr
@@ -31,6 +31,6 @@
 	a = foo(123)
 	b = foo(11 castto(int16))
 	c = frob("meeeeeeh")
-	std.put("%i,%w,%s\n", a, b, c)
+	std.put("{},{},{}\n", a, b, c)
 }
 
--- a/test/uconinit.myr
+++ b/test/uconinit.myr
@@ -13,7 +13,7 @@
 		match v
 		| `A:	std.put("A ")
 		| `B:	std.put("B ")
-		| `C x:	std.put("C %i\n", x)
+		| `C x:	std.put("C {}\n", x)
 		;;
 	;;
 	std.put("\n")