The Option Parsing Library  0.2.0
Data Structures | Enumerations
opt.h File Reference

Documentation for Option Parsing Library (CEL) More...

This graph shows which files directly or indirectly include this file:

Data Structures

struct  opt_t
 represents an element of an option description table. More...

Defines

macros for describing option-arguments; see @c opt_t
#define OPT_ARG_REQ   (&opt_arg_req)
#define OPT_ARG_NO   (&opt_arg_no)
#define OPT_ARG_OPT   (&opt_arg_opt)

Enumerations

enum  {
  OPT_TYPE_NO, OPT_TYPE_BOOL, OPT_TYPE_INT, OPT_TYPE_UINT,
  OPT_TYPE_REAL, OPT_TYPE_STR
}
 defines enum contants for types of argument conversion. More...

Functions

option processing functions:
const char * opt_init (const opt_t *, int *, char **[], const void **, const char *, int)
 prepares to start parsing program arguments.
int opt_parse (void)
 parses program options.
void opt_abort (void)
 aborts parsing options.
const char * opt_errmsg (int)
 returns a diagnostic format string for an error code.
void opt_free (void)
 cleans up any storage used and disables the internal state.

Detailed Description

Documentation for Option Parsing Library (CEL)

Header for Option Parsing Library (CEL)


Define Documentation

#define OPT_ARG_NO   (&opt_arg_no)

no argument taken

#define OPT_ARG_OPT   (&opt_arg_opt)

optional argument

#define OPT_ARG_REQ   (&opt_arg_req)

mandatory argument


Enumeration Type Documentation

anonymous enum

defines enum contants for types of argument conversion.

Enumerator:
OPT_TYPE_NO 

cannot have type

OPT_TYPE_BOOL 

has boolean (int) type

OPT_TYPE_INT 

has integer (long) type

OPT_TYPE_UINT 

has unsigned integer (unsigned long) type

OPT_TYPE_REAL 

has floating-point (double) type

OPT_TYPE_STR 

has string (char *) type


Function Documentation

void opt_abort ( void  )

aborts parsing options.

opt_abort() aborts parsing options immediately handling the remaining arguments as operands. Having invoked opt_abort(), opt_parse() need not be called to access to operands; argc and @ argv are properly adjusted as if opt_parse() has returned -1 except that the remaining options (if any) are treated as operands. If opt_parse() invoked after aborting the parsing, opt_parse() does nothing and returns -1.

Returns:
nothing
const char* opt_errmsg ( int  c)

returns a diagnostic format string for an error code.

Given an error code that is one of '?', '-', '+' and '*', opt_errmsg() returns a string that can be used as a format string for the printf() family. A typical way to handle exceptional cases opt_parse() may return is as follows:

      switch(c) {
          ... cases for valid options ...
          case 0:
              break;
          case '?':
              fprintf(stderr, "%s: unknown option '%s'\n", option.prgname, (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
          case '-':
              fprintf(stderr, "%s: no or invalid argument given for '%s'\n", option.prgname,
                      (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
          case '+':
              fprintf(stderr, "%s: option '%s' takes no argument\n", option.prgname,
                      (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
          case '*':
              fprintf(stderr, "%s: ambiguous option '%s'\n", option.prgname,
                      (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
          default:
              assert(!"not all options covered -- should never reach here");
              break;
      }

where "case 0" is for options that sets a flag variable so in most cases leaves nothing for a user code to do. The following four case labels handle erroneous cases and the default case is there to handle what is never supposed to happen.

As repeating this construct for every program using this library is cumbersome, for convenience opt_errmsg() is provided to handle those four erroneous cases as follows:

      switch(c) {
          ... cases for valid options ...
          case 0:
              break;
          case '?':
          case '-':
          case '+':
          case '*':
              fprintf(stderr, "%s: ", option.prgname);
              fprintf(stderr, opt_errmsg(c), (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
          default:
              assert(!"not all options covered -- should never reach here");
              break;
      }

or more compatly:

      switch(c) {
          ... cases for valid options ...
          case 0:
              break;
          default:
              fprintf(stderr, "%s: ", option.prgname);
              fprintf(stderr, opt_errmsg(c), (const char *)argptr);
              opt_free();
              return EXIT_FAILURE;
      }

The difference of the last two is that the latter turns the assertion in the former (that possibly gets dropped from the delivery code) into a defensive check (that does not). Note that the returned format string contains a newline.

If a user needs flexibility on the format of diagnostics or actions done in those cases, resort to the cumbersome method shown first.

Possible exceptions: none

Unchecked errors: none

Parameters:
[in]cerror code opt_parse() returned
Returns:
format string for diagnostic message
void opt_free ( void  )

cleans up any storage used and disables the internal state.

opt_free() cleans up any storage allocated by opt_init() and used by opt_parse(). It also initializes the internal state, which allows for multiple scans; see opt_init() for some caveat when scanning options multiple times.

Warning:
opt_free(), if invoked, should be invoked after all arguments including operands have been processed. Since opt_init() makes copies of pointers in argv of main(), and opt_free() releases storages for them, any access to them gets invalidated by opt_free().

Possible exceptions: none

Unchecked errors: none

Returns:
nothing
const char* opt_init ( const opt_t o,
int *  pc,
char **  pv[],
const void **  pa,
const char *  name,
int  sep 
)

prepares to start parsing program arguments.

opt_init() prepares to start parsing program arguments. It takes everything necessary to parse arguments and sets the internal state properly that is referred to by opt_parse() later. It also constructs a more readable program name by omitting any path preceeding the pure name. To do this job, it takes a directory separator character through sep and a default program name through name that is used when no name is available through argv. A typical use of opt_init() is given at the commented-out example code in the source file.

On success, opt_init() returns a program name (non-null pointer). On failure, it returns the null pointer; opt_init() may fail only when allocating small-sized storage fails, in which case further execution of the program is very likely to fail due to the same problem.

opt_init() can be called again for multiple scans of options, but only after opt_free() has been invoked. Note that, in such a case, only the internal state and flag variables given with an option description table are initialized. Other objects probably used for processing options in a user code retain their values, thus should be initialized explicitly by a user code. A convenient way to handle that initialization is to introduce a structure grouping all such objects. For example:

      struct option {
          int html;
          const char *input;
          double val;
          ...
      } option;

where, say, html is a flag variable for --html, input is an argument for -i or --input, val is an argument for -n or --number, and so on. By assigning a properly initialized value to the structure, the initialization can be readily done:

      For C90:
          struct option empty = { 0, };
          option = empty;

      For C99:
          option = (struct option){ 0, };

Note that, in this example, the object option should have the static storage duration in order for the html member to be given as an initalizer for an option description table; C99 has no such restriction.

Possible exceptions: none

Unchecked errors: non-null but invalid arguments given

Parameters:
[in]ooption description table
[in]pcpointer to argc
[in]pvpointer to argv
[in]papointer to object to contain argument or erroneous option
[in]namedefault program name
[in]sepdirectory separator (e.g., '/' on UNIX-like systems)
Returns:
program name or null pointer
Return values:
non-nullprogram name
nullfailure
int opt_parse ( void  )

parses program options.

opt_parse() parses program options. In typical cases, the caller of opt_parse() has to behave based on the result of opt_parse() that is one of:

  • '?': unrecognized option; the pointer given to opt_init() through pa points to a string that represents the option
  • '-': valid option, but no option-argument given even if the option requires it, or invalid option-argument given; the pointer given to opt_init() through pa points to a string that represents the option
  • '+': valid option, but an option-argument given even if the option takes none; the pointer given to opt_init() through pa points to a string that represents the option
  • '*': ambiguious option; it is impossible to identify a unique option with the given prefix of a long-named option
  • 0: valid option; a given flag variable is set properly, thus nothing for a user code to do
  • -1: all options have been processed
  • 1: (only when the first long-named option is "-") an operand is given; the pointer given to opt_init() through pa points to the operand

This means that a valid short-named option cannot have the value of '?', '-', '+', '*', -1 or 1; 0 is allowed to say no short-named option given when a flag variable is provided; see opt_t for details. In addition, '=' cannot also be used.

If an option takes an option-argument, the pointer whose address passed to opt_init() through pa is set to point to the argument. A subsequent call to opt_parse() may overwrite it unless the type is OPT_TYPE_STR.

After opt_parse() returns -1, argc and argv (precisely, objects whose addresses are passed to opt_init() through pc and pv) are adjusted for a user code to process remaining operands as if there were no options or option-arguments in program arguments; see the commented-out example code given in the source file. Once opt_parse() starts the parsing, argc and the elements of argv are indeterminate, thus an access to them is not allowed.

opt_parse() changes neither the original contents of argv nor strings pointed to by the elements of argv, thus by granting copies of argc and argv to opt_init() as in the following example, a user code can access to program arguments unchanged if necessary even after options have been parsed by opt_parse().

      int main(int argc, char *argv[])
      {
          const void *arg;
          int argc2 = argc;
          char **argv2 = argv;
          ...
          pname = opt_init(options, &argc2, &argv2, &arg, "program", '/');
          while (opt_parse() != -1) {
              ...
          }

          for (i = 1; i < argc2; i++)
              printf("operands: %s\n", argv2[i]);

          opt_free();

          for (i = 1; i < argc; i++)
              printf("untouched program arguments: %s\n", argv[i]);
          ...
      }
Warning:
opt_init() has to be invoked successfully before calling opt_parse().

Possible exceptions: none

Unchecked errors: argc or argv modified by a user between calls to opt_parse(), modifying an object containing an option-argument or a problematic option

 All Data Structures Files Functions Variables Enumerator Defines