ref: bc046635d6368a7e81bcc172efb121d54b05ebcd
dir: /lib/std/wait+plan9.myr/
use sys
use "alloc"
use "chartype"
use "die"
use "extremum"
use "hashfuncs"
use "hasprefix"
use "htab"
use "intparse"
use "option"
use "strsplit"
use "striter"
use "syswrap"
use "utf"
pkg std =
	type waitstatus = union
		`Wsuccess
		`Wfailure
		`Wsignalled
		`Waiterror
	;;
	const wait	: (pid : pid -> waitstatus)
;;
var statusinit	: bool = false
var statusmap	: htab(pid, waitstatus)#
const wait = {pid
	var buf : byte[512]
	var xpid, status
	var n
	if !statusinit
		statusmap = mkht(inthash, inteq)
		statusinit = true
	;;
		
	match htget(statusmap, pid)
	| `Some st:
		htdel(statusmap, pid)
		-> st
	| `None:	/* nothing */
	;;
	while true
		n = sys.await(buf[:])
		if n < 0
			-> `Waiterror
		;;
		(status, xpid) = parsestatus(buf[:n])
		if xpid == pid
			-> status
		else
			htput(statusmap, pid, status)
		;;
	;;
	/* impossible */
	-> `Waiterror
}
const parsestatus = {status	-> (waitstatus, pid)
	var st : waitstatus, xpid, sp
	sp = strsplit(status, " ")
	if sp.len == 0
		slfree(sp)
		-> (`Wfailure, -1)
	;;
	match intparse(sp[0])
	| `Some pid:
		xpid = pid
		if sp.len == 4 || (sp.len == 5 && sp[4].len > 0)	/* we exited with nil */
			st = `Wsuccess
		elif sp.len == 5	/* we have a status */
			st = `Wfailure
		else	/* we have a malformed await message */
			st = `Waiterror
		;;
	| `None:
		xpid = -1
		st = `Waiterror
	;;
	slfree(sp)
	-> (st, xpid)
}