(require 'getopt)
This routine implements Posix command line argument parsing. Notice
that returning values through global variables means that getopt
is not reentrant.
Obedience to Posix format for the getopt calls sows confusion.
Passing argc and argv as arguments while referencing
optind as a global variable leads to strange behavior,
especially when the calls to getopt are buried in other
procedures.
Even in C, argc can be derived from argv; what purpose
does it serve beyond providing an opportunity for
argv/argc mismatch? Just such a mismatch existed for
years in a SLIB getopt-- example.
I have removed the argc and argv arguments to getopt procedures; and replaced them with a global variable:
Define *argv* with a list of arguments before calling getopt procedures. If you don't want the first (0th) element to be ignored, set *optind* to 0 (after requiring getopt).
Is the index of the current element of the command line. It is initially one. In order to parse a new command line or reparse an old one, *optind* must be reset.
Returns the next option letter in *argv* (starting from
(vector-ref argv *optind*)) that matches a letter in optstring. *argv* is a vector or list of strings, the 0th of which getopt usually ignores. optstring is a string of recognized option characters; if a character is followed by a colon, the option takes an argument which may be immediately following it in the string or in the next element of *argv*.*optind* is the index of the next element of the *argv* vector to be processed. It is initialized to 1 by getopt.scm, and
getoptupdates it when it finishes with each element of *argv*.
getoptreturns the next option character from *argv* that matches a character in optstring, if there is one that matches. If the option takes an argument,getoptsets the variable *optarg* to the option-argument as follows:
- If the option was the last character in the string pointed to by an element of *argv*, then *optarg* contains the next element of *argv*, and *optind* is incremented by 2. If the resulting value of *optind* is greater than or equal to
(length*argv*), this indicates a missing option argument, andgetoptreturns an error indication.- Otherwise, *optarg* is set to the string following the option character in that element of *argv*, and *optind* is incremented by 1.
If, when
getoptis called, the string(vector-ref argv *optind*)either does not begin with the character#\-or is just"-",getoptreturns#fwithout changing *optind*. If(vector-ref argv *optind*)is the string"--",getoptreturns#fafter incrementing *optind*.If
getoptencounters an option character that is not contained in optstring, it returns the question-mark#\?character. If it detects a missing option argument, it returns the colon character#\:if the first character of optstring was a colon, or a question-mark character otherwise. In either case,getoptsets the variable getopt:opt to the option character that caused the error.The special option
"--"can be used to delimit the end of the options;#fis returned, and"--"is skipped.RETURN VALUE
getoptreturns the next option character specified on the command line. A colon#\:is returned ifgetoptdetects a missing argument and the first character of optstring was a colon#\:.A question-mark
#\?is returned ifgetoptencounters an option character not in optstring or detects a missing argument and the first character of optstring was not a colon#\:.Otherwise,
getoptreturns#fwhen all command line options have been parsed.Example:
#! /usr/local/bin/scm (require 'program-arguments) (require 'getopt) (define argv (program-arguments)) (define opts ":a:b:cd") (let loop ((opt (getopt (length argv) argv opts))) (case opt ((#\a) (print "option a: " *optarg*)) ((#\b) (print "option b: " *optarg*)) ((#\c) (print "option c")) ((#\d) (print "option d")) ((#\?) (print "error" getopt:opt)) ((#\:) (print "missing arg" getopt:opt)) ((#f) (if (< *optind* (length argv)) (print "argv[" *optind* "]=" (list-ref argv *optind*))) (set! *optind* (+ *optind* 1)))) (if (< *optind* (length argv)) (loop (getopt (length argv) argv opts)))) (slib:exit)
getopt-- optstringThe procedure
getopt--is an extended version ofgetoptwhich parses long option names of the form ‘--hold-the-onions’ and ‘--verbosity-level=extreme’.Getopt--behaves asgetoptexcept for non-empty options beginning with ‘--’.Options beginning with ‘--’ are returned as strings rather than characters. If a value is assigned (using ‘=’) to a long option,
*optarg*is set to the value. The ‘=’ and value are not returned as part of the option string.No information is passed to
getopt--concerning which long options should be accepted or whether such options can take arguments. If a long option did not have an argument,*optarg*will be set to#f. The caller is responsible for detecting and reporting errors.(define opts ":-:b:") (define *argv* '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--")) (define *optind* 1) (define *optarg* #f) (require 'qp) (do ((i 5 (+ -1 i))) ((zero? i)) (let ((opt (getopt-- opts))) (print *optind* opt *optarg*))) -| 2 #\b "9" 3 "f1" #f 4 "2" "" 5 "g3" "35234.342" 5 #f "35234.342"