parsav  Diff

Differences From Artifact [50677a3c0c]:

To Artifact [bfedd61eec]:


     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