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