Long options handling

Name

X_getopt() – processes long options.

Synopsis

#include <basis/options.h>

struct x_option {
int  optval;
char flag;
char *name;
char *has_argument;
char *description;
};

int x_getopt(int argc, char **argv, int optcount, struct x_option *opts);
extern char *x_optarg;
extern int x_optind, x_opterr, x_optopt;

Description

The x_getopt() function returns the next option in argv that matches an option in opts. The opts argument is an array of option definitions containing the following fields:

=optval= is the value that x_getopt() returns to the program. =flag= is the one-character option. =name= is the long options name. =has_arguments= if the option has an argument associated with it, this is set to some descriptive word describing the contents of that argument (like “FILE” if the option wants a file argument.) =description= A one line description of the argument.

The x_getopt() function places the argv index of the next argument to be processed into the x_optind variable. x_optind is external and is initialized to 1 every time you call x_getopt() with a different argc/argv pair. When all options have been processed, x_getopt() returns EOF. The special option “--” is used to tell x_getopt() that no further options are to be found in argv. This is useful for delimiting non-option arguments that begin with a “-”.

When x_getopt() encounters an option not listed in opts, it returns NULL. In addition, if the x_opterr variable is nonzero, it also prints an error message to stderr.

Example

#include <stdio.h>
#include <basis/options.h>

struct x_option options[] = {
{ 'a', 'a', "opta",        0, "Option A" },
{ 'b', 'b', "optb",        0, "Option B" },
{ 'o', 'o', "output", "FILE", "Write output to FILE" },
{ 'h', 0  , "help",        0, "Print this help message" },
};
#define NROPTS (sizeof options/sizeof options[0])


main(int argc, char **argv)
{
int c;
int aflag = 0,
    bflag = 0;
char *output = "-";


while ( (c = x_getopt(argc, argv, NROPTS, options)) != EOF) {
    switch (c) {
    case 'a':
    aflag++;
    break;
    case 'b':
    bflag++;
    break;
    case 'f':
    output = x_optarg;
    break;
    case 0:
    case 'h':
    fprintf(stderr, "usage: program [-ab] [-o file] ...\n");
    exit(  (c == 'h') ? 0 : 1 );
    }
}
for ( ; x_optind < argc; x_optind++)
    printf("%d: %s\n", x_optind, argv[x_optind]);
}

Source code

I put the header file in /usr/include/basis, to avoid collisions with the seventy or so other options.h files out there. I usually just build options.c as part of the objects list of the programs I build it with, but I’ve also built it into the libraries liboptions.a and libc.a