parsav  Diff

Differences From Artifact [bad20dd1d0]:

To Artifact [50677a3c0c]:


     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