[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: WANTED: POSIX compatible getopt
- From: Tony Finch <dot@...>
- Date: Tue, 13 Jan 2009 00:06:03 +0000
My getopt is below. I call it "Unix-style" because it can be used to
implement programs that conform to the POSIX utility syntax guidelines,
and because it doesn't support GNUish long options. (I'm a BSD hacker.)
In the traditional C API, main() usually contains something like:
while((opt = getopt(argc, argv, "a:...V")) != -1)
switch(opt) {
case('a'):
/* ... */
continue;
/* ... */
case('V'):
printf("myprog version 0.0\n");
exit(0);
default:
usage();
}
argc -= optind;
argv += optind;
Lua lacks a switch statement but it has closures, so my getopt has rather
different usage in order to be more Lunar. The loop over the options is
inside getopt, and instead of a switch you pass in a dispatch table whose
keys are option letters and whose values are option handler functions.
Options that take arguments have a _ appended to their keys. The first
argument to getopt is the array of command-line arguments, and its return
value is the rest of the arguments left after option processing. There's a
special "usage" element in the dispatch table for handling errors, in
which case getopt returns usage's return values. You can break the loop
early by throwing an exception, but then you won't conform to the
standard. For example,
rest = getopt(arg, {
a_ = function (param)
-- ...
end,
-- ...
V = version,
usage = usage
})
I hope that is clear :-)
Tony.
--
f.anthony.n.finch <dot@dotat.at> http://dotat.at/
FAIR ISLE: SOUTHWEST VEERING NORTHWEST 7 TO SEVERE GALE 9, PERHAPS STORM 10
LATER. VERY ROUGH OR HIGH. SQUALLY SHOWERS. MODERATE OR GOOD.
--
-- Unix-style getopt
--
-- Written by Tony Finch <dot@dotat.at> <fanf2@cam.ac.uk>
-- at the University of Cambridge Computing Service.
-- You may do anything with this, at your own risk.
--
-- $Cambridge: users/fanf2/pstx/getopt.lua,v 1.5 2008/05/19 19:21:19 fanf2 Exp $
--
local string = require "string"
local table = require "table"
local match = string.match
local sub = string.sub
local remove = table.remove
local setMT = setmetatable
module "getopt"
function getopt(argv, handler)
repeat
local arg = argv[1]
-- ran out of arguments
if arg == nil then
return argv
end
-- explicit end of options
if arg == "--" then
remove(argv,1)
return argv
end
local opt = match(arg, "^%-(%w)")
-- remaining arguments are not options
if not opt then
return argv
end
-- option with parameter
local fun = handler[opt.."_"]
if fun then
remove(argv,1)
-- parameter immediately follows option,
-- or is the following argument
local param = sub(arg,3)
if #param == 0 then
param = argv[1]
remove(argv,1)
end
fun(param, opt)
else
if #arg == 2 then
-- bare option
remove(argv,1)
else
-- keep rest of clustered options
argv[1] = "-"..sub(arg,3)
end
fun = handler[opt]
if fun then
fun(true, opt)
else
return handler.usage()
end
end
until false
end
-- allow the user to call getopt() as well as getopt.getopt()
local function MTgetopt(module, argv, handler)
return getopt(argv, handler)
end
setMT(_M, { __call = MTgetopt })
-- eof
- References:
- WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Javier Guerra
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Rob Kendrick
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Rob Kendrick
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Rob Kendrick
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Rob Kendrick
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Rob Kendrick
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Doug Currie
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov
- Re: WANTED: POSIX compatible getopt, Aleksey Cheusov