diff options
author | Ori Bernstein <ori@eigenstate.org> | 2013-04-04 16:40:54 -0400 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2013-04-04 16:40:54 -0400 |
commit | 9125dee98dc51e46a35c5e30a8a228031dcca44d (patch) | |
tree | 681fee3399251609ec3f5f00c0c3973138a8c374 | |
parent | 03af679a2a685afe93242d2751ea1a94d9c17569 (diff) | |
download | mc-9125dee98dc51e46a35c5e30a8a228031dcca44d.tar.gz |
Fix up option parsing code.
-rw-r--r-- | libstd/fmt.myr | 6 | ||||
-rw-r--r-- | libstd/optparse.myr | 66 | ||||
-rw-r--r-- | libstd/test.myr | 18 |
3 files changed, 69 insertions, 21 deletions
diff --git a/libstd/fmt.myr b/libstd/fmt.myr index ae2699a..4aba857 100644 --- a/libstd/fmt.myr +++ b/libstd/fmt.myr @@ -15,6 +15,7 @@ use "extremum.use" %w - A 16 bit integer %i - A 32 bit integer %l - A 64 bit integer + %z - A size %p - A pointer %c - A char */ @@ -90,6 +91,7 @@ const bfmtv = {buf, fmt, ap var w_val : int16 var i_val : int32 var l_val : int64 + var z_val : size var p_val : byte# var c_val : char @@ -120,6 +122,10 @@ const bfmtv = {buf, fmt, ap (l_val, ap) = vanext(ap) n += intfmt(buf[n:], l_val castto(int64), 10) ;; + 'z': + (z_val, ap) = vanext(ap) + n += intfmt(buf[n:], z_val castto(int64), 10) + ;; 'p': (p_val, ap) = vanext(ap) n += intfmt(buf[n:], p_val castto(int64), 16) diff --git a/libstd/optparse.myr b/libstd/optparse.myr index 8fba4b2..383e083 100644 --- a/libstd/optparse.myr +++ b/libstd/optparse.myr @@ -1,7 +1,9 @@ use "alloc.use" use "die.use" use "extremum.use" +use "fmt.use" use "slappend.use" +use "sys.use" use "types.use" use "utf.use" @@ -12,14 +14,14 @@ pkg std = args : byte[:][:] /* state */ + done : bool /* if we've seen '--', everything's an arg */ argidx : size curarg : byte[:] arglist : byte[:][:] ;; const optinit : (opts : byte[:], args : byte[:][:] -> optctx#) - const optnext : (ctx : optctx# -> char) - const optarg : (ctx : optctx# -> byte[:]) + const optnext : (ctx : optctx# -> [char, byte[:]]) ;; const optinit = {opts, args @@ -28,49 +30,83 @@ const optinit = {opts, args ctx = alloc() ctx.opts = opts ctx.args = args + + 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 + /* end of arguments */ if !ctx.curarg.len if !next(ctx) - -> Badchar + -> (Badchar, "") ;; ;; - (c, ctx.curarg) = striter(ctx.curarg) - -> c -} -const optarg = {ctx - var arg + (c, ctx.curarg) = striter(ctx.curarg) - if ctx.curarg.len > 0 + (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 ctx.argidx > ctx.args.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 - die("Arg needed") + arg = "" + ;; + + -> (c, arg) +} + +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) + ;; + ;; ;; - -> arg + -> (false, false) } const next = {ctx var i for i = ctx.argidx + 1; i < ctx.args.len; i++ - if decode(ctx.args[i]) == '-' + if !ctx.done && decode(ctx.args[i]) == '-' goto foundopt else - ctx.args = slappend(ctx.args, ctx.args[i]) + ctx.arglist = slappend(ctx.arglist, ctx.args[i]) ;; ;; -> false diff --git a/libstd/test.myr b/libstd/test.myr index b0ad950..f8ff2f1 100644 --- a/libstd/test.myr +++ b/libstd/test.myr @@ -6,20 +6,26 @@ const main = {args : byte[:][:] var i var opt var o + var a std.put("args.len = %i\n", args.len) for i = 0; i < args.len; i++ std.put("args[%i] = %s\n", i, args[i]) ;; - opt = std.optinit("asdf:", args) - while (o = std.optnext(opt)) != std.Badchar - std.put("option %c\n", o) - match o - 'a': std.put("\targ=%s\n", std.optarg(opt));; - 'b': std.put("\targ=%s\n", std.optarg(opt));; + opt = std.optinit("asdf:g?", args) + std.put("arglen = %i\n", opt.args.len) + while true + (o, a) = std.optnext(opt) + if o == std.Badchar + goto done ;; + std.put("option %c, arg = %s\n", o, a) ;; +:done + for i = 0; i < opt.arglist.len; i++ + std.put("arg %s\n", opt.arglist[i]) + ;; /* try the byte allocator for large variety of sizes. */ |