Long options handling


X_getopt() – processes long options.


#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;


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:

is the value that x_getopt() returns to the program.
is the one-character option.
is the long options name.
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.)
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.


#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':
        case 'b':
        case 'f':
            output = x_optarg;
        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