1.\" Copyright (c) 1999 Kungliga Tekniska H�gskolan 2.\" $Id: getarg.3,v 1.2 1999/10/18 17:14:31 joda Exp $ 3.Dd September 24, 1999 4.Dt GETARG 3 5.Os ROKEN 6.Sh NAME 7.Nm getarg , 8.Nm arg_printusage 9.Nd collect command line options 10.Sh SYNOPSIS 11.Fd #include <getarg.h> 12 13.Ft int 14.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind" 15 16.Ft void 17.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string" 18 19.Sh DESCRIPTION 20.Fn getarg 21collects any command line options given to a program in an easily used way. 22.Fn arg_printusage 23pretty-prints the available options, with a short help text. 24.Pp 25.Fa args 26is the option specification to use, and it's an array of 27.Fa struct getargs 28elements. 29.Fa num_args 30is the size of 31.Fa args 32(in elements). 33.Fa argc 34and 35.Fa argv 36are the argument count and argument vector to extract option from. 37.Fa optind 38is a pointer to an integer where the index to the last processed 39argument is stored, it must be initialised to the first index (minus 40one) to process (normally 0) before the first call. 41.Pp 42.Fa arg_printusage 43take the same 44.Fa args 45and 46.Fa num_args 47as getarg; 48.Fa progname is the name of the program (to be used in the help text), and 49.Fa extra_string 50is a string to print after the actual options to indicate more 51arguments. The usefulness of this function is realised only be people 52who has used programs that has help strings that doesn't match what 53the code does. 54.Pp 55The 56.Fa getargs 57struct has the following elements. 58 59.Bd -literal 60struct getargs{ 61 const char *long_name; 62 char short_name; 63 enum { arg_integer, 64 arg_string, 65 arg_flag, 66 arg_negative_flag, 67 arg_strings, 68 arg_double, 69 arg_collect 70 } type; 71 void *value; 72 const char *help; 73 const char *arg_help; 74}; 75.Ed 76.Pp 77.Fa long_name 78is the long name of the option, it can be 79.Dv NULL , 80if you don't want a long name. 81.Fa short_name 82is the characted to use as short option, it can be zero. If the option 83has a value the 84.Fa value 85field gets filled in with that value interpreted as specified by the 86.Fa type 87field. 88.Fa help 89is a longer help string for the option as a whole, if it's 90.Dv NULL 91the help text for the option is omitted (but it's still displayed in 92the synopsis). 93.Fa arg_help 94is a description of the argument, if 95.Dv NULL 96a default value will be used, depending on the type of the option: 97.Pp 98.Bl -hang -width arg_negative_flag 99.It arg_integer 100the argument is a signed integer, and 101.Fa value 102should point to an 103.Fa int . 104.It Fa arg_string 105the argument is a string, and 106.Fa value 107should point to a 108.Fa char* . 109.It Fa arg_flag 110the argument is a flag, and 111.Fa value 112should point to a 113.Fa int . 114It gets filled in with either zero or one, depending on how the option 115is given, the normal case beeing one. Note that if the option isn't 116given, the value isn't altered, so it should be initialised to some 117useful default. 118.It Fa arg_negative_flag 119this is the same as 120.Fa arg_flag 121but it reverses the meaning of the flag (a given short option clears 122the flag), and the synopsis of a long option is negated. 123.It Fa arg_strings 124the argument can be given multiple times, and the values are collected 125in an array; 126.Fa value 127should be a pointer to a 128.Fa struct getarg_strings 129structure, which holds a length and a string pointer. 130.It Fa arg_double 131argument is a double precision floating point value, and 132.Fa value 133should point to a 134.Fa double . 135.It Fa arg_collect 136allows more fine-grained control of the option parsing process. 137.Fa value 138should be a pointer to a 139.Fa getarg_collect_info 140structure: 141.Bd -literal 142typedef int (*getarg_collect_func)(int short_opt, 143 int argc, 144 char **argv, 145 int *optind, 146 int *optarg, 147 void *data); 148 149typedef struct getarg_collect_info { 150 getarg_collect_func func; 151 void *data; 152} getarg_collect_info; 153.Ed 154.Pp 155With the 156.Fa func 157member set to a function to call, and 158.Fa data 159to some application specific data. The parameters to the collect function are: 160.Bl -inset 161.It Fa short_flag 162non-zero if this call is via a short option flag, zero otherwise 163.It Fa argc , argv 164the whole argument list 165.It Fa optind 166pointer to the index in argv where the flag is 167.It Fa optarg 168pointer to the index in argv[*optind] where the flag name starts 169.It Fa data 170application specific data 171.El 172.Pp 173You can modify 174.Fa *optind , 175and 176.Fa *optarg , 177but to do this correct you (more or less) have to know about the inner 178workings of getarg. 179 180You can skip parts of arguments by increasing 181.Fa *optarg 182(you could 183implement the 184.Fl z Ns Ar 3 185set of flags from 186.Nm gzip 187with this), or whole argument strings by increasing 188.Fa *optind 189(let's say you want a flag 190.Fl c Ar x y z 191to specify a coordinate); if you also have to set 192.Fa *optarg 193to a sane value. 194.Pp 195The collect function should return one of 196.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG 197on error, zero otherwise. 198.Pp 199For your convenience there is a function, 200.Fn getarg_optarg , 201that returns the traditional argument string, and you pass it all 202arguments, sans data, that where given to the collection function. 203.Pp 204Don't use this more this unless you absolutely have to. 205.El 206.Pp 207Option parsing is similar to what 208.Xr getopt 209uses. Short options without arguments can be compressed 210.Pf ( Fl xyz 211is the same as 212.Fl x y z ) , 213and short 214options with arguments take these as either the rest of the 215argv-string or as the next option 216.Pf ( Fl o Ns Ar foo , 217or 218.Fl o Ar foo ) . 219.Pp 220Long option names are prefixed with -- (double dash), and the value 221with a = (equal), 222.Fl -foo= Ns Ar bar . 223Long option flags can either be specified as they are 224.Pf ( Fl -help ) , 225or with an (boolean parsable) option 226.Pf ( Fl -help= Ns Ar yes , 227.Fl -help= Ns Ar true , 228or similar), or they can also be negated 229.Pf ( Fl -no-help 230is the same as 231.Fl -help= Ns no ) , 232and if you're really confused you can do it multiple times 233.Pf ( Fl -no-no-help= Ns Ar false , 234or even 235.Fl -no-no-help= Ns Ar maybe ) . 236 237.Pp 238.Sh EXAMPLE 239.Bd -literal 240#include <stdio.h> 241#include <string.h> 242#include <getarg.h> 243 244char *source = "Ouagadougou"; 245char *destination; 246int weight; 247int include_catalog = 1; 248int help_flag; 249 250struct getargs args[] = { 251 { "source", 's', arg_string, &source, 252 "source of shippment", "city" }, 253 { "destination", 'd', arg_string, &destination, 254 "destination of shippment", "city" }, 255 { "weight", 'w', arg_integer, &weight, 256 "weight of shippment", "tons" }, 257 { "catalog", 'c', arg_negative_flag, &include_catalog, 258 "include product catalog" }, 259 { "help", 'h', arg_flag, &help_flag } 260}; 261 262int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */ 263 264const char *progname = "ship++"; 265 266int 267main(int argc, char **argv) 268{ 269 int optind = 0; 270 if (getarg(args, num_args, argc, argv, &optind)) { 271 arg_printusage(args, num_args, progname, "stuff..."); 272 exit (1); 273 } 274 if (help_flag) { 275 arg_printusage(args, num_args, progname, "stuff..."); 276 exit (0); 277 } 278 if (destination == NULL) { 279 fprintf(stderr, "%s: must specify destination\n", progname); 280 exit(1); 281 } 282 if (strcmp(source, destination) == 0) { 283 fprintf(stderr, "%s: destination must be different from source\n"); 284 exit(1); 285 } 286 /* include more stuff here ... */ 287 exit(2); 288} 289.Ed 290.Pp 291The output help output from this program looks like this: 292.Bd -literal 293$ ship++ --help 294Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city] 295 [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff... 296-s city, --source=city source of shippment 297-d city, --destination=city destination of shippment 298-w tons, --weight=tons weight of shippment 299-c, --no-catalog include product catalog 300.Ed 301 302.Sh BUGS 303It should be more flexible, so it would be possible to use other more 304complicated option syntaxes, such as what 305.Xr ps 1 , 306and 307.Xr tar 1 , 308uses, or the AFS model where you can skip the flag names as long as 309the options come in the correct order. 310.Pp 311Options with multiple arguments should be handled better. 312.Pp 313Should be integreated with SL. 314.Pp 315It's very confusing that the struct you pass in is called getargS. 316.Sh SEE ALSO 317.Xr getopt 3 318