Features


The World Of Command Line Options

Scott Maley


Scott Maley is a member of the technical staff at The Analytic Science Corporation (TASC). He has more than fifteen years experience in areas of software engineering ranging from Space Shuttle flight simulation to Cobol maintenance.

Visual, iconic or graphic interfaces reduce complexity for the user by relegating details to another level. Complexity is neither created or destroyed — it only changes its appearance or location and distribution. Thus, beneath the surface of many visual interfaces the various graphical tools exchange a great deal of information, often by means of command line options, where the programmer, rather than the user, must deal with the complexity.

This article describes a command-line option-handling package that pushes some of the command line complexity down a level, reducing the amount of complexity with which the programmer must deal. This article is not intended to help you decide when to use command line options. If you have decided to use them, it may help you decide how. I have assumed that you know how arguments (which include options) are passed to a C program. Even if that is not completely clear, you must at least understand that a pointer is a way to refer to an object, and not the object itself.

Overview

Options are used in two fundamentally different ways, distinguished by their position (in)dependence. An option may indicate that something is desired for all arguments (position independent), or for all following arguments (position dependent). No option can be both, because we can't distinguish which is intended unless context is expanded to more than one option at once.

The function cmd_opts presented here assumes that it must deal with only position independent options. It associates arguments with each recognized option (basically a sorting process) and leaves all unrecognized options, including position dependent options, undisturbed.

Thus, the cmd_opts function handles position independent options, and the programmer continues to handle position dependent options.

cmd_opts accepts the same number of arguments as getopt (provided with UNIX System V). The first and second arguments are identical to those passed to getopt. The third encapsulates expanded information in a nil terminated array of options structures, each option isolated in a separate structure.

cmd_opts works backwards through the command line, grouping arguments for options as it goes. By working backwards, the pointer to each option's array of arguments ends up right where we want it, pointing to the first associated argument; cmd_opts leaves any options it doesn't understand where it found them (relatively speaking) and returns an error count to warn us. See Listing 3.

The Options Structure

Listing 1 presents the elements of the structure options. The first element, options.s, is the character that will be used on the command line for this option (e.g. s in -s). Options.arg_flg indicates the minimum number of this option we expect on the command line. The third element, poptv, controls how arguments are associated with options. If poptv is set to NULL, no arguments can be associated with the option. Otherwise cmd_opts will point poptv to the first such argument.

Note that the ADDRESS (&) of the array of pointers (e.g. barg) must be placed in options.poptv, so that it may be set to point to the first of any arguments for the option. The arg_flg for each option is used to return the number of valid instances of the option that were encountered. It may also be directly used as a flag, since a nonzero value is considered TRUE in C.

The second (arg_flg) and third (poptv) elements of the options structure interact to determine how an option is handled by cmd_opts. Listing 2 presents examples of how they interact, where:

You can gain a better understanding of the interactions by experimenting with various combinations (compile and link tcmdopts.c with cmd_opts. c — both include cmd_opts.h).

Conclusions

cmd_opts is much easier to use than the widely used getopt package provided with UNIX System V (source code freely available). While getopt accepts a list of option switch characters and has a means of specifying which require arguments, it has a number of shortcomings. After all the work it does to isolate option switches and associated arguments, getopt requires you to perform similar work. Once getopt returns with a switch character you must determine which it was, then associate any arguments. Worse, getopt passes some of the information via globals (e.g. optarg).

cmd_opts handles the burden of associating arguments with options for those which are position independent. Yet, it leaves any unrecognized options where they were, so that we may handle position dependent options. Thus, we may typically dispense (at least for position independent options) with the switch statement that is often used to associate arguments with options when using the getopt function. No globals are used by cmd_opts, so possible side-effects have been minimized, and the package is more usable in shared code libraries. Finally, encapsulating the information associated with each option in a structure makes cmd_opts easier to understand and use than getopt.