ref: 3b80bdf127a0e3d1551a4393008f702ca022f2b3
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 /* data passed in */ opts : byte[:] args : byte[:][:] /* state */ optdone : bool /* if we've seen '--', everything's an arg */ done : bool /* if we've processed all the args */ argidx : size curarg : byte[:] arglist : byte[:][:] ;; const optinit : (opts : byte[:], args : byte[:][:] -> optctx#) const optnext : (ctx : optctx# -> [char, byte[:]]) const optdone : (ctx : optctx# -> bool) ;; const optinit = {opts, args var ctx ctx = alloc() ctx.opts = opts ctx.args = args ctx.optdone = false ctx.done = false ctx.argidx = 0 ctx.arglist = [][:] ctx.curarg = [][:] 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.args.len - 1) arg = ctx.args[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.done } const optinfo = {ctx, arg var s var c s = ctx.opts 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) } const next = {ctx var i for i = ctx.argidx + 1; i < ctx.args.len; i++ if !ctx.optdone && decode(ctx.args[i]) == '-' goto foundopt else ctx.arglist = slappend(ctx.arglist, ctx.args[i]) ;; ;; ctx.done = true -> false :foundopt ctx.argidx = i ctx.curarg = ctx.args[i][1:] -> true }