Differences From
Artifact [50677a3c0c]:
1 1 -- vim: ft=terra
2 -return function(tbl)
2 +return function(tbl,opts)
3 + opts = opts or {}
3 4 local options = terralib.types.newstruct('options') do
4 5 local flags = '' for _,d in pairs(tbl) do flags = flags .. d[1] end
5 - local helpstr = 'usage: parsav [-' .. flags .. '] [<arg>...]\n'
6 + local flagstr = '[-' .. flags .. ']'
7 + local helpstr = '\n'
6 8 options.entries = {
7 9 {field = 'arglist', type = lib.mem.ptr(rawstring)}
8 10 }
9 11 local shortcases, longcases, init, verifiers = {}, {}, {}, {}
10 12 local self = symbol(&options)
11 13 local arg = symbol(rawstring)
12 14 local idx = symbol(uint)
13 15 local argv = symbol(&rawstring)
14 16 local argc = symbol(int)
15 17 local optstack = symbol(intptr)
18 + local subcmd = symbol(intptr)
16 19 local skip = label()
17 20 local sanitize = function(s) return s:gsub('_','-') end
18 21 for o,desc in pairs(tbl) do
19 - local consume = desc[3] or 0
22 + local consume = desc.consume or 0
23 + local incr = desc.inc or 0
20 24 options.entries[#options.entries + 1] = {
21 - field = o, type = (consume > 0) and &rawstring or bool
25 + field = o, type = (consume > 0) and &rawstring or
26 + (incr > 0) and uint or bool
22 27 }
23 28 helpstr = helpstr .. string.format(' -%s --%s: %s\n',
24 29 desc[1], sanitize(o), desc[2])
25 30 end
26 31 for o,desc in pairs(tbl) do
27 32 local flag = desc[1]
28 - local consume = desc[3] or 0
29 - init[#init + 1] = quote [self].[o] = [(consume > 0 and `nil) or false] end
33 + local consume = desc.consume or 0
34 + local incr = desc.inc or 0
35 + init[#init + 1] = quote [self].[o] = [
36 + (consume > 0 and `nil) or
37 + (incr > 0 and `0 ) or false
38 + ] end
30 39 local ch if consume > 0 then
31 40 ch = quote
32 41 [self].[o] = argv+(idx+1+optstack)
33 42 optstack = optstack + consume
34 43 end
35 44 verifiers[#verifiers+1] = quote
36 45 var terminus = argv + argc
37 46 if [self].[o] ~= nil and [self].[o] >= terminus then
38 47 lib.bail(['missing argument for command line option ' .. sanitize(o)])
39 48 end
40 49 end
50 + elseif incr > 0 then
51 + ch = quote [self].[o] = [self].[o] + incr end
41 52 else ch = quote
42 53 [self].[o] = true
43 54 end end
44 55 shortcases[#shortcases + 1] = quote
45 56 case [int8]([string.byte(flag)]) then [ch] end
46 57 end
47 58 longcases[#longcases + 1] = quote
................................................................................
49 60 end
50 61 end
51 62 terra options:free() self.arglist:free() end
52 63 options.methods.parse = terra([self], [argc], [argv])
53 64 [init]
54 65 var parseopts = true
55 66 var [optstack] = 0
67 + var [subcmd] = [ opts.subcmd or 0 ]
56 68 self.arglist = lib.mem.heapa(rawstring, argc)
57 69 var finalargc = 0
58 70 for [idx]=1,argc do
59 71 var [arg] = argv[idx]
60 72 if optstack > 0 then optstack = optstack - 1 goto [skip] end
61 73 if arg[0] == @'-' and parseopts then
62 74 if arg[1] == @'-' then -- long option
................................................................................
68 80 switch arg[j] do [shortcases] end
69 81 j = j + 1
70 82 end
71 83 end
72 84 else
73 85 self.arglist.ptr[finalargc] = arg
74 86 finalargc = finalargc + 1
87 + if subcmd > 0 then
88 + subcmd = subcmd - 1
89 + if subcmd == 0 then parseopts = false end
90 + end
75 91 end
76 92 ::[skip]::
77 93 end
78 94 [verifiers]
79 95 if finalargc == 0 then self.arglist:free()
80 96 else self.arglist:resize(finalargc) end
81 97 end
82 - options.helptxt = helpstr
98 + options.helptxt = { opts = helpstr, flags = flagstr }
83 99 end
84 100 return options
85 101 end