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