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