summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2013-04-04 16:40:54 -0400
committerOri Bernstein <ori@eigenstate.org>2013-04-04 16:40:54 -0400
commit9125dee98dc51e46a35c5e30a8a228031dcca44d (patch)
tree681fee3399251609ec3f5f00c0c3973138a8c374
parent03af679a2a685afe93242d2751ea1a94d9c17569 (diff)
downloadmc-9125dee98dc51e46a35c5e30a8a228031dcca44d.tar.gz
Fix up option parsing code.
-rw-r--r--libstd/fmt.myr6
-rw-r--r--libstd/optparse.myr66
-rw-r--r--libstd/test.myr18
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. */