summaryrefslogtreecommitdiff
path: root/libstd/optparse.myr
blob: 8fba4b2125b9ba37246dc782d0a44319ad1b833e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use "alloc.use"
use "die.use"
use "extremum.use"
use "slappend.use"
use "types.use"
use "utf.use"

pkg std =
	type optctx = struct
		/* data passed in */
		opts	: byte[:]
		args	: byte[:][:]

		/* state */
		argidx	: size
		curarg	: byte[:]
		arglist	: byte[:][:]
	;;

	const optinit	: (opts	: byte[:], args : byte[:][:] -> optctx#)
	const optnext	: (ctx : optctx# -> char)
	const optarg	: (ctx : optctx# -> byte[:])
;;

const optinit = {opts, args
	var ctx

	ctx = alloc()
	ctx.opts = opts
	ctx.args = args
	ctx.argidx = 0
	ctx.arglist = [][:]
	ctx.curarg = [][:]
	next(ctx)
	-> ctx
}

const optnext = {ctx
	var c

	if !ctx.curarg.len
		if !next(ctx)
			-> Badchar
		;;
	;;
	(c, ctx.curarg) = striter(ctx.curarg)
	-> c
}

const optarg = {ctx
	var arg

	if ctx.curarg.len > 0
		arg = ctx.curarg
		ctx.curarg = ctx.curarg[ctx.curarg.len:]
	elif ctx.argidx > ctx.args.len
		arg = ctx.args[ctx.argidx + 1]
		ctx.argidx++
		next(ctx)
	else
		die("Arg needed")
	;;
	-> arg
}

const next = {ctx
	var i

	for i = ctx.argidx + 1; i < ctx.args.len; i++
		if decode(ctx.args[i]) == '-'
			goto foundopt
		else
			ctx.args = slappend(ctx.args, ctx.args[i])
		;;
	;;
	-> false
:foundopt
	ctx.argidx = i
	ctx.curarg = ctx.args[i][1:]
	-> true
}