   This document describes `opt', v3.7, a subroutine library for
communicating options and parameter values to a C program via the
command line, parameter files, environment variables, or a rudimentary
builtin interactive menu.

   Copyright (C) 1996,1997 James Theiler

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "Copying" is included exactly as in the
original, and provided that the entire resulting derived work is
distributed under the terms of a permission notice identical to this
one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the author.

   This document describes `opt', v3.7, a subroutine library for
communicating options and parameter values to a C program via the
command line, parameter files, environment variables, or a rudimentary
builtin interactive menu.

Nutshell
********

   `opt' is a subroutine library which facilitates the convenient input
of parameters to a C program.  Parameters are parsed from a command
line, with further facilities for reading options from files, from
environment strings, or from an interactive environment.

   The aim of the `opt' package is to permit programs to be both user-
and programmer- friendly.  The package attempts to provide a direct and
relatively full-featured input interface to the ultimate user of the
program, and at the same time to impose a minimal amount of work on the
programmer to "add" options parsing to existing software.

   `opt' is similar in its effects to the standard UNIX (and also to
the GNU) `getopts' packages, and I have tried (though possibly not as
hard as I could have) to keep them as similar as possible whenever
feasable.  But `opt' does takes a somewhat different philosophy.
Variables are "registered" to strings, and whenever the strings are
used on the command line, the variables are updated accordingly.  This
tends to be a little more compact (and in my view more convenient) than
the loop and case-statement approach used by `getopt'.  Also, `opt' has
a few more bells and whistles.

What the user sees
==================

   Code written with `opt' can read parameters from the command line;
for example running the program
     birthday -m 9 -d 11 -y1989 -v

can set paramters MONTH=9, DAY=11, and YEAR=1989, and also turn on the
VERBOSE flag, inside the `birthday' program.  Note that the space
between the single-character option name and the value is optional.
Some parameters can also be set using long names, for instance:
     birthday --month=9 --day 11 -y1989

Note that the `=' can only be used with the long form of the options,
but it is optional and white space can also be used to separate the
option name from its value.  Note also that the long name `--month' and
the variable name MONTH only happen to be the same in this example;
they aren't in general.  Alternatively, you can use
     birthday @file.opt

to read the paramters from the file `file.opt'.  There is also an
interactive menu.  If you type
     birthday --menu

at the command line, then you'll see this on the screen:
     birthday
     m Month                                    4
     d Day of month                             24
     y Year                                     1993
     v Verbose                                  FALSE
     p Use Pade Approximants                    FALSE
     g Gregorian                                FALSE
     (Type ? for Help)
     ->

By invoking the menu, the user is able to see what all the available
options are, even the obscure ones.  The prompt `->' is waiting for
your response; type `m 9' and return to set the value of MONTH to 9.
Set any other parameters as you see fit.  Enter a blank line, and the
you'll again see a list of parameters and values.  Then type `=' and
the program will run with those parameters, and then return to the
prompt.  You can change the parameters and run again if you like.  Type
`.' to exit.

   Finally, the program is somewhat self-documenting.  Type
     birthday --help

at the command line, and then you'll see a message like this:
     Usage: birthday [options]
     To invoke the menu, type:
             birthday --menu
     The options are:
      -m, --month        <integer>       Month
      -d, --day          <integer>       Day of month
      -y                 <integer>       Year
      -v                 <flag>          Verbose
      -p                 <flag>          Use Pade Approximants
      -g                 <flag>          Gregorian

and then the program exits.  There are several other features provided
by `opt' that will be discussed in later sections.

What the programmer sees
========================

   The above example is based on actual output from the following code.
This is not the simplest possible, but it illustrates what I personally
find to be the most commonly used features.  More sophisticated options
processing is also available, and will be discussed in later sections.
     /* birthday.c */

     #include <stdio.h>
     #include <opt.h>                /* part of opt package */

     /* Parameters that user has access to via opt package;
      * They are typically (but not necessarily) global variables.
      * Their default values are provided in the assignement statements.
      */
     int month=9;
     int day=11;
     int year=1989;
     int verb=0;
     int pade=0;
     int greg=0;

     /* All of what the program itself does is in the birthday() function;
      * This function does what a non-options parsing main() might do.
      */
     int birthday(int argc, char **argv)
     {
         if (month == 9 && day == 11 && year == 1989)
             printf("Happy birthday, Max\n");
         else if (month == 4 && day == 24 && year == 1993)
             printf("Happy birthday, Sky\n");

         if (verb)
             printf("Hello, world: %4d/%02d/%02d\n",year,month,day);

         return OPT_OK;
     }

     /* all of the options parsing is in the new main() function */

     int main(int argc, char **argv)
     {
         /* optrega() registers short name '-m' and long name '--month' to
          * variable 'month', and provides brief description "Month"
          */
         optrega(&month,OPT_INT,'m',"month","Month");
         optrega(&day,  OPT_INT,'d',"day",  "Day of month");
         /* optreg() only provides short name '-y' */
         optreg(&year,OPT_INT,'y',"Year");
         /* register some flag variables... */
         optreg(&verb,OPT_FLAG,'v',"Verbose");
         optreg(&pade,OPT_FLAG,'p',"Use Pade Approximants");
         optreg(&greg,OPT_FLAG,'g',"Gregorian");

         /* the function birthday() is registered with opt */
         optMain(birthday);

         /* opt() is the routine that actually parses the argc/argv
          * variables
          */
         opt(&argc,&argv);
         /* and when it's done, argc/argv will contain the leftover
          * argc/argv variables, including the same argv[0] as in
          * the original argc/argv
          */

         /* Now that variables are parsed, run birthday() */
         return birthday(argc,argv);
     }

   The opt package consists of the header file `opt.h', which must be
`#include''d in any code that uses opt, and the library file
`libopt.a', which is linked to the program at compile time
             cc -Idir_with_opt_h -Ldir_with_libopt_a birthday.c -lopt

Opt
***

Philosophical digression
========================

   Programs that provide a convenient user interface, especially those
with gooey user interfaces (GUI's), generally require a fair bit of
programming to produce.  But for short programs that will not be used a
lot, "programmer friendly" is more important than "user friendly."  If
a program grows in size or usefulness, the programmer can then go back
and put in a better interface.  But in doing so, the programmer trades
away the "programmer friendliness" of the original code to end up with
software that exhibits "user friendliness".

   Suppose you want to write a program that depends on some parameters.
As a programmer, it is convenient to set the parameters (in the
vernacular, to "hardcode" them) to desired values right in the program.
It is not really very convenient, though, because you have to recompile
the program every time you want to run it with different values.  This
is especially inconvenient when the user and the programmer are
different people.

   It is usually more convenient (for the user) if the parameters can be
specified at run time.  There is, of course, more than one way to do
this.  You can specify parameter values in an input file, for instance.
Then the program has to open the file, read the values, assign them to
the appropriate variables, and then compute accordingly.  It's a little
inconvenient for the programmer, and a little inconvenient for the
user, but if there are a large number of parameters, this is often the
best approach.  Even for a small number of parameters, it is useful to
at least have the option of saving parameter values in a file.

   Another approach is to have the program "ask" the user what parameter
values are desired.  After typing `birthday' for instance, the program
might respond with
     What is the number of the month?_

to which the user would reply, say, "9".  Then
     Enter the day of the month and the year?_

to which the user would type "11 1989" or perhaps "11,1989" depending
on the format that the program expected for input.  This style of
program sometimes seems friendly at first, since the user doesn't have
to know a lot about the program to run it, but just has to answer the
questions.  It can get to be pretty awkward after awhile, though,
particularly if there are a lot of options, and especially if the
program is to be used in shell scripts.  It is not too hard to write
the program to do this (it is basically a series alternating `printf''s
and `scanf''s), but for a lot of parameters, it can get pretty tedious.

   One of the most popular approaches is to specify the options and
parameter values directly from the command line.  The user types
     birthday -m 9 -d 11 -y 1989

and this specifies in one compact line values for month, day, and year.
This is a bit of a compromise; the user has to know what all the options
are, and the programmer has to do a little string parsing.  The
motivation for the `opt' package is to bridge this gap: to on the one
hand simplify the programmer's task of converting command line strings
into parameter assignments, and on the other hand to provide the user a
little more information about the available options and a little more
convenience in setting those options and parameter values.

What is Opt?
============

   I know I've said this already, but...  `opt' is a subroutine library
for communicating options and parameter values to a C program via the
command line, parameter files, environment variables, or a rudimentary
builtin interactive menu.

   The aim of the `opt' package is to permit programs to be both user-
and programmer- friendly.  The package attempts to provide a direct and
relatively full-featured input interface to the ultimate user of the
program, and at the same time to impose a minimal amount of work on the
programmer to "add" options parsing to existing software.

   The next sections basically parallel the `Nutshell' chapter, but add
a little more detail.  First, the `opt' interface will be described, as
it appears to the user.  This comprises the advertisement for
incorporating `opt' into your code.  Then it will be shown how to write
code that uses `opt' for its user interface.

User Interface
==============

   Currently, `opt' supports the following modes of interface to the
user:

   * Direct command line options

   * Options from a named file

   * Environment strings

   * Rudimentary builtin menu

   * Standard usage messages

Direct command line options
---------------------------

   Options are typically invoked with a delimiter (either `-' or `--')
followed by an alphabetic character or string, and both of those by the
value of the parameter.  Thus `birthday -m5' means that the parameter
associated with `m' takes the value 5.  The same effect is acheived by
`birthday -m 5' (with a space between `m' and `5').  The power of this
assignment is that options for several parameters can be assigned in a
flexible way:
     birthday -m9 -d11 -y1989  ;Sets values of month, day, and year
     birthday -d11 -y1989 -m9  ;Doesn't matter what order
     birthday -m9              ;Set month=5, day and year to their defaults
     birthday -m 9             ;Space is permitted between m and 9
     birthday - m9             ;Not valid to have space beweeen - and m
     birthday -m9-d11          ;Not valid; need space between each
                               ;delimited option

   Some kinds of options are of a different form.  Among these are
"flags" which signal whether a given option is on off.  Thus, one might
signal that a program is to operate in verbose mode with a command line
of the form `birthday -m9 -v'.  Alternatively, one can write `birthday
-m9 -v+' to explicitly turn the verbose option on, or `birthday -m9
-v-' to explicitly turn verbose off.  Unlike options which assign
values, flag parameters can be assigned with a single delimiter.  Thus,
one might have a verbose (`v') flag, a gregorian (`g') flag, and a "use
Pade approximant" (`p') flag.  In this case, one can write commands of
the following forms:
     birthday -v -g -p  ;Invoke all flags
     birthday -vgp      ;Invoke all flags, in a more compact notation
     birthday -pv+g-    ;Invoke p-flag, while explicitly
                        ;turning v-flag on, g-flag off.
   Invoking a flag is not always the same as setting the flag to ON.
Depending on how the flags are defined in the program, invoking a flag
may set its value to ON, to OFF, or toggle it to the opposite of its
value before invocation.  For instance, if the `p'-flag is a toggle,
the command `birthday -p -m9 -p' toggles it twice, so that the effect of
the two invocations are to cancel each other out.  The motivation for
toggles and other kinds of flags will become apparent when the command
line is extended to files and environment variables and interactive
menus.

Options from a named file
-------------------------

   It is clear that a program with many options begins to get unwieldy
on the command line, and it is desirable to save options in a file, and
not have to retype them every time the program is run.  The `opt'
package permits this with command lines of the form `birthday
@bday.opt'.  Here `bday.opt' is a file which contains options which are
used by the program `birthday'.  The form of the options file
`bday.opt' is like that of the command line itself.  Thus, if the file
is composed of the string `-m9 -d11 -y1989 -vg' then it is as if that
string replaced `@bday.opt' on the command line.

   A file permits some luxuries that are not available on the command
line directly.  One of these is that you are not limited to a single
line, and another is that you can add comments in the file.  Thus if
the file looks like this:
     ;file: bday.opt
     ;Comments are preceded by a semi-colon
     -m9             ;September
     -g              ;Use gregorian
     -d11 -y1989     ;Can still have several options on one line

Then `birthday @bday.opt" is exactly equivalent to "birthday -m9 -g
-d11 -y1989'.

   It is possible to mix direct command line options with file options.
Thus `birthday -v @bday.opt -p' is equivalent to `birthday -v -m9 -g
-d11 -y1989 -p'.  This is particularly useful if you want to make many
runs in which only a few parameters are changed at a time.  For
instance,
     birthday @defaults.opt
     birthday @defaults.opt -m10
     birthday @defaults.opt -v

might represent three runs of the program "birthday", the first with a
default set of options, the second with the same options except m=10,
and the third the same as the first, except that verbose is turned ON.

   It is also possible to nest files, so that one might have two files:
     ;file: bd1.opt
     -m5             ;set some option values
     -y 1997
     @bd2.opt        ;get more options from file bd2.opt

and
     ;file: bd2.opt
     -d 11           ;set day=11
     -y 1989         ;set year=1989

and then the command line `birthday @bd1.opt' conceptually expands to be
the equivalent `birthday -m5 -y 1997 -d 11 -y1989'.  This is a
completely valid command line, even though the 'y' option appears
twice; it is the last value of a variable which the program uses, in
this case y=1989.

   Of course, recursive nesting will only get you into trouble.

   There is a useful abbreviation for files: @@ stands for the default
options filename which is always the program name with the extension
".opt".  Thus `birthday @@' is equivalent to `birthday @birthday.opt'

   You can also write to an `opt' file; the directive `%file.opt'
writes the current options to the file `file.opt'.  Here, `%%', invoked
for a program called `birthday', is an abbreviation for `%birthday.opt'.

Environment strings
-------------------

   The program which uses the `opt' package can be instructed to look
for an environment variable for options.  If birthday sets `BIRTHDAY'
as its option environment variable, and if the environment string
`BIRTHDAY=-m9 -y1989' is set, then running `birthday' is equivalent to
running `birthday -m9 -y1989'.  The environment options are assigned
before any command line options, so they can be over-ridden: thus the
command `birthday -m10' resets m to be equal to 10 instead of m=9
suggested by the environment string, but one still has y=1989.  The
environment string is therefore a useful place for storing default
options that you don't want to have to keep typing them each time you
run the program.  In the UNIX C-shell you can set an environment string
with the `setenv' command:
     setenv BIRTHDAY "-m9 -y1989"
   while in the Bourne shell, you'd write
     BIRTHDAY="-m9 -y1989"
     export BIRTHDAY
   Note that UNIX environment strings are not the same thing as shell
variables In MS-DOS, one uses the command "set"; the format is
     set BIRTHDAY=-m9 -y1989

with no quotes.  To unset, type "set BIRTHDAY=", and to view just type
"set".  (However, it's been ages since I've used `opt' on MS-DOS; I'd
be surprised if it still worked on that platform.  Of course I'm always
surprised when anything works on that platform.)

Rudimentary builtin menu
------------------------

   Although the above methods provide flexible means of getting
parameter values to a program which is run in background or batch mode,
it is also useful to alter parameters interactively.  The `opt' package
provides a convenient way to do this, with an interactive menu.  To
invoke the menu type `$' (or `--menu') at the end of the command line.
For instance, typing `birthday -m4 -y1993 $' will return a menu that
looks something like
     birthday
     m Month                                    4
     d Day of month                             11
     y Year                                     1993
     v Verbose                                  FALSE
     p Use Pade Approximants                    FALSE
     g Gregorian                                FALSE
     (Type ? for Help)
     ->
   The prompt `->' is an invitation to the user to write a segment of a
command line.  For instance a reply of `-m4 -vg' will come back with a
bare prompt:
     ->

Responding with an empty line will give a new menu that looks like
     m Month                                    4
     d Day of month                             11
     y Year                                     1989
     v Verbose                                  TRUE
     p Use Pade Approximants                    FALSE
     g Gregorian                                TRUE
     (Type ? for Help)
     ->
   When you are ready to run the program with these values, type `='.
Actually, there are a number of things you can type at the command
prompt; type a plain `?' for the following description:
             - Options delimiter
             ? Help
             = Run program and return to menu
             ! Shell to Operating System
             $ Exit menu
             + Additional options
             @<filename> Get options from file
             @@ Get options from file [birthday.opt]
             %<filename> Put options in file
             %% Put options in file [birthday.opt]
             . Quit
     ->

   It is also possible that `?c' will give further information about
the option specified by `c', although this requires that the programmer
supplied extra information (usually, the brief description is all that
is available).  For example,
             -> ?d
             d: Use day of month, should be less than 32
             ->

Standard usage messages
-----------------------

   The user can type
     birthday --help

and get a fairly complete usage message:
     Usage: birthday [options]
     To invoke the menu, type:
             birthday --menu
     The options are:
      -m, --month        <integer>       Month
      -d, --day          <integer>       Day of month
      -y                 <integer>       Year
      -v                 <flag>          Verbose
      -p                 <flag>          Use Pade Approximants
      -g                 <flag>          Gregorian

Programmer Interface
====================

   First an example source code will be shown so that the programmer
gets an idea of what it takes to incorporate `opt' into his or her
favorite application.  Subsequent sections will then go into more
detailed explanation.

Example code
------------

   The easiest way to see how to use the `opt' package is with an
example.  The following program illustrates most of the features that
you'd actually want to use (and several you probably don't care about).

     /* testopt.c */

     #include <stdio.h>
     #include <stdlib.h>
     #include <opt.h>

     int month=4;
     int day=24;
     int year=1993;
     char *who=NULL;

     int go(int argc, char **argv)
     {
         if (argc>1) {
             printf("In program %s, Extra option: %s\n",argv[0],argv[1]);
         }

         if (optinvoked(&month)) {
             printf("User set month...\n");
         }

         if (month == 9 && day == 11 && year == 1989) {
             printf("Happy birthday, Max\n");
         } else {
             printf("Hello, %s: %4d/%02d/%02d\n",(who==NULL ? "world" : who),
                    year,month,day);
         }
         return OPT_OK;
     }

     int checkyear(void *v)
     {
         if (year == 2000) {
             printf("Watch out for that year=2000 bug!\n");
             return OPT_ERROR;
         }
         return OPT_OK;
     }
     int quit()
     {
         printf("Bye...\n");
         return OPT_OK;
     }
     int write_version()
     {
         printf("Version XXX\n");
         optExitNumber(12);
         return OPT_EXIT;
     }
     int fix_mon(void *v)
     {
         int m;
         /* fix whatever int variable v is pointing to */
         m = *((int *)v);
         if (m < 1 || m > 12)
             m=1;
         *((int *)v) = m;
         return OPT_OK;
     }

     main(int argc, char **argv)
     {
         optreg(&month,OPT_INT,'m',"Month");
         optlongname(&month,"month");
         opthook(&month,fix_mon);

         optrega(&day,OPT_INT,'d',"day","Day");
         opthelp(&day,"Use day of month, should be less than 32");

         optreg_INT(&year,'y',"Year");
         optreg(&year,OPT_INT,'Y',"Year");
         optdescript(&year,"What Year");
         opthook(&year,checkyear);

         optreg(&who,OPT_UNDELIM,'\0',"Who to say hello to");

         optexec("version",write_version,"Write version number and exit");

         optEnvVarName( "OPT" );

         optMain(go);
         optQuit(quit);

         opt(&argc,&argv);
         return go(argc,argv);
     }

Registering options
-------------------

   	It is necessary for the programmer to somehow tell the package which
options are associated with which variables in the program, and what
descriptions `opt' should use in the usage message and the menu.  This
is done with a function call that "registers" (or associates(1)) a
variable and a name.  These functions (one for each variable, in
general) are usually called at the beginning of the code.  For example,
         optreg(&day,OPT_INT,'d',"Day");

where DAY is the name of the variable as it appears (for instance as a
global variable) in the C program; OPT_INT tells opt that the variable
is an `int', D is the alphabetic character that is used on the command
line to alter the parameter DAY, and "DAY" is a string that will be
used in the menu and the standard usage messages.

   You can register a long (string) name as well as the short (one
character) name.  The function name has an extra `a' (mnemonic: all) at
the end.
     optrega(&month,OPT_INT,'m',"month","Month");
   With this registration in place, `-m 4' and `--month=4' have the same
effect; to change the value of the variable MONTH to four.  If you want
to register a long name to a variable without also having a short name
(this is sometimes desirable if there are a lot of options), this can
be done with a call to `optrega' that sets the short name to the null
character; e.g.,
     optrega(&month,OPT_INT,'\0',"month","Month");

   The variable `OPT_INT' is of type `opt_TYPE'; this is an enumerated
type and is defined in the header file `opt.h'.  The available option
types are: `OPT_INT', `OPT_SHORT', `OPT_LONG', `OPT_CHAR', `OPT_UINT',
`OPT_USHORT', `OPT_ULONG', `OPT_UCHAR', `OPT_INTLEVEL', `OPT_FLOAT',
`OPT_DOUBLE', `OPT_FLAG', `OPT_NEGFLAG', `OPT_ABSFLAG',
`OPT_ABSNEGFLAG', `OPT_STRING', `OPT_CSTRING', `OPT_UNDELIM', and
`OPT_UNDELIMC'.  There is also a type `OPT_NUL' that is used internally.

   Most of these are self-explanatory:
     OPT_INT     int
     OPT_SHORT   short int
     OPT_LONG    long int
     OPT_UINT    unsigned int
     OPT_USHORT  unsigned short int
     OPT_ULONG   unsigned long int
     OPT_FLOAT   float
     OPT_DOUBLE  double
   All of these are invoked on the command line with the form `-x#' or
with `-x #' where `#' is the value of the number.  Along these same
lines is the type
     OPT_CHAR    char
   which can only be invoked as `-x#' and not `-x #'.  The latter form
will assign the X variable to the character value NULL ('\0'), and `#'
will be treated as the next option.

   There are a variety of flags:
     OPT_FLAG        int     This is a toggle-type flag, whose first
                         invocation makes the flag TRUE (or ON).
     OPT_NEGFLAG     int     When flag is TRUE, variable is FALSE.
     OPT_ABSFLAG     int     No toggle.  Any (nonzero) number of
                         invocations makes this flag TRUE.
                         In my own experience, I have found absolute flags
             are usually preferable to toggle flags (and now I wish I'd made
             absolute flags the default.  The problem with toggles is
             that you can easily lose track of what the current state
             of the toggle is, especially when options can be specified
             in files, environment variables, and the menu, as well as
             the command line itself.
     OPT_ABSNEGFLAG  int     Any invocation makes flag FALSE.
     OPT_INTLEVEL    int     This is a kind of a combination flag and
                         int: it is an integer that can take on
                         only positive values, usually less than
                         ten.  I find this useful for "verbose"
                         since I can not only turn verbose ON,
                         but I can have a range from slightly
                         verbose to extremely verbose.
                         For this flag, each invocation increases
                         the level; eg, "-v -v" sets verbose=2.
                         and -v- turns verbose off.
   There are two types of strings, variable and constant.  Which of
these to use depends on how the variable is declared:
     char *vstring=NULL;     /* variable string */
     char cstring[80];       /* constant string */
     char *cstring="hello";  /* this is a constant string too */

The difference is that CSTRING already has space allocated for it, so
to have CSTRING be "string" one has to use `strcpy(cstring,"string")',
and note that the pointer CSTRING itself does not change.  By contrast,
to use VSTRING, space must be allocated dynamically.  In this case, one
has to change the value of the pointer VSTRING with something like
     vstring = (char *)malloc(strlen("string")+1);
     strcpy(vstring,"string");

     OPT_STRING         char *
     OPT_CSTRING         char *

By the way, if you are using `OPT_CSTRING', you should make sure that
it has room for a string of length `OPT_MAXSTRLEN'.  But in general,
you should prefer `OPT_STRING' of the two.  (Note, `OPT_STRING' used to
be called `OPT_VSTRING' but the latter form is now discouraged.)

   Finally, undelimited strings which do not have an alphabetic
character identifier (e.g., invoked as `program "string"' instead of
`program -s "string"') can be read from the command line and into a
variable using one of these two types:
     OPT_UNDELIM         char *
     OPT_UNDELIMC        char *

`OPT_UNDELIM' and `OPT_UNDELIMC' are the same as `OPT_STRING' and
`OPT_CSTRING', except that they are invoked on a command line without a
delimeter.

   If a variable is registered, then you can change or add to its
attributes; for instance:
     optreg(&var,OPT_INT,'c');
     optlongname(&var,"variance");

   The various registration functions (`optreg()', etc) return an
integer which is the index of the registered option. Sometimes (eg,
instance when there is no variable associated with the registration)
this integer is a more useful identifier of a given option.  The above,
for instance, is equivalent to:
     n = optreg(&var,OPT_INT,'c');
     optlongname_n(n,"variance");

`void optchar(void *v, char c)'
     Associates the single-character name with the variable pointed to
     by V.

`void optchar_n(int n, char)'
     Associates the single-character name with the N'th registered
     variable.

`void optlongname(void *v, char *longname)'
     Associates the long name to the variable pointed to by V.

`void optlongname_n(int n, char *longname)'
     Associates the long name to the N'th registered variable.

`void optdescript(void *v, char *descript)'
     Changes the brief description of the variable pointed to by V.

`void optdescript_n(int n, char *descript)'
     Changes the brief description of the N'th registered variable.

`void opthelp(void *v, char *help)'
     Associates a longer help string with the variable pointed to by V.
     This is the string the user will see upon typing `?c' at the menu
     prompt, where `c' is the single-character name.

`void opthelp_n(int n, char *help)'
     Associates a longer help string with the N'th registered variable.

   ---------- Footnotes ----------

   (1) When I say "register" I mean it as a verb, in the sense of
"register your handgun", and not as a noun, meaning an immediate memory
location on a microprocessor.  I apologize to any old assembler-coders
who may find this language confusing.  I do not apologize to the
NRA-types who oppose global variables and unregulated firearms.

Setting some strings
--------------------

   The following functions set strings which the `opt' package uses for
various things.
`void optUsage(char *s)'
     Sets the usage statement that the program will print as part of
     the help message.

`void optTitle(char *s)'
     Sets the title, which appears as the first line in the menu.  If
     not set, then the program name is used.

`void optEnvVarName(char *s)'
     Sets the name of the environment variable where the `opt' package
     will look for initial command line options.  If not set, the `opt'
     will not be check any environment variable for options processing.

`void optDefaultString(char *s)'
     The program itself can define a default command line to be
     processed before the environment string and before the actual
     command line.  To be honest, I can't imagine when you'd want to
     use this in real life.

`void optDefaultFile(char *s)'
     The program can define a file name, eg `~/.programrc' or
     `/etc/program.opt', in which to look for default options for the
     program.  If the file exists, then its options are read in before
     reading the environment string or the command line.

`void optExitNumber(int n)'
     If opt has to exit, then call exit(n);

Registering functions (hooks)
-----------------------------

   Hooks are means by which the user can write routines which the `opt'
package calls during its processing.  This enables the programmer to
customize the behavior of `opt' to the program at hand.  Of course
`opt' has to be informed of the function (in the same way that
variables have to be registered, so do functions).  The hook function
should always return an integer, and a value of zero is the default
that tells `opt' that all is okay.  (You can also return `OPT_OK',
which is defined to be zero in `opt.h'.)  The return value tells `opt'
what to do after the hook has been run.  [** Warning: I am thinking of
changing these. -jt **]
`OPT_OK'
     Default.  Keep processing options.

`OPT_ERROR'
     Signals to `opt' that the hook was not successful.  Currently,
     `opt' doesn't do anything differently from what it does if
     `OPT_OK' is returned.

`OPT_EXIT'
     Program exits using the C command `exit(n);' The value of n will
     be zero unless it has been set by the function `optExitNumber(n)'.

`OPT_QUIT'
     Program exits, as with `OPT_EXIT', but it will first check to see
     if a quit-hook has been defined with the `optQuit()' function.  If
     one has, then it will run the quit-hook and then exit.

`OPT_ABORT'
     If you are in the menu, you should be returned to the prompt
     (assuming you configured `opt' to `--enable-longjmp' (default) at
     compile time); but if you are running from the command line, the
     program will quit calling a quit-hook if one has been defined.

   There are basically two kinds of hooks.  The first kind is associated
with a specific variable, and it is run whenever that option is invoked.
These hooks take a single argument, a `void *' that points to the
associated variable.  The second kind of hook is not associated with a
specific variable, and it takes no arguments.  It might be associated
with a command line string (such as `--version' which you might want to
use to make the program write a version number and exit), or with the
general behavior of `opt', such as the quit hook described below.
Here, `OPT_PFI' is declared `typedef int (*OPT_PFI)()' in the header
file `opt.h'; it is a pointer to a function returning an integer.
(Currently we exploit C's loose typecasting rules, so that `OPT_FPI'
refers to a function with any number of arguments, as long as it
returns an integer.  In future versions, we may define `OPT_PFI_V' and
`OPT_PFI_ARG' types, to indicate functions that take arguments `void *'
and `int,char **' respectively.)

   The first kind of hook is registered with the function `opthook()'.
For instance, if you register a hook with a statement such as
     int fix_mon(void *v) { ... }
     int month=9;
     ...
     optreg(&month,OPT_INT,'m',"Month");
     opthook(&month,fix_mon)
   then the function `fix_mon' will be called when the 'm' option is
invoked.  For instance, the function might determine whether the
integer MONTH variable was between 1 and 12, and if not, to fix it in
some way.  Note that the hook function `fix_mon' takes a single `void *'
argument; when `opt' calls the hook function, it will use a pointer to
the variable MONTH as the argument.  You can use the argument to get
(and manipulate) the value of the variable MONTH.  However, if the
variable is global, then you can also manipulate the month directly.
So the following two examples serve the same purpose.
     int fix_mon(void *v)
     {
         /* don't bother using the argument v;
          * just manipulate month directly */
         if (month < 1 || month > 12)
             month=1;
         return OPT_OK;
     }
   and
     int fix_mon(void *v)
     {
         int m;
         /* fix whatever int variable v is pointing to */
         m = *((int *)v);
         if (m < 1 || m > 12)
             m=1;
         *((int *)v) = m;
         return OPT_OK;
     }
   The second example is not as pretty to look at, but it is more
general.  It does not have to know which variable it is fixing, and in
fact you can `opthook' this function to several variables, and it will
apply the `fix_mon' algorithm to those variables as they are invoked.

`void opthook(void *v, OPT_PFI fcn)'
     associates a hook `fcn' with the variable pointed to by V.
     Whenever the option associated with V is invoked, eg from the
     command line, the hook is called.

`void opthook_n(int n, OPT_PFI fcn)'
     associates a hook `fcn' with the N'th option.  N is the value
     returned by the registration function `optreg'.

`int optexec(char *longname, OPT_PFI fcn, char *descript)'
     associates a hook `fcn' to the string pointed to by LONGNAME.  For
     instance, the command `optexec("version",print_version,"Write
     version info and exit");' will cause the function
     `print_version()' to be called whenever the string `--version'
     appears on the command line.  The function `print_version()' takes
     no argument, and depending on its return value, the program will
     either exit or keep going after printing the version string.

`optMain(OPT_PFI fcn)'
     The most commonly used hook in an `opt' program, at least by me.
     This function is run when the user types `=' at the `opt' menu
     prompt.  Usually, the programmer writes `fcn(argc,argv)' to do
     whatever it is that the program is supposed to do (essentially the
     same as `main(argc,argv)' but without the command line parsing
     that `opt' is taking care of).  The arguments `argc,argv' that
     `fcn' sees are the command line strings that are "leftover" after
     `opt' has finished parsing; `argv[0]' is retained however, so that
     `fcn' behaves just like a `main' function would behave.  When
     `fcn' is finished, you will be returned to the command line
     prompt.  If `opt' was configured at compile time with the
     `--enable-longjmp' (default), then if you interrupt (^C) `fcn'
     while it is running, you will be returned to the command prompt
     (instead of exiting the program completely).

`optRun(OPT_PFI run)'
     This is essentially the same as `optMain', except that the
     function `run()' takes no arguments.  If you set this hook and the
     hook in `optMain', then this hook will be ignored.

`optQuit(OPT_PFI fcn)'
     is a hook that is run just before the program that is using `opt'
     exits.

`optAdditionalUsage(OPT_PFI fcn)'
     This hook is run at the end of the usage message, and can be used
     to provide the user with additional usage information.

Misc
----

`int optinvoked(void *v)'
     Returns the number of times the option associated with the variable
     pointed to by V was invoked by the user.

Etc
***

Installation
============

   Because `opt' does not require exotic systems services or esoteric
libraries, installation on a variety of platforms should be
straightforward.  What follows is a guide to installing OPT on a UNIX
system, but I have heard of at least one successful install on a
Microsoft operating system.

   First you have to un-archive the `opt-XXX.tar.gz' file, where `XXX'
is the version number, using commands along these lines:
                gzip -d opt-XXX.tar.gz
                tar xvf opt-XXX.tar
                cd opt-XXX

   Then, it's bascially a generic GNU installation, with `configure',
`make', and `make install'.  More details can be found in the `INSTALL'
file that should be in the distribution, but those are details about
the generic installation procedure, and contain no `opt'-specific notes.

  1. You configure with the command `./configure' where the initial
     `./' is to ensure that you are running the configure script that
     is in the current directory.  You can also use the configure
     command with options.  Type `./configure --help' to see what those
     options are.  One of the most useful is the `--prefix=PATHNAME'
     option, which tells you where to install it.  Some `opt'-specific
     options are:
    `--disable-longjmp'
          If `longjmp' is enabled (default), then hitting `^C' during a
          run launched from the menu prmopt will return you to the menu
          prompt; if `longjmp' is disabled, then `^C' exits the program
          entirely.  You should only disable longjmp if you have
          trouble compiling.

    `--with-readline'
          If your system has `GNU readline' installed(1), you can
          specify this option to obtain readline features (line editing,
          history recall, etc) in the `opt' menu.  If you will be using
          the menu even a little bit, these features are very
          convenient.

    `--enable-flagonezero'
          By default, flag values of true and false are recorded (to
          the `.opt' file for instance) with `+' or `-', respectively;
          eg, `-v+' turns on the `v'-flag.  But if you invoke
          `--enable-flagonezero', then true and false are encoded as
          `1' and `0' instead.  If you have a lot of long option names,
          it looks a little cleaner (some might argure) to have
          `--verbose=0' rather than the default `--verbose=-'.

  2. The next step is easy, just type `make'.  If this fails, you may
     want to reconfigure in the previous step.

  3. If you are brave, or overly cautious, you can now type `make
     check'.  At this point, all this does is go into the `test/'
     directory and run the script `checkopt'.  The tests in this
     directory also serve as example code to show you how to use the
     opt package in your own programs.

  4. The last step is to type `make install' but you should be sure you
     have permission to write to the directories where `libopt.a' and
     `opt.h' will be copied.  This is by default `/usr/local/lib' and
     `/usr/local/include', but that can be changed at the configure
     step (see `INSTALL' for details).  Unless you are installing `opt'
     into your personal directory, you will probably have to become
     "root" before you do this step.

   ---------- Footnotes ----------

   (1) If it doesn't, you can get `readline' from any `GNU' mirror site.

Adding `opt' to existing code: a recipe
=======================================

   Suppose your code initially looks like this:
     /* yourprogram.c */
     #include <stdio.h>

     int N=5;           /* Global variable */

     int
     main(int argc, char **argv)
     {
             /** do some complicated thing  **
              ** that depends on value of N **/
     }

   You want to use the `opt' package to make the variable N into a
parameter that can be altered on the command line.  Here is the recipe.

     /* yourprogramonopt.c */
     #include <stdio.h>
     #include <opt.h>

     int N=5;           /* Global variable */

     int
     youroldmain(int argc, char **argv)
     {
             /** do some complicated thing  **
              ** that depends on value of N **/
     }

     int
     main(int argc, char **argv)
     {
             optreg(&N,OPT_INT,'N',"Number that complicated thing depends on");
             optMain(youroldmain);
             opt(&argc,&argv)
             return youroldmain(argc,argv);
     }
   Basically, you need to include the `opt.h' header file, register the
variables that will be command line parameters, register your original
`main' function (only now renamed not to conflict with the new
`main()'), call the `opt()' function itself, and then call your
original `main()' function (now renamed).

   If the "complicated thing that depends on N" depends on ARGC,ARGV,
then the ARGC,ARGV that `youroldmain()' will see will be the leftover
arguments on the command line that come after the `-N 5', or the
arguments that come after `--' on the command line.

   When the users use your program in the menu mode, they can try
different values of N, eg
     -> N 5                 ;user types `N 5' in response to prompt `->'
     -> =                   ;user says to do the complicated thing
     5                      ;output of complicated thing, followed by prompt
     -> N 500 =             ;user tries another value, and says run with that
     2 2 5 5 5              ;computer responds
     -> N 12345678          ;user types in too large a value, computer hangs
     ^C                     ;user hits ^C
     ->                     ;computer responds with menu prompt, so user can
                            ;try again with some other value

So, you don't like global variables?
====================================

   One, they're not as bad as you might think.  Remember, these are not
obscure variables that will be interacting in odd ways with different
components of a complicated whole; these are the variables that you
want to give the user direct access to.

   Two, although the examples I've given (and the codes I write) use
global variables for the user-alterable parameters, it is possible to
use `opt' without global variables.  I will leave this as an exercise
for the reader who gives a damn.

Single file
===========

   If you want to include `opt' in code that you have written to be
distributed, you are by the LGPL quite welcome to do so, following the
usual caveats, provisos, and quid pro quo's.

   You may find it inconvenient, however, to include the full
distribution of opt, with all of its automake'd Makefiles, its multiple
source files, and the extra test and extension directories.  As long as
your distribution is not an extension to opt whose purpose is ever
fancier options parsing, but instead does something useful and just
uses opt for its command line processing, then you are permitted to
include only the minimal source needed to make `libopt.a'.  In fact, to
simplify this task, you can do a `make opt.c' in the `src/' directory
and a single file, called `opt.c' of course, will be generated.  (It is
possible that the `opt' distribution will already have an `opt.c' made
for you.) You are free to include `opt.c' along with `opt.h' in your
distribution.  You don't even need to make a `libopt.a' if you don't
want to.  Just have your `Makefile' include lines to this effect:
             opt.o: opt.c opt.h
                    $(CC) $(CFLAGS) -c opt.c

             yourprogram.o: yourprogram.c opt.h
                    ...

             yourprogram: yourpgram.o ... opt.o
                    $(CC) $(LDFLAGS) -o yourprogram yourprogram.o ... opt.o
   Note that when you make `opt.c', an LGPL style copyright will appear.
You are required to keep that copyright intact, and make sure it
includes a pointer so that users of your distribution can find my full
`opt' distribution, if they want it.

Extensions
==========

`tkopt'
     is a Tk/Tcl script that is used as a front end to programs that
     have an `opt' interface.  To use it type
                  tkopt program [options]
     and a window will pop up which will permit you to edit all the
     registered options and parameters, and to run the program.  The
     beauty of `tkopt' is that it knows nothing about the program
     `program' beforehand.  It learns what the options are by running
     `program --help' and parsing the standard usage message that is
     output.  It also runs `program %tmp.opt' and then reads the
     `tmp.opt' file to determine the defaults.

`opt.pl'
     is an old Perl options processing library that is no longer
     supported, and no longer included with distributions of opt, but
     in it's place...

`Opt.pm'
     is a Perl package module which can be `use''d by other Perl
     scripts to achieve an opt-like interface.  The main bug are that
     you can already get pretty good option parsing with only a few
     lines of Perl, and there exists other packages (eg,
     `Getopt::Long') that perform quite powerful processing.  What
     `Opt.pm' provides is nearly identical behavior to the C version.
     Thus, you can use `tkopt' as a front-end to perl scripts using
     `Opt.pm' just like you can use it for C programs linked with
     `libopt.a'.

`READLINE'
     If you configure `opt' with the `--with-readline' feature, then
     `GNU readline' features (line editing, previous line retrieval,
     etc) will be available in the menu mode of `opt'.  To link your
     program to this code, you'll need to have the `readline' and
     `termcap' libraries available. But this is all done automagically
     (where by "magic" I mean code that is embarassingly complicated)
     by the configure script.  So if `libopt.a' is built with this
     option enabled, it will actually incorporate the `readline' and
     `termcap' libraries within itself, and you don't need to do
     anything different on the linking step.  In particular, you do NOT
     need to add `-lreadline -ltermcap' to the `cc' command line.  If
     it fails, and you don't feel like trying to figure out why, just
     reconfigure without the `--with-readline' option.  It's nice, but
     not really crucial.

Bugs
====

   Using `opt' promotes the use of global variables for the parameters
that `opt' sets.  Global variables are generally considered harmful to
your health, but in my experience, this has rarely been a problem for
variables that you want the user to have access to anyway.

   Another bug is that `opt' doesn't look much like the standard and
GNU's `getopt' package, even though it does pretty much the same thing.
Partly this is a design choice; I wanted something that was very easy
to "attach" to the code.  In particular, with `opt', you register
options and associate them with variables; this tends to be a little
more compact (and in my view more convenient) than the loop and
case-statement approach used by `getopt'.  Also, `opt' has a few more
bells and whistles.  If I were smart, I would have built `opt' as an
add-on to the standard `getopt'.

Warranty
========

   none.

Copying
=======

   The subroutines and source code in the `opt' package are "free".
The precise meaning of this statement is codified in the GNU Library
General Public License, which is described in the file `COPYING' that
should be included in the `opt' distribution.  If it is not, you can
obtain a copy from the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  My own imprecise interpretation of that
license, as it applies to `opt', follows.  I should say that this is a
heavily edited version of a `Copying' section that I copied from some
other GNU package (now forgotten).

   Everyone is free to use this software and free to redistribute it on
a free basis.  The `opt' library is not in the public domain; it is
copyrighted and there are restrictions on its distribution, but these
restrictions are designed to permit everything that a good cooperating
citizen would want to do.  What is not allowed is to prevent or inhibit
others from further sharing any version of this software that they
might get from you.

   Specifically, I want to make sure that you have the right to give
away copies of `opt', that you receive source code or else can get it
if you want it, that you can change `opt' or use pieces of it in new
free programs, and that you know you can do these things.

   To make sure that everyone has such rights, I cannot and do not give
you the "right" to deprive anyone else of these rights.  For example,
if you distribute copies of the `opt'-related code, you must give the
recipients all the rights that you have.  You must make sure that they,
too, receive or can get the source code.  And you must tell them their
rights.

   Also, for my own protection, I must make certain that everyone finds
out that there is no warranty for `opt'.  If this software is modified
by someone else and passed on, I want the recipients to know that what
they have is not what I distributed, so that any problems introduced by
others will not reflect on my reputation, feeble though it may be.

   Let me say that by `opt'-related, I mostly mean `opt'-derived.  If
your software does something substantially different from `opt', but
uses `opt' for its command line processing, then you can do what pretty
much you like with that code: sell it for a profit, design weapons of
mass destruction, etc.  But you should make it clear to the users of
your code that the options parsing is done by software that is free;
you should provide the `opt' source code, or at least provide the users
with a pointer to where the code is available.  (Currently, that is
`http://nis-www.lanl.gov/~jt/Software' and
`ftp://nis-ftp.lanl.gov/pub/users/jt/Software/opt'.)

   Happy hacking to all.