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