ref: d7c4bac9357a6d5e3dfd691434f8d9a47d79f0dc
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"
use "sleq"
use "fmt"
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
var spbuf : byte[:][5]
var xpid, sp
sp = bstrsplit(spbuf[:], status, " ")
if sp.len == 0
-> (`Wfailure, -1)
;;
match intparse(sp[0])
| `Some pid:
xpid = pid
/* exits(nil) => sp[0] either not present or equal to '' */
if sp.len == 4 || (sp.len == 5 && sleq(sp[4], "''"))
st = `Wsuccess
elif sp.len == 5
st = `Wfailure
else /* we have a malformed await message */
st = `Waiterror
;;
| `None:
xpid = -1
st = `Waiterror
;;
-> (st, xpid)
}