ref: 9125dee98dc51e46a35c5e30a8a228031dcca44d
parent: 03af679a2a685afe93242d2751ea1a94d9c17569
author: Ori Bernstein <[email protected]>
date: Thu Apr 4 12:40:54 EDT 2013
Fix up option parsing code.
--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -15,6 +15,7 @@
%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 @@
var w_val : int16
var i_val : int32
var l_val : int64
+ var z_val : size
var p_val : byte#
var c_val : char
@@ -119,6 +121,10 @@
'l':
(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)
--- 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,6 +14,7 @@
args : byte[:][:]
/* state */
+ done : bool /* if we've seen '--', everything's an arg */
argidx : size
curarg : byte[:]
arglist : byte[:][:]
@@ -18,8 +21,7 @@
;;
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 @@
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
-
- 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 = ""
;;
- -> 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)
+ ;;
+ ;;
+ ;;
+ -> (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
--- a/libstd/test.myr
+++ b/libstd/test.myr
@@ -6,6 +6,7 @@
var i
var opt
var o
+ var a
std.put("args.len = %i\n", args.len)
for i = 0; i < args.len; i++
@@ -12,14 +13,19 @@
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. */