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