I often end up writing little command line programs that behave differently depending on the options that they are passed. Most of the software libraries that I publish include examples requiring command line options. I had been using the getopt() function to help me with the necessary parsing.
Since getopt() isn't ANSI, it's not included with all ANSI C
compilers. That means that I need to include a copy of
getopt()
with any of my code samples so people with compilers
that don't provide the getopt()
function can still use my code.
Fortunately there is at least one getopt()
implementation
published under version 2 of the
GNU LGPL.
The version even allows upgrading to new versions of the LGPL, so
I had been using that in my projects licensed under version 2.1 of
the LGPL.
When version 3 of the LGPL was released I decided that I wanted
to explicitly license my projects under the newer version. There's
no reason that I couldn't continue to use the version 2
getopt()
library, but there are things that I don't like about
getopt()
that I wanted to change, and the license upgrade
seemed like a good reason to write a library that worked the way I wanted
it to work.
Now that my replacement library works pretty much the way that I want it to work, I am publishing it under version 3 of the GNU LGPL in hopes that they will be of use to other people.
The rest of this page discusses, the optlist library, my
replacement for getopt()
.
Michael Dipperstein
mdipperstein@gmail.com
The optlist library provides the functions GetOptList()
,
FreeOptList()
, and a bonus function FindFileName()
.
The GetOptList()
function is similar to getopt()
.
Its most notable differences are that it returns a linked list to the
command line arguments and their parameters. One call to
GetOptList()
will return all of the command line options and
their arguments.
Other Differences:
GetOptList()
will not modify argc
or
argv
GetOptList()
does not use global variables
GetOptList()
is thread safe and reenterant
GetOptList()
allocates memory which must
be freed one element at a time or by calling FreeOptList()
FindFileName()
is a bonus function that returns a pointer
to the start of a file name in an array of char
containing a
path including the file name.
typedef struct option_t
{
char option;
char *argument;
int argIndex;
struct option_t *next;
} option_t;
option_t *GetOptList(int argc, char *const argv[], char *const options);
void FreeOptList(option_t *list);
GetOptList()
's parameters "argc" and
"argv" are usually the argument count and array as passed to the
main()
function on program invocation. An element of argv that
starts with "-" is an option element. The character following the
"-" is an option character.
The "options" parameter is a string containing legitimate option characters. If such a character is followed by a colon, the option requires an argument. (e.g. "a:bc?" a, b ,c, and, ? are all options. a should be followed by an argument.)
GetOptList()
returns a linked list of type
option_t
. The *next
field of the element at the
end of the list will be set to NULL
. The option field will
contain the option character. If the option accepts an argument, a pointer
to the text that follows in the same argv-element, or the text of the
following argv-element will be stored in the arguement
field.
Otherwise the arguement
field is set to NULL
.
The index of the argv-element containing the argument will be stored in the
argIndex
. If there is no argument, the field will contain
OL_NOINDEX
.
FreeOptList()
accepts one parameter, *list
, a
pointer to the head of the option_t
type list to be freed.
FreeOptList()
will free each element in the list and set the
value of list
to NULL
.
option_t *optList, *thisOpt;
/* get list of command line options and their arguments */
optList = NULL;
optList = GetOptList(argc, argv, "a:bcd:ef?");
/* display results of parsing */
while (optList != NULL)
{
thisOpt = optList;
optList = optList->next;
if ('?' == thisOpt->option)
{
printf("Usage: %s <options>\n\n", FindFileName(argv[0]));
printf("options:\n");
printf(" -a : option excepting argument.\n");
printf(" -b : option without arguments.\n");
printf(" -c : option without arguments.\n");
printf(" -d : option excepting argument.\n");
printf(" -e : option without arguments.\n");
printf(" -f : option without arguments.\n");
printf(" -? : print out command line options.\n\n");
FreeOptList(thisOpt); /* done with this list, free it */
break;
}
printf("found option %c\n", thisOpt->option);
if (thisOpt->argument != NULL)
{
printf("\tfound argument %s", thisOpt->argument);
printf(" at index %d\n", thisOpt->argIndex);
}
else
{
printf("\tno argument for this option\n");
}
free(thisOpt); /* done with this item, free it */
}
All the source code that I have provided is written in strict ANSI C. I would expect it to build correctly on any machine with an ANSI C or ISO C++ compiler. I have tested the code compiled with gcc on Linux and mingw on Windows.
I am releasing my implementation of the OptList() library under the LGPL. The source code repository is available on GitHub. I recommend that you checkout the latest revision of the master branch, unless you're looking for something specific.
Repository Location | https://github.com/michaeldipperstein/optlist |
---|
If you have any further questions or comments, you may contact me by e-mail. My e-mail address is: mdipperstein@gmail.com
HomeLast updated on December 29, 2018