xref: /freebsd/crypto/heimdal/lib/roken/getarg.3 (revision b528cefc6b8f9670b31a865051741d946cb37085)
1b528cefcSMark Murray.\" Copyright (c) 1999 Kungliga Tekniska H�gskolan
2b528cefcSMark Murray.\" $Id: getarg.3,v 1.2 1999/10/18 17:14:31 joda Exp $
3b528cefcSMark Murray.Dd September 24, 1999
4b528cefcSMark Murray.Dt GETARG 3
5b528cefcSMark Murray.Os ROKEN
6b528cefcSMark Murray.Sh NAME
7b528cefcSMark Murray.Nm getarg ,
8b528cefcSMark Murray.Nm arg_printusage
9b528cefcSMark Murray.Nd collect command line options
10b528cefcSMark Murray.Sh SYNOPSIS
11b528cefcSMark Murray.Fd #include <getarg.h>
12b528cefcSMark Murray
13b528cefcSMark Murray.Ft int
14b528cefcSMark Murray.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind"
15b528cefcSMark Murray
16b528cefcSMark Murray.Ft void
17b528cefcSMark Murray.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string"
18b528cefcSMark Murray
19b528cefcSMark Murray.Sh DESCRIPTION
20b528cefcSMark Murray.Fn getarg
21b528cefcSMark Murraycollects any command line options given to a program in an easily used way.
22b528cefcSMark Murray.Fn arg_printusage
23b528cefcSMark Murraypretty-prints the available options, with a short help text.
24b528cefcSMark Murray.Pp
25b528cefcSMark Murray.Fa args
26b528cefcSMark Murrayis the option specification to use, and it's an array of
27b528cefcSMark Murray.Fa struct getargs
28b528cefcSMark Murrayelements.
29b528cefcSMark Murray.Fa num_args
30b528cefcSMark Murrayis the size of
31b528cefcSMark Murray.Fa args
32b528cefcSMark Murray(in elements).
33b528cefcSMark Murray.Fa argc
34b528cefcSMark Murrayand
35b528cefcSMark Murray.Fa argv
36b528cefcSMark Murrayare the argument count and argument vector to extract option from.
37b528cefcSMark Murray.Fa optind
38b528cefcSMark Murrayis a pointer to an integer where the index to the last processed
39b528cefcSMark Murrayargument is stored, it must be initialised to the first index (minus
40b528cefcSMark Murrayone) to process (normally 0) before the first call.
41b528cefcSMark Murray.Pp
42b528cefcSMark Murray.Fa arg_printusage
43b528cefcSMark Murraytake the same
44b528cefcSMark Murray.Fa args
45b528cefcSMark Murrayand
46b528cefcSMark Murray.Fa num_args
47b528cefcSMark Murrayas getarg;
48b528cefcSMark Murray.Fa progname is the name of the program (to be used in the help text), and
49b528cefcSMark Murray.Fa extra_string
50b528cefcSMark Murrayis a string to print after the actual options to indicate more
51b528cefcSMark Murrayarguments. The usefulness of this function is realised only be people
52b528cefcSMark Murraywho has used programs that has help strings that doesn't match what
53b528cefcSMark Murraythe code does.
54b528cefcSMark Murray.Pp
55b528cefcSMark MurrayThe
56b528cefcSMark Murray.Fa getargs
57b528cefcSMark Murraystruct has the following elements.
58b528cefcSMark Murray
59b528cefcSMark Murray.Bd -literal
60b528cefcSMark Murraystruct getargs{
61b528cefcSMark Murray    const char *long_name;
62b528cefcSMark Murray    char short_name;
63b528cefcSMark Murray    enum { arg_integer,
64b528cefcSMark Murray	   arg_string,
65b528cefcSMark Murray	   arg_flag,
66b528cefcSMark Murray	   arg_negative_flag,
67b528cefcSMark Murray	   arg_strings,
68b528cefcSMark Murray	   arg_double,
69b528cefcSMark Murray           arg_collect
70b528cefcSMark Murray    } type;
71b528cefcSMark Murray    void *value;
72b528cefcSMark Murray    const char *help;
73b528cefcSMark Murray    const char *arg_help;
74b528cefcSMark Murray};
75b528cefcSMark Murray.Ed
76b528cefcSMark Murray.Pp
77b528cefcSMark Murray.Fa long_name
78b528cefcSMark Murrayis the long name of the option, it can be
79b528cefcSMark Murray.Dv NULL ,
80b528cefcSMark Murrayif you don't want a long name.
81b528cefcSMark Murray.Fa short_name
82b528cefcSMark Murrayis the characted to use as short option, it can be zero. If the option
83b528cefcSMark Murrayhas a value the
84b528cefcSMark Murray.Fa value
85b528cefcSMark Murrayfield gets filled in with that value interpreted as specified by the
86b528cefcSMark Murray.Fa type
87b528cefcSMark Murrayfield.
88b528cefcSMark Murray.Fa help
89b528cefcSMark Murrayis a longer help string for the option as a whole, if it's
90b528cefcSMark Murray.Dv NULL
91b528cefcSMark Murraythe help text for the option is omitted (but it's still displayed in
92b528cefcSMark Murraythe synopsis).
93b528cefcSMark Murray.Fa arg_help
94b528cefcSMark Murrayis a description of the argument, if
95b528cefcSMark Murray.Dv NULL
96b528cefcSMark Murraya default value will be used, depending on the type of the option:
97b528cefcSMark Murray.Pp
98b528cefcSMark Murray.Bl -hang -width arg_negative_flag
99b528cefcSMark Murray.It arg_integer
100b528cefcSMark Murraythe argument is a signed integer, and
101b528cefcSMark Murray.Fa value
102b528cefcSMark Murrayshould point to an
103b528cefcSMark Murray.Fa int .
104b528cefcSMark Murray.It Fa arg_string
105b528cefcSMark Murraythe argument is a string, and
106b528cefcSMark Murray.Fa value
107b528cefcSMark Murrayshould point to a
108b528cefcSMark Murray.Fa char* .
109b528cefcSMark Murray.It Fa arg_flag
110b528cefcSMark Murraythe argument is a flag, and
111b528cefcSMark Murray.Fa value
112b528cefcSMark Murrayshould point to a
113b528cefcSMark Murray.Fa int .
114b528cefcSMark MurrayIt gets filled in with either zero or one, depending on how the option
115b528cefcSMark Murrayis given, the normal case beeing one. Note that if the option isn't
116b528cefcSMark Murraygiven, the value isn't altered, so it should be initialised to some
117b528cefcSMark Murrayuseful default.
118b528cefcSMark Murray.It Fa arg_negative_flag
119b528cefcSMark Murraythis is the same as
120b528cefcSMark Murray.Fa arg_flag
121b528cefcSMark Murraybut it reverses the meaning of the flag (a given short option clears
122b528cefcSMark Murraythe flag), and the synopsis of a long option is negated.
123b528cefcSMark Murray.It Fa arg_strings
124b528cefcSMark Murraythe argument can be given multiple times, and the values are collected
125b528cefcSMark Murrayin an array;
126b528cefcSMark Murray.Fa value
127b528cefcSMark Murrayshould be a pointer to a
128b528cefcSMark Murray.Fa struct getarg_strings
129b528cefcSMark Murraystructure, which holds a length and a string pointer.
130b528cefcSMark Murray.It Fa arg_double
131b528cefcSMark Murrayargument is a double precision floating point value, and
132b528cefcSMark Murray.Fa value
133b528cefcSMark Murrayshould point to a
134b528cefcSMark Murray.Fa double .
135b528cefcSMark Murray.It Fa arg_collect
136b528cefcSMark Murrayallows more fine-grained control of the option parsing process.
137b528cefcSMark Murray.Fa value
138b528cefcSMark Murrayshould be a pointer to a
139b528cefcSMark Murray.Fa getarg_collect_info
140b528cefcSMark Murraystructure:
141b528cefcSMark Murray.Bd -literal
142b528cefcSMark Murraytypedef int (*getarg_collect_func)(int short_opt,
143b528cefcSMark Murray				   int argc,
144b528cefcSMark Murray				   char **argv,
145b528cefcSMark Murray				   int *optind,
146b528cefcSMark Murray				   int *optarg,
147b528cefcSMark Murray				   void *data);
148b528cefcSMark Murray
149b528cefcSMark Murraytypedef struct getarg_collect_info {
150b528cefcSMark Murray    getarg_collect_func func;
151b528cefcSMark Murray    void *data;
152b528cefcSMark Murray} getarg_collect_info;
153b528cefcSMark Murray.Ed
154b528cefcSMark Murray.Pp
155b528cefcSMark MurrayWith the
156b528cefcSMark Murray.Fa func
157b528cefcSMark Murraymember set to a function to call, and
158b528cefcSMark Murray.Fa data
159b528cefcSMark Murrayto some application specific data. The parameters to the collect function are:
160b528cefcSMark Murray.Bl -inset
161b528cefcSMark Murray.It Fa short_flag
162b528cefcSMark Murraynon-zero if this call is via a short option flag, zero otherwise
163b528cefcSMark Murray.It Fa argc , argv
164b528cefcSMark Murraythe whole argument list
165b528cefcSMark Murray.It Fa optind
166b528cefcSMark Murraypointer to the index in argv where the flag is
167b528cefcSMark Murray.It Fa optarg
168b528cefcSMark Murraypointer to the index in argv[*optind] where the flag name starts
169b528cefcSMark Murray.It Fa data
170b528cefcSMark Murrayapplication specific data
171b528cefcSMark Murray.El
172b528cefcSMark Murray.Pp
173b528cefcSMark MurrayYou can modify
174b528cefcSMark Murray.Fa *optind ,
175b528cefcSMark Murrayand
176b528cefcSMark Murray.Fa *optarg ,
177b528cefcSMark Murraybut to do this correct you (more or less) have to know about the inner
178b528cefcSMark Murrayworkings of getarg.
179b528cefcSMark Murray
180b528cefcSMark MurrayYou can skip parts of arguments by increasing
181b528cefcSMark Murray.Fa *optarg
182b528cefcSMark Murray(you could
183b528cefcSMark Murrayimplement the
184b528cefcSMark Murray.Fl z Ns Ar 3
185b528cefcSMark Murrayset of flags from
186b528cefcSMark Murray.Nm gzip
187b528cefcSMark Murraywith this), or whole argument strings by increasing
188b528cefcSMark Murray.Fa *optind
189b528cefcSMark Murray(let's say you want a flag
190b528cefcSMark Murray.Fl c Ar x y z
191b528cefcSMark Murrayto specify a coordinate); if you also have to set
192b528cefcSMark Murray.Fa *optarg
193b528cefcSMark Murrayto a sane value.
194b528cefcSMark Murray.Pp
195b528cefcSMark MurrayThe collect function should return one of
196b528cefcSMark Murray.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG
197b528cefcSMark Murrayon error, zero otherwise.
198b528cefcSMark Murray.Pp
199b528cefcSMark MurrayFor your convenience there is a function,
200b528cefcSMark Murray.Fn getarg_optarg ,
201b528cefcSMark Murraythat returns the traditional argument string, and you pass it all
202b528cefcSMark Murrayarguments, sans data, that where given to the collection function.
203b528cefcSMark Murray.Pp
204b528cefcSMark MurrayDon't use this more this unless you absolutely have to.
205b528cefcSMark Murray.El
206b528cefcSMark Murray.Pp
207b528cefcSMark MurrayOption parsing is similar to what
208b528cefcSMark Murray.Xr getopt
209b528cefcSMark Murrayuses. Short options without arguments can be compressed
210b528cefcSMark Murray.Pf ( Fl xyz
211b528cefcSMark Murrayis the same as
212b528cefcSMark Murray.Fl x y z ) ,
213b528cefcSMark Murrayand short
214b528cefcSMark Murrayoptions with arguments take these as either the rest of the
215b528cefcSMark Murrayargv-string or as the next option
216b528cefcSMark Murray.Pf ( Fl o Ns Ar foo ,
217b528cefcSMark Murrayor
218b528cefcSMark Murray.Fl o Ar foo ) .
219b528cefcSMark Murray.Pp
220b528cefcSMark MurrayLong option names are prefixed with -- (double dash), and the value
221b528cefcSMark Murraywith a = (equal),
222b528cefcSMark Murray.Fl -foo= Ns Ar bar .
223b528cefcSMark MurrayLong option flags can either be specified as they are
224b528cefcSMark Murray.Pf ( Fl -help ) ,
225b528cefcSMark Murrayor with an (boolean parsable) option
226b528cefcSMark Murray.Pf ( Fl -help= Ns Ar yes ,
227b528cefcSMark Murray.Fl -help= Ns Ar true ,
228b528cefcSMark Murrayor similar), or they can also be negated
229b528cefcSMark Murray.Pf ( Fl -no-help
230b528cefcSMark Murrayis the same as
231b528cefcSMark Murray.Fl -help= Ns no ) ,
232b528cefcSMark Murrayand if you're really confused you can do it multiple times
233b528cefcSMark Murray.Pf ( Fl -no-no-help= Ns Ar false ,
234b528cefcSMark Murrayor even
235b528cefcSMark Murray.Fl -no-no-help= Ns Ar maybe ) .
236b528cefcSMark Murray
237b528cefcSMark Murray.Pp
238b528cefcSMark Murray.Sh EXAMPLE
239b528cefcSMark Murray.Bd -literal
240b528cefcSMark Murray#include <stdio.h>
241b528cefcSMark Murray#include <string.h>
242b528cefcSMark Murray#include <getarg.h>
243b528cefcSMark Murray
244b528cefcSMark Murraychar *source = "Ouagadougou";
245b528cefcSMark Murraychar *destination;
246b528cefcSMark Murrayint weight;
247b528cefcSMark Murrayint include_catalog = 1;
248b528cefcSMark Murrayint help_flag;
249b528cefcSMark Murray
250b528cefcSMark Murraystruct getargs args[] = {
251b528cefcSMark Murray    { "source",      's', arg_string,  &source,
252b528cefcSMark Murray      "source of shippment", "city" },
253b528cefcSMark Murray    { "destination", 'd', arg_string,  &destination,
254b528cefcSMark Murray      "destination of shippment", "city" },
255b528cefcSMark Murray    { "weight",      'w', arg_integer, &weight,
256b528cefcSMark Murray      "weight of shippment", "tons" },
257b528cefcSMark Murray    { "catalog",     'c', arg_negative_flag, &include_catalog,
258b528cefcSMark Murray      "include product catalog" },
259b528cefcSMark Murray    { "help",        'h', arg_flag, &help_flag }
260b528cefcSMark Murray};
261b528cefcSMark Murray
262b528cefcSMark Murrayint num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
263b528cefcSMark Murray
264b528cefcSMark Murrayconst char *progname = "ship++";
265b528cefcSMark Murray
266b528cefcSMark Murrayint
267b528cefcSMark Murraymain(int argc, char **argv)
268b528cefcSMark Murray{
269b528cefcSMark Murray    int optind = 0;
270b528cefcSMark Murray    if (getarg(args, num_args, argc, argv, &optind)) {
271b528cefcSMark Murray	arg_printusage(args, num_args, progname, "stuff...");
272b528cefcSMark Murray	exit (1);
273b528cefcSMark Murray    }
274b528cefcSMark Murray    if (help_flag) {
275b528cefcSMark Murray	arg_printusage(args, num_args, progname, "stuff...");
276b528cefcSMark Murray	exit (0);
277b528cefcSMark Murray    }
278b528cefcSMark Murray    if (destination == NULL) {
279b528cefcSMark Murray	fprintf(stderr, "%s: must specify destination\n", progname);
280b528cefcSMark Murray	exit(1);
281b528cefcSMark Murray    }
282b528cefcSMark Murray    if (strcmp(source, destination) == 0) {
283b528cefcSMark Murray	fprintf(stderr, "%s: destination must be different from source\n");
284b528cefcSMark Murray	exit(1);
285b528cefcSMark Murray    }
286b528cefcSMark Murray    /* include more stuff here ... */
287b528cefcSMark Murray    exit(2);
288b528cefcSMark Murray}
289b528cefcSMark Murray.Ed
290b528cefcSMark Murray.Pp
291b528cefcSMark MurrayThe output help output from this program looks like this:
292b528cefcSMark Murray.Bd -literal
293b528cefcSMark Murray$ ship++ --help
294b528cefcSMark MurrayUsage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
295b528cefcSMark Murray   [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
296b528cefcSMark Murray-s city, --source=city      source of shippment
297b528cefcSMark Murray-d city, --destination=city destination of shippment
298b528cefcSMark Murray-w tons, --weight=tons      weight of shippment
299b528cefcSMark Murray-c, --no-catalog            include product catalog
300b528cefcSMark Murray.Ed
301b528cefcSMark Murray
302b528cefcSMark Murray.Sh BUGS
303b528cefcSMark MurrayIt should be more flexible, so it would be possible to use other more
304b528cefcSMark Murraycomplicated option syntaxes, such as what
305b528cefcSMark Murray.Xr ps 1 ,
306b528cefcSMark Murrayand
307b528cefcSMark Murray.Xr tar 1 ,
308b528cefcSMark Murrayuses, or the AFS model where you can skip the flag names as long as
309b528cefcSMark Murraythe options come in the correct order.
310b528cefcSMark Murray.Pp
311b528cefcSMark MurrayOptions with multiple arguments should be handled better.
312b528cefcSMark Murray.Pp
313b528cefcSMark MurrayShould be integreated with SL.
314b528cefcSMark Murray.Pp
315b528cefcSMark MurrayIt's very confusing that the struct you pass in is called getargS.
316b528cefcSMark Murray.Sh SEE ALSO
317b528cefcSMark Murray.Xr getopt 3
318