shithub: mc

Download patch

ref: 3400b0428b9147012553c6f2280147d8dc99bbf1
parent: c4d04d5ed7a782baf87e5beea2a2d95e31bebc5b
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Oct 6 09:32:25 EDT 2015

Fix up error handling for syswrap+posixy.myr

--- a/bench/runbench.myr
+++ b/bench/runbench.myr
@@ -13,15 +13,6 @@
 	std.put("total:\t{}s\n", tot);
 }
 
-
-generic perror = {a : @a::(numeric,integral), msg : byte[:] -> @a
-	if a < 0
-		std.fatal("{}", msg)
-	else
-		-> a
-	;;
-}
-
 const timeit = {prog -> flt64
 	var avg, m, d, x, n : flt64
 
@@ -49,10 +40,10 @@
 	if pid < 0
 		std.fatal("Could not fork\n");
 	elif pid == 0
-		infd = perror(std.open("/dev/zero", std.Ordonly), "could not open /dev/zero")
-		outfd = perror(std.open("/dev/null", std.Owronly), "could not open /dev/null")
-		perror(std.dup2(infd, 0), "could not redirect stdin")
-		perror(std.dup2(outfd, 1), "could not redirect stdout")
+		infd = std.try(std.open("/dev/zero", std.Ordonly))
+		outfd = std.try(std.open("/dev/null", std.Owronly))
+		std.try(std.dup2(infd, 0))
+		std.try(std.dup2(outfd, 1))
 		std.execv(prog, [prog][:])
 		std.fatal("Failed to exec\n")
 	else
--- a/doc/lang.txt
+++ b/doc/lang.txt
@@ -818,6 +818,8 @@
 
 7. STANDARD LIBRARY:
 
+    This is documented separately.
+
 8. GRAMMAR:
 
 9. FUTURE DIRECTIONS:
--- a/doc/mc.1
+++ b/doc/mc.1
@@ -15,6 +15,11 @@
 .I filename.myr
 then the the object file that is generated will be named
 .I filename.o.
+.PP
+Any text between the first '+' in the file name and the suffix are
+stripped. This functionality is used to specify system tags for
+tools like 'mbld'.
+.PP
 If the filename does not end with the suffix
 .I .myr
 then the suffix
--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -49,7 +49,7 @@
 	const flush	: (f : file# -> bool)
 
 	/* seeking */
-	const seek	: (f : file#, std.off -> std.off)
+	const seek	: (f : file#, std.off -> std.result(std.off, ioerr))
 
 	/* single unit operations */
 	const putb	: (f : file#, b : byte	-> status(std.size))
@@ -133,13 +133,9 @@
 
 /* open the file, and return it */
 const sysopen = {path, mode, openmode, perm
-	var fd
-
-	fd = std.openmode(path, openmode, perm castto(int64))
-	if fd < 0
-		-> `std.Fail "could not open fd"
-	else
-		-> `std.Ok mkfile(fd, mode)
+	match std.openmode(path, openmode, perm castto(int64))
+	| `std.Ok fd:	-> `std.Ok mkfile(fd, mode)
+	| `std.Fail e:	-> `std.Fail "could not open fd"
 	;;
 }
 
@@ -189,8 +185,8 @@
 returning the number of bytes read.
 */
 const read = {f, dst
-	var n, d
-	var count
+	var count : std.size
+	var d : byte[:]
 
 	/* Clear the error state so we can retry */
 	if f.lasterr != 0
@@ -218,21 +214,22 @@
 	/* Read the rest directly from the fd */
 	d = dst[count:]
 	while dst.len > 0
-		n = std.read(f.fd, d)
-		if n == 0
+		match std.read(f.fd, d)
+		| `std.Ok 0:
 			break
-		elif n < 0
-			if count > 0
-				f.lasterr = n castto(std.errno)
+		| `std.Ok n:
+			count += n
+			d = d[n:]
+		| `std.Fail err:
+			if count == 0
+				-> `Err errtype(err)
+			else
+				f.lasterr = err
 			;;
 			break
 		;;
-		count += n
-		d = d[n:]
 	;;
-	if n < 0 && count == 0
-		-> `Err errtype(n)
-	elif count == 0
+	if count == 0
 		-> `Eof
 	else
 		-> `Ok dst[:count]
@@ -256,7 +253,10 @@
 
 const seek = {f, off
 	flush(f)
-	-> std.seek(f.fd, off, std.Seekset)
+	match std.seek(f.fd, off, std.Seekset)
+	| `std.Ok ret:	-> `std.Ok ret
+	| `std.Fail e:	-> `std.Fail errtype(e)
+	;;
 }
 
 /* writes a single byte to the output stream */
@@ -581,19 +581,19 @@
 
 /* blats a buffer to an fd */
 const writebuf = {fd, src
-	var n
 	var count
 
 	count = 0
 	while src.len != 0
-		n = std.write(fd, src)
-		if n == 0
+		match std.write(fd, src)
+		| `std.Ok 0:
 			-> `Eof
-		elif n < 0
-			-> `Err errtype(n)
+		| `std.Ok n:
+			count += n
+			src = src[n:]
+		| `std.Fail e:
+			-> `Err errtype(e)
 		;;
-		count += n
-		src = src[n:]
 	;;
 :writedone
 	-> `Ok count
@@ -606,7 +606,6 @@
 the read buffer.
 */
 const fill = {f, min
-	var n
 	var count
 
 	count = 0
@@ -615,27 +614,28 @@
 		-> `Err geterr(f)
 	;;
 	while count < min
-		n = std.read(f.fd, f.rbuf[f.rend:])
 		/*
 		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
+		match std.read(f.fd, f.rbuf[f.rend:])
+		| `std.Ok 0:
 			break
-		elif n < 0
+		| `std.Ok n:
+			count += n
+			f.rend += n
+		| `std.Fail e:
 			if count > 0
-				f.lasterr = n castto(std.errno)
+				f.lasterr = e
+			else
+				-> `Err errtype(e)
 			;;
 			break
 		;;
-		count += n
-		f.rend += n
 	;;
 
-	if n < 0 && count == 0
-		-> `Err errtype(n)
-	elif count == 0
+	if count == 0
 		-> `Eof
 	else
 		-> `Ok count
@@ -647,10 +647,10 @@
 
 	e = f.lasterr
 	f.lasterr = 0
-	-> errtype(e castto(std.size))
+	-> errtype(e)
 }
 
-const errtype : (e : std.size -> ioerr )= {e : std.size -> ioerr
+const errtype : (e : std.errno -> ioerr )= {e : std.errno -> ioerr
 	var errno
 
 	errno = e castto(std.errno)
--- a/lib/std/blat.myr
+++ b/lib/std/blat.myr
@@ -1,4 +1,5 @@
 use "syswrap.use"
+use "result.use"
 
 pkg std =
 	const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
@@ -6,27 +7,26 @@
 ;;
 
 const blat = {path, buf, perm
-	var fd
-
-	fd = openmode(path, Ocreat|Owronly, perm)
-	if fd < 0
-		-> false
+	match openmode(path, Ocreat|Owronly, perm)
+	| `Ok fd:	-> fblat(fd, buf)
+	| `Fail e:	-> false
 	;;
-	-> fblat(fd, buf)
 }
 
 
 const fblat = {fd, buf
-	var written, n
+	var count
 
-	n = 0
+	count = 0
 	while true
-		written = write(fd, buf[n:])
-		if written <= 0
-			goto done
+		match write(fd, buf[count:])
+		| `Fail e:	-> false
+		| `Ok n:
+			if n == 0
+				break
+			;;
+			count += n
 		;;
-		n += written
 	;;
-:done
-	-> written == 0 && n == buf.len
+	-> count == buf.len
 }
--- a/lib/std/execvp.myr
+++ b/lib/std/execvp.myr
@@ -8,8 +8,8 @@
 use "syswrap.use"
 
 pkg std = 
-	const execvp	: (cmd : byte[:], args : byte[:][:] -> int64)
-	const execvpe	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
+	const execvp	: (cmd : byte[:], args : byte[:][:] -> errno)
+	const execvpe	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> errno)
 ;;
 
 const execvp = {cmd, args
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -9,6 +9,7 @@
 use "introspect.use"
 use "intparse.use"
 use "option.use"
+use "result.use"
 use "sleq.use"
 use "slpush.use"
 use "strbuf.use"
@@ -529,15 +530,18 @@
 }
 
 const writeall = {fd, buf
-	var n, len
+	var len
 
 	len = 0
 	while true
-		n = write(fd, buf)
-		if n <= 0 || n >= len
-			break
+		match write(fd, buf[len:])
+		| `Fail err:	break
+		| `Ok n:
+			len += n
+			if n == 0 || len == buf.len
+				break
+			;;
 		;;
-		len += n
 	;;
 	-> len
 }
--- a/lib/std/result.myr
+++ b/lib/std/result.myr
@@ -1,5 +1,3 @@
-use "die.use"
-
 pkg std =
 	type result(@a, @b) = union
 		`Ok	@a
--- a/lib/std/slurp.myr
+++ b/lib/std/slurp.myr
@@ -3,41 +3,42 @@
 use "result.use"
 use "extremum.use"
 use "syswrap.use"
+use "errno.use"
 use "types.use"
 
 pkg std =
-	const slurp : (path : byte[:] -> result(byte[:], byte[:]))
-	const fslurp : (path : fd -> result(byte[:], byte[:]))
+	const slurp : (path : byte[:] -> result(byte[:], errno))
+	const fslurp : (path : fd -> result(byte[:], errno))
 ;;
 
 const Bufstart = 4096
 
 const slurp = {path
-	var fd
-	fd = open(path, Ordonly)
-	if fd < 0
-		-> `Fail "Could not open file"
+	match open(path, Ordonly)
+	| `Ok fd:	-> fslurp(fd)
+	| `Fail e:	-> `Fail e
 	;;
-	-> fslurp(fd)
 }
 
 const fslurp = {fd
 	var len, bufsz
 	var buf
-	var n
 
 	len = 0
 	bufsz = Bufstart
 	buf = slalloc(bufsz)
 	while true
-		n = read(fd, buf[len:])
-		if n <= 0
-			goto done
+		match read(fd, buf[len:])
+		| `Ok n:
+			if n == 0
+				-> `Ok buf[:len]
+			;;
+			len += n
+			bufsz *= 2
+			buf = slgrow(buf, bufsz)
+		| `Fail e:
+			-> `Fail e
 		;;
-		len += n
-		bufsz *= 2
-		buf = slgrow(buf, bufsz)
 	;;
-:done
-	-> `Ok buf[:len]
+	die("unreachable")
 }
--- a/lib/std/spork.myr
+++ b/lib/std/spork.myr
@@ -3,10 +3,11 @@
 use "fmt.use"
 use "result.use"
 use "syswrap.use"
+use "errno.use"
 
 pkg std =
-	const spork	: (cmd : byte[:][:]	-> result((pid, fd, fd), int))
-	const sporkfd	: (cmd : byte[:][:], infd : fd, outfd : fd	-> result(pid, int))
+	const spork	: (cmd : byte[:][:]	-> result((pid, fd, fd), errno))
+	const sporkfd	: (cmd : byte[:][:], infd : fd, outfd : fd	-> result(pid, errno))
 ;;
 
 const spork = {cmd
@@ -14,13 +15,13 @@
 	var err
 
 	/* open up pipes */
-	err = pipe(&infds)
-	if err != 0
-		-> `Fail (-err castto(int))
+	err = pipe(&infds) 
+	if err != Enone
+		-> `Fail err
 	;;
 	err = pipe(&outfds)
-	if err != 0
-		-> `Fail (-err castto(int))
+	if err != Enone
+		-> `Fail err
 	;;
 
 	match sporkfd(cmd, infds[0] castto(fd), outfds[1] castto(fd))
@@ -35,7 +36,7 @@
 }
 
 const sporkfd = {cmd, infd, outfd
-	var pid
+	var pid, err
 
 	pid = fork()
 	/* error  */
@@ -44,16 +45,22 @@
 	/* child */
 	elif pid == 0
 		/* stdin/stdout for our communication. */
-		if dup2(infd castto(fd), 0) != 0
-			fatal("unable to set stdin\n")
+		match dup2(infd castto(fd), 0)
+		| `Ok _:	/* nothing */
+		| `Fail e:	-> `Fail e
 		;;
-		if dup2(outfd castto(fd), 1) != 1
-			fatal("unable to set stdout\n")
+		match dup2(outfd castto(fd), 1)
+		| `Ok _:	/* nothing */
+		| `Fail e:	-> `Fail e
 		;;
 		close(infd)
 		close(outfd)
-		execvp(cmd[0], cmd) < 0
-		fatal("failed to exec {}\n", cmd[0])
+		err = execvp(cmd[0], cmd)
+		if err != Enone
+			-> `Fail err
+		;;
+		/* if fork succeeds, we never return */
+		die("unreachable")
 	/* parent */
 	else
 		-> `Ok pid
--- a/lib/std/syswrap+posixy.myr
+++ b/lib/std/syswrap+posixy.myr
@@ -1,8 +1,9 @@
 use sys
 use "cstrconv.use"
+use "errno.use"
 use "option.use"
+use "result.use"
 use "types.use"
-use "errno.use"
 
 pkg std =
 	type fd		= sys.fd
@@ -29,23 +30,22 @@
 	const Ordwr    	: fdopt = sys.Ordwr	castto(fdopt)
 	const Ocreat   	: fdopt = sys.Ocreat	castto(fdopt)
 	const Otrunc   	: fdopt = sys.Otrunc	castto(fdopt)
-	const Oappend  	: fdopt = sys.Oappend	castto(fdopt)
 	const Odir	: fdopt = sys.Odir	castto(fdopt)
 
 	/* fd stuff */
-	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 read	: (fd : fd, buf : byte[:] -> size)
-	const write	: (fd : fd, buf : byte[:] -> size)
-	const pipe	: (fds : fd[2]# -> int64)
-	const seek	: (fd : fd, delta : off, whence : whence -> off)
-	const dup2	: (ofd : fd, nfd : fd -> fd)
+	const open	: (path : byte[:], opts : fdopt -> result(fd, errno))
+	const openmode	: (path : byte[:], opts : fdopt, mode : int64 -> result(fd, errno))
+	const close	: (fd : fd -> errno)
+	const creat	: (path : byte[:], mode : int64 -> result(fd, errno))
+	const read	: (fd : fd, buf : byte[:] -> result(size, errno))
+	const write	: (fd : fd, buf : byte[:] -> result(size, errno))
+	const pipe	: (fds : fd[2]# -> errno)
+	const seek	: (fd : fd, delta : off, whence : whence -> result(off, errno))
+	const dup2	: (ofd : fd, nfd : fd -> result(fd, errno))
 
 	/* useful/portable bits of stat */
-	const fmtime	: (f : byte[:]	-> option(time))
-	const fsize	: (f : byte[:]	-> option(off))
+	const fmtime	: (f : byte[:]	-> result(time, errno))
+	const fsize	: (f : byte[:]	-> result(off, errno))
 	const fexists	: (f : byte[:]	-> bool)
 
 	/* useful/portable bits of uname */
@@ -60,27 +60,28 @@
 	const getpid	: ( -> pid)
 	const suicide	: ( -> void)
 	const fork	: (-> pid)
-	const execv	: (cmd : byte[:], args : byte[:][:] -> int64)
-	const execve	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
-	const waitpid	: (pid:pid, loc:int32#, opt : int64	-> int64)
+	const execv	: (cmd : byte[:], args : byte[:][:] -> errno)
+	const execve	: (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> errno)
 
 	pkglocal const Canunmap	: bool = true
 	pkglocal const getmem	: (sz : size -> byte#)
 	pkglocal const freemem	: (p : byte#, sz : size -> void)
 	pkglocal const curtime	: (-> time)
+	pkglocal const waitpid	: (pid:pid, loc:int32#, opt : int64	-> int64)
 ;;
 
 /* fd stuff */
-const open	= {path, opts;	-> sys.open(path, opts castto(sys.fdopt)) castto(fd)}
-const openmode	= {path, opts, mode;	-> sys.openmode(path, opts castto(sys.fdopt), mode) castto(fd)}
-const close	= {fd;		-> sys.close(fd castto(sys.fd))}
-const creat	= {path, mode;	-> sys.creat(path, mode) castto(fd)}
-const read	= {fd, buf;	-> sys.read(fd castto(sys.fd), buf) castto(size)}
-const write	= {fd, buf;	-> sys.write(fd castto(sys.fd), buf) castto(size)}
-const pipe	= {fds;		-> sys.pipe(fds castto(sys.fd[2]#))}
-const seek	= {fd, delta, whence;	-> sys.lseek(fd castto(sys.fd), delta castto(sys.off), whence castto(sys.whence)) castto(off)}
-const dup2	= {ofd, nfd;	-> sys.dup2(ofd castto(sys.fd), nfd castto(sys.fd)) castto(fd)}
+const open	= {path, opts;	-> check(sys.open(path, opts castto(sys.fdopt)))}
+const openmode	= {path, opts, mode;	-> check(sys.openmode(path, opts castto(sys.fdopt), mode))}
+const close	= {fd;		-> sys.close(fd castto(sys.fd)) castto(errno)}
 
+const creat	= {path, mode;	-> check(sys.creat(path, mode))}
+const read	= {fd, buf;	-> check(sys.read(fd castto(sys.fd), buf))}
+const write	= {fd, buf;	-> check(sys.write(fd castto(sys.fd), buf))}
+const pipe	= {fds;		-> sys.pipe(fds castto(sys.fd[2]#)) castto(errno)}
+const seek	= {fd, delta, whence;	-> check(sys.lseek(fd castto(sys.fd), delta castto(sys.off), whence castto(sys.whence)))}
+const dup2	= {ofd, nfd;	-> check(sys.dup2(ofd castto(sys.fd), nfd castto(sys.fd)) castto(fd))}
+
 /* path manipulation */
 const mkdir	= {path, mode;	-> sys.mkdir(path, mode)}
 const chdir	= {path;	-> sys.chdir(path) == 0}
@@ -99,8 +100,8 @@
 const getpid	= {;		-> sys.getpid() castto(pid)}
 const suicide	= {;		sys.kill(sys.getpid(), 6)}	/* kill self with sigabort */
 const fork	= {;		-> sys.fork() castto(pid)}
-const execv	= {cmd, args;	-> sys.execv(cmd, args)}
-const execve	= {cmd, args, env;	-> sys.execve(cmd, args, env)}
+const execv	= {cmd, args;	-> sys.execv(cmd, args) castto(errno)}
+const execve	= {cmd, args, env;	-> sys.execve(cmd, args, env) castto(errno)}
 const sleep	= {time;	sys.sleep(time)}
 
 /* memory stuff */
@@ -125,24 +126,34 @@
 }
 
 const fmtime = {path
-	var sb
+	var sb, r
 	var sec, nsec
 
-	if sys.stat(path, &sb) == 0
+	r = sys.stat(path, &sb)
+	if r >= 0
 		sec = sb.mtime.sec castto(time)
 		nsec = sb.mtime.nsec castto(time)
-		-> `Some sec*1000 + nsec/1_000_000
+		-> `Ok sec*1000 + nsec/1_000_000
 	else
-		-> `None
+		-> check(r)
 	;;
 }
 
 const fsize = {path
-	var sb
+	var sb, r
 
-	if sys.stat(path, &sb) == 0
-		-> `Some (sb.size castto(off))
+	r = sys.stat(path, &sb)
+	if r >= 0
+		-> `Ok (sb.size castto(off))
 	else
-		-> `None
+		-> check(r)
+	;;
+}
+
+generic check = {e : @a::(integral, numeric) -> result(@b, errno)
+	if e < 0
+		-> `Fail e castto(errno)
+	else
+		-> `Ok e castto(@b)
 	;;
 }
--- a/mbld/build.myr
+++ b/mbld/build.myr
@@ -479,12 +479,12 @@
 	up to date.
 	*/
 	match std.fmtime(src)
-	| `std.Some mt:	srcmt = mt
-	| `std.None:	std.fatal("could not stat {}\n", src)
+	| `std.Ok mt:	srcmt = mt
+	| `std.Fail e:	std.fatal("could not stat {}: {}\n", src, e)
 	;;
 	match std.fmtime(dst)
-	| `std.Some mt:	dstmt = mt
-	| `std.None:	-> false
+	| `std.Ok mt:	dstmt = mt
+	| `std.Fail e:	-> false
 	;;
 	-> srcmt <= dstmt
 }