POSIX command line argument processing

Q&A's, tips, howto's
Locked
TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

POSIX command line argument processing

Post by TedWalther »

I have made a module called "getopts". It doesn't use its own context. I don't think it needs to. If people can try it out, it does the following:

It parses command line options in the following forms:

Code: Select all

-f filename
-ffilename (-f filename)
-avh (-a -v -h)
-avfboo (-a -v -f boo)
--long-option
--long-option with-argument
--long-option=with-argument (--long-option "with-argument")
-- (everything after -- is ignored)
Anything that is not an option, or an argument to an option, is just accumulated to a list. At the end of the option processing, this accumulated list is returned for your own custom processing.

There is just one possible glitch. I start the argument parsing at index position 2 of main-args. For my scripts, this works well.

As a bonus, the way it is set up, the "usage" function, automatically lists all the options that you have specified. Also, unlike in C, you don't call getopt repeatedly. The getopts function does it all in one pass. Here is an example of how to use it:

Code: Select all

(module "getopts.lsp")

(short-opt "v" (++ verbosity) nil "Increase verbosity")
(short-opt "q" (setq verbosity 0) nil "Quiet")
(short-opt "?" (usage) nil "Print this usage message")
(short-opt "h" (usage) nil "Print this usage message")
(short-opt "o" (setq output-file arg) "file" "Output file")
(long-opt "help" (usage) nil "Print this usage message")
(long-opt "quiet" (setq verbosity 0) nil "Quiet")
(long-opt "verbose" (++ verbosity) nil)
(long-opt "output" (setq output-file arg) "file" "Output file")

(println (getopts)) ; this shows the command line datum that weren't options
(println "Verbosity: " verbosity)
(println "Output To: " output-file)
(exit)
Example usage:

Code: Select all

$ ./test.lsp --output foo -obar -v --quiet -vv arg1 arg2
("arg1" "arg2")
Verbosity: 2
Output To: bar
There is just one issue. If I pass an argument to newlisp, it changes the starting point for processing in main-args. I see no way to detect this.

Code: Select all

#!/usr/bin/newlisp

$ ./test.lsp foo bar
main-args: "/usr/bin/newlisp" "./test.lsp" "foo" "bar"

#!/usr/bin/newlisp -m 50 -s 1024

$ ./test.lsp foo bar
main-args: "/usr/bin/newlisp" "-m 50 -s 1024" "./test.lsp" "foo" "bar"
See how it differs? Wouldn't it be better if there was an empty string there always, in index position 1, if there are no arguments passed to the newlisp interpreter?
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: POSIX command line argument processing

Post by Lutz »

Different UNIX behave differently on how they treat arguments in the #! line of a script file:

With this "args" program:

Code: Select all

#!/usr/bin/newlisp -m 50 -s 1024

(println (main-args))

(exit)
you get different output on different platforms:

on Mac OSX:

Code: Select all

~> ./args foo bar
("/usr/bin/newlisp" "-m" "50" "-s" "1024" "./args" "foo" "bar")
on FreeBSD, OpenBSD and Linux:

Code: Select all

~> ./args foo bar
("/usr/bin/newlisp" "-m 50 -s 1024" "./args" "foo" "bar")
Only Mac OSX does it "correctly". newLISP just passes on whatever the argv[] array is offered by the standard libraries and C startup code, assuming that this is the excpected behavior on that platform.

But I don't think it really matters, because starting with the script name "./args" the structure of the list is the same.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: POSIX command line argument processing

Post by TedWalther »

Thank you for that feedback. I am modifying the getopts function so now you have to pass in the list of arguments. That will allow it to work across all platforms.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: POSIX command line argument processing

Post by TedWalther »

I have updated the getopts module, and anyone can now download and test it here:

http://dpkg.reactor-core.org/modules/

I hope that everyone finds it useful. Especially if you want to distribute a newlisp script as a commandline utility, this module makes it easy to support the GNU coding standards, and pass information into your script through the command line.

Please look at it, test it, and comment. I included sample code so you can cut and paste to get started.

Ted
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

Locked