return function(tbl)
	local options = terralib.types.newstruct('options') do
		local flags = '' for _,d in pairs(tbl) do flags = flags .. d[1] end
		local helpstr = 'usage: parsav [-' .. flags .. '] [<arg>...]\n'
		options.entries = {
			{field = 'arglist', type = lib.mem.ptr(rawstring)}
		}
		local shortcases, longcases, init = {}, {}, {}
		local self = symbol(&options)
		local arg = symbol(rawstring)
		local skip = label()
		for o,desc in pairs(tbl) do
			options.entries[#options.entries + 1] = {
				field = o, type = bool
			}
			helpstr = helpstr .. string.format('    -%s --%s: %s\n',
				desc[1], o, desc[2])
		end
		for o,desc in pairs(tbl) do
			local flag = desc[1]
			init[#init + 1] = quote [self].[o] = false end
			shortcases[#shortcases + 1] = quote
				case [int8]([string.byte(flag)]) then [self].[o] = true end
			end
			longcases[#longcases + 1] = quote
				if lib.str.cmp([arg]+2, o) == 0 then
					[self].[o] = true
					goto [skip]
				end
			end
		end
		options.methods.parse = terra([self], argc: int, argv: &rawstring)
			[init]
			var parseopts = true
			self.arglist = lib.mem.heapa(rawstring, argc)
			var finalargc = 0
			for i=0,argc do
				var [arg] = argv[i]
				if arg[0] == ('-')[0] and parseopts then
					if arg[1] == ('-')[0] then -- long option
						if arg[2] == 0 then -- last option
							parseopts = false
						else [longcases] end
					else -- short options
						var j = 1
						while arg[j] ~= 0 do
							switch arg[j] do [shortcases] end
							j = j + 1
						end
					end
				else
					self.arglist.ptr[finalargc] = arg
					finalargc = finalargc + 1
				end
				::[skip]::
			end
			if finalargc == 0 then self.arglist:free()
							  else self.arglist:resize(finalargc) end
		end
		options.helptxt = helpstr
	end
	return options
end
