ref: af128ae8ef5c2d4627ab90e02efe15eca7b8cdb5
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)
}