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