ref: b65a821ba2d8c753e974b02e541229dfd6754a6a
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 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 optfin : (ctx : optctx# -> byte[:][:]) ;; 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 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: 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, 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 == ':' -> `Some (true, true) /* optional arg */ elif c == '?' -> `Some (true, false) /* no arg */ else -> `Some (false, false) ;; ;; ;; -> `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 }