xref: /freebsd/crypto/heimdal/lib/roken/getarg.3 (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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