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