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