Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / lib / roken / getarg.3
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 .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
18 collects any command line options given to a program in an easily used way. 
19 .Fn arg_printusage 
20 pretty-prints the available options, with a short help text.
21 .Pp
22 .Fa args
23 is the option specification to use, and it's an array of 
24 .Fa struct getargs
25 elements.
26 .Fa num_args
27 is the size of
28 .Fa args
29 (in elements).
30 .Fa argc
31 and
32 .Fa argv
33 are the argument count and argument vector to extract option from.
34 .Fa optind
35 is a pointer to an integer where the index to the last processed
36 argument is stored, it must be initialised to the first index (minus
37 one) to process (normally 0) before the first call.
38 .Pp
39 .Fa arg_printusage
40 take the same
41 .Fa args
42 and
43 .Fa num_args
44 as getarg;
45 .Fa progname
46 is the name of the program (to be used in the help text), and 
47 .Fa extra_string
48 is a string to print after the actual options to indicate more
49 arguments. The usefulness of this function is realised only be people
50 who has used programs that has help strings that doesn't match what
51 the code does.
52 .Pp
53 The
54 .Fa getargs
55 struct has the following elements.
56 .Bd -literal
57 struct 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
75 is the long name of the option, it can be 
76 .Dv NULL ,
77 if you don't want a long name.
78 .Fa short_name 
79 is the characted to use as short option, it can be zero. If the option
80 has a value the
81 .Fa value
82 field gets filled in with that value interpreted as specified by the 
83 .Fa type
84 field.
85 .Fa help
86 is a longer help string for the option as a whole, if it's
87 .Dv NULL
88 the help text for the option is omitted (but it's still displayed in
89 the synopsis).
90 .Fa arg_help
91 is a description of the argument, if
92 .Dv NULL
93 a 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
97 the argument is a signed integer, and
98 .Fa value
99 should point to an
100 .Fa int .
101 .It Fa arg_string
102 the argument is a string, and
103 .Fa value
104 should point to a
105 .Fa char* .
106 .It Fa arg_flag
107 the argument is a flag, and
108 .Fa value
109 should point to a
110 .Fa int . 
111 It gets filled in with either zero or one, depending on how the option
112 is given, the normal case beeing one. Note that if the option isn't
113 given, the value isn't altered, so it should be initialised to some
114 useful default.
115 .It Fa arg_negative_flag
116 this is the same as 
117 .Fa arg_flag
118 but it reverses the meaning of the flag (a given short option clears
119 the flag), and the synopsis of a long option is negated.
120 .It Fa arg_strings
121 the argument can be given multiple times, and the values are collected
122 in an array;
123 .Fa value
124 should be a pointer to a 
125 .Fa struct getarg_strings
126 structure, which holds a length and a string pointer.
127 .It Fa arg_double
128 argument is a double precision floating point value, and
129 .Fa value
130 should point to a
131 .Fa double .
132 .It Fa arg_collect
133 allows more fine-grained control of the option parsing process.
134 .Fa value
135 should be a pointer to a 
136 .Fa getarg_collect_info
137 structure:
138 .Bd -literal
139 typedef int (*getarg_collect_func)(int short_opt,
140                                    int argc,
141                                    char **argv,
142                                    int *optind,
143                                    int *optarg,
144                                    void *data);
145
146 typedef struct getarg_collect_info {
147     getarg_collect_func func;
148     void *data;
149 } getarg_collect_info;
150 .Ed
151 .Pp
152 With the
153 .Fa func
154 member set to a function to call, and 
155 .Fa data
156 to some application specific data. The parameters to the collect function are:
157 .Bl -inset
158 .It Fa short_flag
159 non-zero if this call is via a short option flag, zero otherwise
160 .It Fa argc , argv
161 the whole argument list
162 .It Fa optind
163 pointer to the index in argv where the flag is
164 .It Fa optarg
165 pointer to the index in argv[*optind] where the flag name starts
166 .It Fa data
167 application specific data
168 .El
169 .Pp
170 You can modify
171 .Fa *optind ,
172 and 
173 .Fa *optarg ,
174 but to do this correct you (more or less) have to know about the inner
175 workings of getarg.
176 .Pp 
177 You can skip parts of arguments by increasing
178 .Fa *optarg
179 (you could
180 implement the 
181 .Fl z Ns Ar 3
182 set of flags from
183 .Nm gzip
184 with 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
188 to specify a coordinate); if you also have to set
189 .Fa *optarg
190 to a sane value.
191 .Pp
192 The collect function should return one of 
193 .Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG
194 on error, zero otherwise.
195 .Pp
196 For your convenience there is a function,
197 .Fn getarg_optarg ,
198 that returns the traditional argument string, and you pass it all
199 arguments, sans data, that where given to the collection function.
200 .Pp
201 Don't use this more this unless you absolutely have to.
202 .El
203 .Pp
204 Option parsing is similar to what 
205 .Xr getopt
206 uses. Short options without arguments can be compressed
207 .Pf ( Fl xyz
208 is the same as
209 .Fl x y z ) ,
210 and short
211 options with arguments take these as either the rest of the
212 argv-string or as the next option
213 .Pf ( Fl o Ns Ar foo ,
214 or
215 .Fl o Ar foo ) .
216 .Pp
217 Long option names are prefixed with -- (double dash), and the value
218 with a = (equal),
219 .Fl -foo= Ns Ar bar .
220 Long option flags can either be specified as they are 
221 .Pf ( Fl -help ) ,
222 or with an (boolean parsable) option
223 .Pf ( Fl -help= Ns Ar yes ,
224 .Fl -help= Ns Ar true ,
225 or similar), or they can also be negated 
226 .Pf ( Fl -no-help
227 is the same as 
228 .Fl -help= Ns no ) ,
229 and if you're really confused you can do it multiple times
230 .Pf ( Fl -no-no-help= Ns Ar false ,
231 or 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
239 char *source = "Ouagadougou";
240 char *destination;
241 int weight;
242 int include_catalog = 1;
243 int help_flag;
244
245 struct 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
257 int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
258
259 const char *progname = "ship++";
260
261 int
262 main(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
286 The output help output from this program looks like this:
287 .Bd -literal
288 $ ship++ --help                                            
289 Usage: 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
297 It should be more flexible, so it would be possible to use other more
298 complicated option syntaxes, such as what
299 .Xr ps 1 ,
300 and 
301 .Xr tar 1 ,
302 uses, or the AFS model where you can skip the flag names as long as
303 the options come in the correct order.
304 .Pp
305 Options with multiple arguments should be handled better.
306 .Pp
307 Should be integreated with SL.
308 .Pp
309 It's very confusing that the struct you pass in is called getargS.
310 .Sh SEE ALSO
311 .Xr getopt 3