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