ref: bedcec2e2cb62540375ebec97adbb725e28fb791
dir: /libstd/optparse.myr/
use "alloc.use"
use "die.use"
use "extremum.use"
use "fmt.use"
use "option.use"
use "slpush.use"
use "syswrap.use"
use "syswrap-ss.use"
use "types.use"
use "utf.use"
pkg std =
type optdef = struct
argdesc : byte[:]
opts : optdesc[:]
;;
type optdesc = struct
opt : char
arg : byte[:]
desc : byte[:]
needed : bool
;;
type optctx = struct
/* public variables */
args : byte[:][:]
/* data passed in */
optdef : optdef#
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 : (optargs : byte[:][:], def : optdef# -> optctx#)
const optnext : (ctx : optctx# -> (char, byte[:]))
const optdone : (ctx : optctx# -> bool)
const optfin : (ctx : optctx# -> byte[:][:])
const optusage : (ctx : optctx# -> void)
;;
const optinit = {args, def
var ctx
ctx = alloc()
ctx.optargs = args
ctx.optdef = def
ctx.optdone = false
ctx.finished = false
ctx.argidx = 0
ctx.curarg = [][:]
ctx.args = [][:]
next(ctx)
-> ctx
}
const optfin = {ctx
var a
a = ctx.args
free(ctx)
-> a
}
const optnext = {ctx
var c
var arg
(c, ctx.curarg) = striter(ctx.curarg)
match optinfo(ctx, c)
| `None:
if c == 'h' || c == '?'
optusage(ctx)
exit(0)
else
fatal(1, "unexpected argument '%c'\n", c)
;;
| `Some (true, needed):
/* -arg => '-a' 'rg' */
if ctx.curarg.len > 0
arg = ctx.curarg
ctx.curarg = ctx.curarg[ctx.curarg.len:]
next(ctx)
/* '-a rg' => '-a' 'rg' */
elif ctx.argidx < (ctx.optargs.len - 1)
arg = ctx.optargs[ctx.argidx + 1]
ctx.argidx++
next(ctx)
elif needed
put("Expected argument for %c\n", c)
exit(1)
;;
| `Some (false, _):
arg = ""
if ctx.curarg.len == 0
next(ctx)
;;
;;
-> (c, arg)
}
const optdone = {ctx
-> ctx.curarg.len == 0 && ctx.finished
}
const optinfo = {ctx, opt
for o in ctx.optdef.opts
if o.opt == opt
-> `Some (o.arg.len != 0, o.needed)
;;
;;
-> `None
}
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 = slpush(ctx.args, ctx.optargs[i])
;;
;;
ctx.finished = true
-> false
:foundopt
ctx.argidx = i
ctx.curarg = ctx.optargs[i][1:]
-> true
}
const optusage = {ctx
std.put("usage: %s [-h?]", ctx.optargs[0])
for o in ctx.optdef.opts
std.put("[-%c%s%s] ", o.opt, sep(o.arg), o.arg)
;;
std.put("%s\n", ctx.optdef.argdesc)
std.put("\t-h\tprint this help message\n")
std.put("\t-?\tprint this help message\n")
for o in ctx.optdef.opts
std.put("\t%c%s%s\t%s\n", o.opt, sep(o.arg), o.arg, o.desc)
;;
}
const sep = {s
if s.len > 0
-> " "
else
-> ""
;;
}