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