shithub: mc

Download patch

ref: 8728342de349e7029312ddbd33c2710d2d03fff2
parent: 35bde60621ecf5cbcf07b743cafd9724f87faccb
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Oct 4 06:59:36 EDT 2015

Make the interface for libbio expose errors.

    Filling in all the error conditions correctly is only lightly
    tested, but it seems to work.

--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -10,6 +10,7 @@
 		/* backing fd */
 		fd	: std.fd
 		mode	: mode
+		haderr	: bool
 
 		/* read buffer */
 		rbuf	: byte[:]
@@ -21,6 +22,12 @@
 		wend	: std.size
 	;;
 
+	type status(@a) = union
+		`Eof
+		`Ok @a
+		`Err
+	;;
+
 	/* creation */
 	const mkfile	: (fd : std.fd, mode : mode	-> file#)
 	const open	: (path : byte[:], mode : mode	-> std.result(file#, byte[:]))
@@ -30,8 +37,8 @@
 	const free	: (f : file# -> void)
 
 	/* basic i/o. Returns sub-buffer when applicable. */
-	const write	: (f : file#, src : byte[:]	-> std.size)
-	const read	: (f : file#, dst : byte[:]	-> std.option(byte[:]))
+	const write	: (f : file#, src : byte[:]	-> status(std.size))
+	const read	: (f : file#, dst : byte[:]	-> status(byte[:]))
 	const flush	: (f : file# -> bool)
 
 	/* seeking */
@@ -38,27 +45,28 @@
 	const seek	: (f : file#, std.off -> std.off)
 
 	/* single unit operations */
-	const putb	: (f : file#, b : byte	-> std.size)
-	const putc	: (f : file#, c : char	-> std.size)
-	const getb	: (f : file# -> std.option(byte))
-	const getc	: (f : file# -> std.option(char))
+	const putb	: (f : file#, b : byte	-> status(std.size))
+	const putc	: (f : file#, c : char	-> status(std.size))
+	const getb	: (f : file# -> status(byte))
+	const getc	: (f : file# -> status(char))
 
 	/* peeking */
-	const peekb	: (f : file# -> std.option(byte))
-	const peekc	: (f : file# -> std.option(char))
+	const peekb	: (f : file# -> status(byte))
+	const peekc	: (f : file# -> status(char))
 
 	/* delimited read; returns freshly allocated buffer. */
-	const readln	: (f : file#	-> std.option(byte[:]))
-	const readto	: (f : file#, delim : byte[:]	-> std.option(byte[:]))
+	const readln	: (f : file#	-> status(byte[:]))
+	const readto	: (f : file#, delim : byte[:]	-> status(byte[:]))
 	const skipto	: (f : file#, delim : byte[:]	-> bool)
 	const skipspace	: (f : file# -> void)
 
 	/* formatted i/o */
-	const put	: (f : file#, fmt : byte[:], args : ... -> std.size)
+	const put	: (f : file#, fmt : byte[:], args : ... -> status(std.size))
 
 	/* pkg funcs */
-	pkglocal const ensureread	: (f : file#, n : std.size -> bool)
-	pkglocal const ensurewrite	: (f : file#, n : std.size -> bool)
+	pkglocal const ensureread	: (f : file#, n : std.size -> status(std.size))
+	pkglocal const ensurewrite	: (f : file#, n : std.size -> status(std.size))
+	pkglocal const writebuf	: (fd : std.fd,  b : byte[:] -> status(std.size))
 ;;
 
 const Bufsz = 16*std.KiB
@@ -162,7 +170,7 @@
 	if src.len < (f.wbuf.len - f.wend)
 		std.slcp(f.wbuf[f.wend:f.wend+src.len], src)
 		f.wend += src.len
-		-> src.len
+		-> `Ok src.len
 	else
 		flush(f)
 		-> writebuf(f.fd, src)
@@ -178,6 +186,11 @@
 	var d
 	var count
 
+	/* Clear the error state so we can retry */
+	if f.haderr
+		f.haderr = false
+		-> `Err
+	;;
 	std.assert(f.mode & Rd != 0, "File is not in read mode")
 	/* 
 	 * small reads should try to fill, so we don't have to make a
@@ -201,17 +214,23 @@
 	d = dst[count:]
 	while dst.len > 0
 		n = std.read(f.fd, d)
-		if n <= 0
-			goto readdone
+		if n == 0
+			break
+		elif n < 0
+			if count > 0
+				f.haderr = true
+			;;
+			break
 		;;
 		count += n
 		d = d[n:]
 	;;
-:readdone
-	if count > 0
-		-> `std.Some dst[:count]
+	if n < 0 && count == 0
+		-> `Err
+	elif count == 0
+		-> `Eof
 	else
-		-> `std.None
+		-> `Ok dst[:count]
 	;;
 }
 
@@ -221,8 +240,13 @@
 
 	ret = true
 	if f.mode & Wr != 0
-		ret = (writebuf(f.fd, f.wbuf[:f.wend]) == f.wend)
-		f.wend = 0
+		match writebuf(f.fd, f.wbuf[:f.wend])
+		| `Ok n:
+			ret = (n == f.wend)
+			f.wend = 0
+		| _:
+			-> false
+		;;
 	;;
 	-> ret
 }
@@ -234,9 +258,13 @@
 
 /* writes a single byte to the output stream */
 const putb = {f, b
-	ensurewrite(f, 1)
-	f.wbuf[f.wend++] = b
-	-> 1
+	match ensurewrite(f, 1)
+	| `Err:	-> `Err
+	| `Eof: -> `Eof
+	| `Ok n:
+		f.wbuf[f.wend++] = b
+		-> `Ok 1
+	;;
 }
 
 /* writes a single character to the output stream, encoded in utf8 */
@@ -244,18 +272,24 @@
 	var sz
 	
 	sz = std.charlen(c)
-	ensurewrite(f, sz)
-	std.encode(f.wbuf[f.wend:], c)
-	f.wend += sz
-	-> sz
+	match ensurewrite(f, sz)
+	| `Err:	-> `Err
+	| `Eof: -> `Eof
+	| `Ok n:
+		std.encode(f.wbuf[f.wend:], c)
+		f.wend += sz
+		-> `Ok sz
+	;;
 }
 
 /* reads a single byte from the input stream */
 const getb = {f
-	if ensureread(f, 1)
-		-> `std.Some f.rbuf[f.rstart++]
+	match ensureread(f, 1)
+	| `Eof:	-> `Eof
+	| `Err:	-> `Err
+	| `Ok n:
+		-> `Ok f.rbuf[f.rstart++]
 	;;
-	-> `std.None
 }
 
 /* reads a single character from the input stream, encoded in utf8 */
@@ -262,35 +296,39 @@
 const getc = {f
 	var c
 
-	if ensurecodepoint(f)
+	match ensurecodepoint(f)
+	| `Err:	-> `Err
+	| `Eof:	-> `Eof
+	| `Ok n:
 		c = std.decode(f.rbuf[f.rstart:f.rend])
 		f.rstart += std.charlen(c)
-		-> `std.Some c
+		-> `Ok c
 	;;
-	-> `std.None
 }
 
 /* ensures we have enough to read a single codepoint in the buffer */
-const ensurecodepoint = {f
+const ensurecodepoint : (f : file# -> status(std.size)) = {f
 	var b
 	var len
 
-	if !ensureread(f, 1)
-		-> false
+	match ensureread(f, 1)
+	| `Err:	-> `Err
+	| `Eof:	-> `Eof
+	| `Ok n:
+		b = f.rbuf[f.rstart]
+		if b & 0x80 == 0	/* 0b0xxx_xxxx */
+			len = 1
+		elif b & 0xe0 == 0xc0	/* 0b110x_xxxx */
+			len = 2
+		elif b & 0xf0 == 0xe0 	/* 0b1110_xxxx */
+			len = 3
+		elif b & 0xf8 == 0xf0 	/* 0b1111_0xxx */
+			len = 4
+		else
+			len = 1		/* invalid unicode char */
+		;;
+		-> ensureread(f, len)
 	;;
-	b = f.rbuf[f.rstart]
-	if b & 0x80 == 0	/* 0b0xxx_xxxx */
-		len = 1
-	elif b & 0xe0 == 0xc0	/* 0b110x_xxxx */
-		len = 2
-	elif b & 0xf0 == 0xe0 	/* 0b1110_xxxx */
-		len = 3
-	elif b & 0xf8 == 0xf0 	/* 0b1111_0xxx */
-		len = 4
-	else
-		len = 1		/* invalid unicode char */
-	;;
-	-> ensureread(f, len)
 }
 
 /*
@@ -319,19 +357,21 @@
 
 /* peeks a single byte from an input stream */
 const peekb = {f
-	if !ensureread(f, 1)
-		-> `std.None
-	else
-		-> `std.Some f.rbuf[f.rstart]
+	match ensureread(f, 1)
+	| `Eof:	-> `Eof
+	| `Err:	-> `Err
+	| `Ok n:
+		-> `Ok f.rbuf[f.rstart]
 	;;
 }
 
 /* peeks a single character from a utf8 encoded input stream */
 const peekc = {f
-	if !ensurecodepoint(f)
-		-> `std.None
-	else
-		-> `std.Some std.decode(f.rbuf[f.rstart:f.rend])
+	match ensurecodepoint(f)
+	| `Eof:	-> `Eof
+	| `Err:	-> `Err
+	| `Ok n:
+		-> `Ok std.decode(f.rbuf[f.rstart:f.rend])
 	;;
 }
 
@@ -351,8 +391,9 @@
 /* same as readto, but drops the read data. */
 const skipto = {f, delim
 	match readdelim(f, delim, true)
-	| `std.Some ret:	-> true
-	| `std.None:	-> false
+	| `Ok ign:	-> true
+	| `Eof:		-> false
+	| `Err:		-> false
 	;;
 }
 
@@ -359,13 +400,15 @@
 const skipspace = {f
 	while true
 		match bio.peekc(f)
-		| `std.Some c:
+		| `Ok c:
 			if std.isspace(c)
 				break
 			;;
 			bio.getc(f)
-		| `std.None:
+		| `Eof:
 			break
+		| `Err:
+			break
 		;;
 	;;
 }
@@ -377,12 +420,15 @@
 	ret = [][:]
 	while true
 		/* get at least delimiter count of characters */
-		if !ensureread(f, 1)
+		match ensureread(f, 1)
+		| `Ok _:
+		| `Err:	-> `Err
+		| `Eof:
 			ret = readinto(f, ret, f.rend - f.rstart)
 			if ret.len > 0
-				-> `std.Some ret
+				-> `Ok ret
 			else
-				-> `std.None
+				-> `Eof
 			;;
 		;;
 		/* scan for delimiter */
@@ -391,12 +437,12 @@
 			if c == '\r' || c == '\n'
 				n = 1
 				/* if we have '\r', we can get '\r\n'. */
-				if c == '\r' && std.getv(peekc(f), -1) == '\n'
+				if c == '\r' && unwrapc(peekc(f), -1) == '\n'
 					n = 2
 				;;
 				ret = readinto(f, ret, i - f.rstart)
 				f.rstart += n
-				-> `std.Some ret
+				-> `Ok ret
 			;;
 :nextitergetln
 		;;
@@ -405,6 +451,13 @@
 	std.die("unreachable")
 }
 
+const unwrapc = {cc, v
+	match cc
+	| `Ok c:	-> c
+	| _:	-> v
+	;;
+}
+
 const readdelim = {f, delim, drop
 	var ret
 
@@ -411,14 +464,17 @@
 	ret = [][:]
 	while true
 		/* get at least delimiter count of characters */
-		if !ensureread(f, delim.len)
+		match ensureread(f, 1)
+		| `Ok _:
+		| `Err:	-> `Err
+		| `Eof:
 			if !drop
 				ret = readinto(f, ret, f.rend - f.rstart)
 			;;
 			if ret.len > 0
-				-> `std.Some ret
+				-> `Ok ret
 			else
-				-> `std.None
+				-> `Err
 			;;
 		;;
 		for var i = f.rstart; i < f.rend; i++
@@ -432,7 +488,7 @@
 					ret = readinto(f, ret, i - f.rstart)
 				;;
 				f.rstart += delim.len
-				-> `std.Some ret
+				-> `Ok ret
 			;;
 :nextiterread
 		;;
@@ -476,9 +532,15 @@
 const ensurewrite = {f, n
 	std.assert(n < f.wbuf.len, "ensured write capacity > buffer size")
 	if n > f.wbuf.len - f.wend
-		-> flush(f)
+		match writebuf(f.fd, f.wbuf[:f.wend])
+		| `Ok len:
+			f.wend = 0
+			-> `Ok len
+		| _:
+			-> `Err
+		;;
 	;;
-	-> true
+	-> `Ok n
 }
 
 /*
@@ -499,9 +561,18 @@
 			f.rstart = 0
 			f.rend = cap
 		;;
-		-> fill(f, n) > n
+		match fill(f, n)
+		| `Eof:	-> `Eof
+		| `Err:	-> `Err
+		| `Ok len:
+			if len > n
+				-> `Ok len
+			else
+				-> `Eof
+			;;
+		;;
 	else
-		-> true
+		-> `Ok n
 	;;
 }
 
@@ -513,14 +584,16 @@
 	count = 0
 	while src.len != 0
 		n = std.write(fd, src)
-		if n <= 0
-			goto writedone
+		if n == 0
+			-> `Eof
+		elif n < 0
+			-> `Err
 		;;
 		count += n
 		src = src[n:]
 	;;
 :writedone
-	-> count
+	-> `Ok count
 }
 
 
@@ -534,16 +607,37 @@
 	var count
 
 	count = 0
+	/* Clear the error state so we can retry */
+	if f.haderr
+		f.haderr = false
+		-> `Err
+	;;
 	while count < min
 		n = std.read(f.fd, f.rbuf[f.rend:])
-		if n <= 0
-			goto filldone
+		/*
+		If we've already read data, we don't want to
+		throw it away, so we report a successful short
+		read, and then error on the next read.
+		*/
+		if n == 0
+			break
+		elif n < 0
+			if count > 0
+				f.haderr = true
+			;;
+			break
 		;;
 		count += n
 		f.rend += n
 	;;
-:filldone
-	-> count
+
+	if n < 0 && count == 0
+		-> `Err
+	elif count == 0
+		-> `Eof
+	else
+		-> `Ok count
+	;;
 }
 
 
--- a/lib/bio/geti.myr
+++ b/lib/bio/geti.myr
@@ -4,16 +4,16 @@
 
 pkg bio =
 	/* unsigned big endian */
-	generic getbe8	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getbe16	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getbe32	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getbe64	: (f : file# -> std.option(@a::(numeric,integral)))
+	generic getbe8	: (f : file# -> status(@a::(numeric,integral)))
+	generic getbe16	: (f : file# -> status(@a::(numeric,integral)))
+	generic getbe32	: (f : file# -> status(@a::(numeric,integral)))
+	generic getbe64	: (f : file# -> status(@a::(numeric,integral)))
 
 	/* signed big endian */
-	generic getle8	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getle16	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getle32	: (f : file# -> std.option(@a::(numeric,integral)))
-	generic getle64	: (f : file# -> std.option(@a::(numeric,integral)))
+	generic getle8	: (f : file# -> status(@a::(numeric,integral)))
+	generic getle16	: (f : file# -> status(@a::(numeric,integral)))
+	generic getle32	: (f : file# -> status(@a::(numeric,integral)))
+	generic getle64	: (f : file# -> status(@a::(numeric,integral)))
 ;;
 
 /*
@@ -20,17 +20,19 @@
   reads a single integer-like value to the output stream, in
   little endian format
 */
-generic getle = {f, n -> std.option(@a::(numeric,integral))
+generic getle = {f, n -> status(@a::(numeric,integral))
 	var v, i
 
 	v = 0
-	if !ensureread(f, n)
-		-> `std.None
+	match ensureread(f, n)
+	| `Eof:	-> `Eof
+	| `Err:	-> `Err
+	| `Ok _:
+		for i = 0; i < n; i++
+			v |= (f.rbuf[f.rstart++] castto(uint64)) << (8*(i castto(uint64)))
+		;;
+		-> `Ok v castto(@a::(numeric,integral))
 	;;
-	for i = 0; i < n; i++
-		v |= (f.rbuf[f.rstart++] castto(uint64)) << (8*(i castto(uint64)))
-	;;
-	-> `std.Some v castto(@a::(numeric,integral))
 }
 
 /*
@@ -37,18 +39,20 @@
   reads a single integer-like value to the output stream, in
   big endian format
 */
-generic getbe = {f, n -> std.option(@a::(numeric,integral))
+generic getbe = {f, n -> status(@a::(numeric,integral))
 	var v, i
 
 	v = 0
-	if !ensureread(f,n)
-		-> `std.None
+	match ensureread(f, n)
+	| `Eof:	-> `Eof
+	| `Err:	-> `Err
+	| `Ok _:
+		for i = 0; i < n; i++
+			v <<= 8
+			v |= (f.rbuf[f.rstart++] castto(uint64))
+		;;
+		-> `Ok v castto(@a::(numeric,integral))
 	;;
-	for i = 0; i < n; i++
-		v <<= 8
-		v |= (f.rbuf[f.rstart++] castto(uint64))
-	;;
-	-> `std.Some v castto(@a::(numeric,integral))
 }
 
 generic getbe8  = {f; -> getbe(f, 1)}
--- a/lib/bio/puti.myr
+++ b/lib/bio/puti.myr
@@ -4,16 +4,16 @@
 
 pkg bio =
 	/* unsigned big endian */
-	generic putbe8	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putbe16	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putbe32	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putbe64	: (f : file#, v : @a::(numeric,integral) -> std.size)
+	generic putbe8	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putbe16	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putbe32	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putbe64	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
 
 	/* unsigned little endian */
-	generic putle8	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putle16	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putle32	: (f : file#, v : @a::(numeric,integral) -> std.size)
-	generic putle64	: (f : file#, v : @a::(numeric,integral) -> std.size)
+	generic putle8	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putle16	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putle32	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
+	generic putle64	: (f : file#, v : @a::(numeric,integral) -> status(std.size))
 ;;
 
 generic putbe8  = {f, v; -> putbe(f, v castto(uint64), 1)}
@@ -29,34 +29,38 @@
 const putle = {f, v, n
 	var buf : byte[8]
 
-	if !ensurewrite(f, n)
-		-> 0
+	match ensurewrite(f, n)
+	| `Err:	-> `Err
+	| `Eof:	-> `Eof
+	| `Ok _:
+		buf[0] = (v >> 0) & 0xff castto(byte)
+		buf[1] = (v >> 8) & 0xff castto(byte)
+		buf[2] = (v >> 16) & 0xff castto(byte)
+		buf[3] = (v >> 24) & 0xff castto(byte)
+		buf[4] = (v >> 32) & 0xff castto(byte)
+		buf[5] = (v >> 40) & 0xff castto(byte)
+		buf[6] = (v >> 48) & 0xff castto(byte)
+		buf[7] = (v >> 56) & 0xff castto(byte)
+		-> write(f, buf[:n])
 	;;
-	buf[0] = (v >> 0) & 0xff castto(byte)
-	buf[1] = (v >> 8) & 0xff castto(byte)
-	buf[2] = (v >> 16) & 0xff castto(byte)
-	buf[3] = (v >> 24) & 0xff castto(byte)
-	buf[4] = (v >> 32) & 0xff castto(byte)
-	buf[5] = (v >> 40) & 0xff castto(byte)
-	buf[6] = (v >> 48) & 0xff castto(byte)
-	buf[7] = (v >> 56) & 0xff castto(byte)
-	-> write(f, buf[:n])
 }
 
 const putbe = {f, v, n
 	var buf : byte[8]
 
-	if !ensurewrite(f, n)
-		-> 0
+	match ensurewrite(f, n)
+	| `Err:	-> `Err
+	| `Eof:	-> `Eof
+	| `Ok _:
+		buf[0] = (v >> 56) & 0xff castto(byte)
+		buf[1] = (v >> 48) & 0xff castto(byte)
+		buf[2] = (v >> 40) & 0xff castto(byte)
+		buf[3] = (v >> 32) & 0xff castto(byte)
+		buf[4] = (v >> 24) & 0xff castto(byte)
+		buf[5] = (v >> 16) & 0xff castto(byte)
+		buf[6] = (v >> 8) & 0xff castto(byte)
+		buf[7] = (v >> 0) & 0xff castto(byte)
+		-> write(f, buf[8-n:])
 	;;
-	buf[0] = (v >> 56) & 0xff castto(byte)
-	buf[1] = (v >> 48) & 0xff castto(byte)
-	buf[2] = (v >> 40) & 0xff castto(byte)
-	buf[3] = (v >> 32) & 0xff castto(byte)
-	buf[4] = (v >> 24) & 0xff castto(byte)
-	buf[5] = (v >> 16) & 0xff castto(byte)
-	buf[6] = (v >> 8) & 0xff castto(byte)
-	buf[7] = (v >> 0) & 0xff castto(byte)
-	-> write(f, buf[8-n:])
 }
 
--- a/lib/regex/redump.myr
+++ b/lib/regex/redump.myr
@@ -57,10 +57,13 @@
 const dump = {re, fd 
 	while true
 		match bio.readln(fd)
-		| `std.Some ln:
+		| `bio.Ok ln:
 			show(re, ln, regex.exec(re, ln))
 			std.slfree(ln)
-		| `std.None:
+		| `bio.Eof:
+			break
+		| `bio.Err:
+			std.put("error reading from input")
 			break
 		;;
 	;;
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -215,11 +215,11 @@
 	while true
 		lnum++
 		match bio.readln(f)
-		| `std.Some ln:
+		| `bio.Err:	std.fatal("unable to read {}\n", path)
+		| `bio.Eof:	break
+		| `bio.Ok ln:
 			(cflags, libs) = getcflags(ln, cflags, libs)
 			std.slfree(ln)
-		| `std.None:
-			break
 		;;
 	;;
 	bio.close(f)
@@ -251,7 +251,7 @@
 	-> (cflags, libs)
 }
 
-const getdeps = {b : build#, ds : depscan#, path
+const getdeps = {b, ds, path
 	var deps, lnum
 	var f
 
@@ -261,10 +261,11 @@
 	while true
 		lnum++
 		match bio.readln(f)
-		| `std.Some ln:
+		| `bio.Err:	std.fatal("unable to read {}\n", path)
+		| `bio.Eof:	break
+		| `bio.Ok ln:
 			deps = depname(deps, ln, lnum)
 			std.slfree(ln)
-		| `std.None:	break
 		;;
 	;;
 	bio.close(f)
@@ -315,19 +316,21 @@
 
 	f = openlib(lib, incs)
 	match bio.getc(f)
-	| `std.Some 'U': /* nothing */
-	| `std.Some _:	std.fatal("library {}: corrupt or invalid usefile\n", lib)
-	| `std.None:	std.fatal("library {}: could not read usefile\n", lib)
+	| `bio.Ok 'U': /* nothing */
+	| `bio.Ok _:	std.fatal("library {}: corrupt or invalid usefile\n", lib)
+	| `bio.Err:	std.fatal("library {}: could not read usefile\n", lib)
+	| `bio.Eof:	std.fatal("library {}: could not read usefile\n", lib)
 	;;
 	match bio.getbe32(f)
-	| `std.Some Abiversion:	/* nothing: version matches. */
-	| `std.Some v:	
+	| `bio.Ok Abiversion:	/* nothing: version matches. */
+	| `bio.Ok v:	
 		if v < Abiversion
 			std.fput(1, "library {}: warning: old abi version {}\n", lib, v)
 		else
 			std.fput(1, "library {}: usefile version {} unknown\n", lib, v)
 		;;
-	| `std.None:	std.fatal("library {}: corrupt or invalid usefile\n", lib)
+	| `bio.Eof:	std.fatal("library {}: corrupt or truncated usefile\n", lib)
+	| `bio.Err:	std.fatal("library {}: error reading usefile\n", lib)
 	;;
 	std.slfree(rdstr(f))
 
@@ -335,14 +338,15 @@
 	deps = [][:]
 	while !done
 		match bio.getc(f)
-		| `std.Some 'L':
+		| `bio.Ok 'L':
 			d = rdstr(f)
 			deps = std.slpush(deps, d)
-		| `std.Some 'X':
+		| `bio.Ok 'X':
 			d = rdstr(f)
 			dg.extlibs = std.slpush(dg.extlibs, d)
-		| `std.Some _:	done = true
-		| `std.None:	done = true
+		| `bio.Ok _:	done = true
+		| `bio.Eof:	done = true
+		| `bio.Err:	std.fatal("io error reading {}", lib)
 		;;
 	;;
 	bio.close(f)
@@ -388,10 +392,11 @@
 	var sl
 
 	match bio.getbe32(f)
-	| `std.Some l:
+	| `bio.Ok l:
 		len = l
 		sl = std.slalloc(len)
-	| `std.None:	std.die("string length not readable")
+	| `bio.Eof:	std.die("end of file while reading string")
+	| `bio.Err:	std.die("error while reading string")
 	;;
 	bio.read(f, sl)
 	-> sl