ref: 64968bcc3b6f03415aac19c8cdfff83c9e3f424e
dir: /libstd/optparse.myr/
use "alloc.use"
use "die.use"
use "extremum.use"
use "fmt.use"
use "slappend.use"
use "sys.use"
use "types.use"
use "utf.use"
pkg std =
type optctx = struct
/* public variables */
args : byte[:][:]
/* data passed in */
optstr : byte[:]
optargs : byte[:][:]
/* state */
optdone : bool /* if we've seen '--', everything's an arg */
finished : bool /* if we've processed all the optargs */
argidx : size
curarg : byte[:]
;;
const optinit : (optstr: byte[:], optargs : byte[:][:] -> optctx#)
const optnext : (ctx : optctx# -> [char, byte[:]])
const optdone : (ctx : optctx# -> bool)
;;
const optinit = {optstr, optargs
var ctx
ctx = alloc()
ctx.optstr= optstr
ctx.optargs =optargs
ctx.optdone = false
ctx.finished = false
ctx.argidx = 0
ctx.curarg = [][:]
ctx.args = [][:]
next(ctx)
-> ctx
}
const optnext = {ctx
var c
var arg
var valid
var tryarg
var needarg
(c, ctx.curarg) = striter(ctx.curarg)
(valid, tryarg, needarg) = optinfo(ctx, c)
if !valid
put("Unexpected argument %c\n", c)
exit(1)
elif tryarg && ctx.curarg.len > 0
arg = ctx.curarg
ctx.curarg = ctx.curarg[ctx.curarg.len:]
elif tryarg && ctx.argidx < (ctx.optargs.len - 1)
arg = ctx.optargs[ctx.argidx + 1]
ctx.argidx++
next(ctx)
elif needarg
put("Expected argument for %c\n", c)
exit(1)
else
arg = ""
;;
if !ctx.curarg.len
next(ctx)
;;
-> (c, arg)
}
const optdone = {ctx
-> !ctx.curarg.len && ctx.finished
}
const optinfo = {ctx, arg
var s
var c
s = ctx.optstr
while s.len != 0
(c, s) = striter(s)
if c == arg
(c, s) = striter(s)
/* mandatory arg */
if c == ':'
-> (true, true, true)
/* optional arg */
elif c == '?'
-> (true, true, false)
/* no arg */
else
-> (true, false, false)
;;
;;
;;
-> (false, false, false)
}
const next = {ctx
var i
for i = ctx.argidx + 1; i < ctx.optargs.len; i++
if !ctx.optdone && decode(ctx.optargs[i]) == '-'
goto foundopt
else
ctx.args = slappend(ctx.args, ctx.optargs[i])
;;
;;
ctx.finished = true
-> false
:foundopt
ctx.argidx = i
ctx.curarg = ctx.optargs[i][1:]
-> true
}