home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_08_03
/
8n03028a
< prev
next >
Wrap
Text File
|
1990-03-20
|
5KB
|
186 lines
*****Listing 3*****
/* cmd_opts.c, c\lib\src, (c) 1989 Scott D. Maley
May be freely used, as long as copyright notice is preserved
cmd_options(argc, argv, option)
int *argc; -- pointer to command line arg count
char *argv[]; -- pointer to array of pointers to
command line arguments
struct options option[]; -- structure array defining valid
options
This is a function to process command line options (or
switches). The full set of command line arguments is passed
to the routine via argc and argv. Every option switch
encountered that is a valid match for a switch specified in
the option array is counted, removed from argv, and the
pointer to it's associated value (if any) is moved to
the optv array. A count of switches which are not valid
matches of any option is returned, and those switches are
left in argv.
A switch's value may be contiguous with it, or be separated
from it by white-space (e.g. -svalue, -s value). White-
space is commonly blanks and tabs, but may also include
commas in some C implementations. This routine doesn't care.
The C runtime initilization routine which runs before main()
is entered parses the command line into tokens (which the
elements of argv point to), based on it's definition of
white-space.
The structure "options" is used to define what this routine
will parse:
struct options
{
char s; -- The option (switch) letter
int arg_flg; -- indicates if an arg is required
char **poptv[];-- pointer to option value vector
-- NULL, if none expected
} ;
The third argument to this routine, option, is an array of
the options structures. The end of this array is signaled
with s == 0.
This routine returns:
0 - if all switches encountered were valid options.
-n - Negative of the count of invalid (e.g. no
value followed the switch when one was expected, or
a value was contiguous with the switch, but none
was expected) switches encountered. N also includes
a count of switches that were expected, but not
encountered in argv.
It also sets arg_flg to indicate how many of each
switch encountered.
Sample use:
----------
#include <stdio.h>
#include "cmd_opts.h"
main(argc, argv)
int argc;
char *argv[];
{
char s, *farg[] *marg[];
static struct options sw[] =
{'a', 0, NULL, -- optional, no value
'f', 0, &farg, -- optional, w/ value
'm', 1, &marg, -- required, w/ value
0, 0, NULL};
if (cmd_options( & argc, argv, sw) < 0)
{
--- error, handle it here
---
}
---
--- continue with rest of program
---
}
*-- History:
* 30 Jan 89 SDM (TASC) No need to calloc optv, we
* can work entirely within argv (plus
* a temp pointer).
* 27 Jan 89 SDM (TASC) Handle multiple instances
* of a switch.
* Retain everything not
* specified in opts in argv, and set
* argc accordingly.
* 20 Jan 89 S.D. Maley (TASC) Initial implementation.
*-- End History
*/
#include <stdio.h>
#include "cmd_opts.h"
#define EOS '\0'
#define MoveOptFromArg(optv,argv,i,argc) \
{char *temp;\
temp= argv[i];\
RemoveArg(argv,i,argc);\
(optv)--;\
optv[0]= temp;\
}
#define RemoveArg(argv,i,argc) \
{int j;\
(argc)--;\
for(j=i;j<argc;j++) argv[j]=argv[j+1];\
}
#define SWFLG '-'
#define SwChr *(argv[i]+1)
#define SwMatch (*argv[i] == SWFLG && opts[j].s == SwChr)
#define SwValContig (*(argv[i]+2) != EOS)
#define SwValNext (i+1 < *argc && *argv[i+1] != SWFLG)
cmd_options(argc, argv, opts)
int *argc;
char *argv[];
struct options opts[];
{
int i,j, njth, stat;
char **optv; /* equivalent to: *optv[] */
optv = argv + *argc; /* work from back to front */
/*-- Transfer options from argv to optv
* -- and check against expectations
*/
stat = 0;
for (j = 0; opts[j].s != 0; j++)
{
njth = 0;
for (i = *argc - 1; i > 0; i--)
{ /* back to front, we build optv */
if (SwMatch)
{
if (opts[j].poptv == NULL)
{ /* no arg value desired */
if (SwValContig)
continue; /* next i */
else
RemoveArg(argv,i,*argc);
} else { /* A value is desired */
if (SwValContig)
{
argv[i] += 2; /* past "-'opt_char'" */
MoveOptFromArg(optv, argv,i,*argc);
} else if (SwValNext)
{ /*-- pick up value from next arg */
RemoveArg(argv,i,*argc);
MoveOptFromArg(optv, argv,i,*argc);
} else
continue; /* next i */
}
njth++; /* only count valid switches */
} /* if SwMatch */
} /* for i */
if (opts[j].poptv != NULL)
*opts[j].poptv= optv; /* point to option value vector */
if (opts[j].arg_flg > njth )
stat -= opts[j].arg_flg - njth ; /* not enough */
opts[j].arg_flg = njth;
} /* for j */
for (i= 1; i < *argc; i++)
if (*argv[i] == SWFLG)
stat--; /* a switch we couldn't handle */
return(stat);
}