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