-allow 'years' in time units, indentation and doxygen fixes
[oweals/gnunet.git] / src / util / getopt_helpers.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2006, 2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file src/util/getopt_helpers.c
23  * @brief implements command line that sets option
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28
29 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
30
31
32 /**
33  * Print out program version (implements --version).
34  *
35  * @param ctx command line processing context
36  * @param scls additional closure (points to version string)
37  * @param option name of the option
38  * @param value not used (NULL)
39  * @return #GNUNET_NO (do not continue, not an error)
40  */
41 int
42 GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
43                               void *scls,
44                               const char *option,
45                               const char *value)
46 {
47   const char *version = scls;
48
49   printf ("%s v%s\n",
50           ctx->binaryName,
51           version);
52   return GNUNET_NO;
53 }
54
55
56 /**
57  * At what offset does the help text start?
58  */
59 #define BORDER 29
60
61 /**
62  * Print out details on command line options (implements --help).
63  *
64  * @param ctx command line processing context
65  * @param scls additional closure (points to about text)
66  * @param option name of the option
67  * @param value not used (NULL)
68  * @return #GNUNET_NO (do not continue, not an error)
69  */
70 int
71 GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
72                             void *scls,
73                             const char *option,
74                             const char *value)
75 {
76   const char *about = scls;
77   size_t slen;
78   unsigned int i;
79   int j;
80   size_t ml;
81   size_t p;
82   char *scp;
83   const char *trans;
84   const struct GNUNET_GETOPT_CommandLineOption *opt;
85
86   if (NULL != about)
87   {
88     printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
89     printf (_
90             ("Arguments mandatory for long options are also mandatory for short options.\n"));
91   }
92   i = 0;
93   opt = ctx->allOptions;
94   while (opt[i].description != NULL)
95   {
96     if (opt[i].shortName == '\0')
97       printf ("      ");
98     else
99       printf ("  -%c, ", opt[i].shortName);
100     printf ("--%s", opt[i].name);
101     slen = 8 + strlen (opt[i].name);
102     if (opt[i].argumentHelp != NULL)
103     {
104       printf ("=%s", opt[i].argumentHelp);
105       slen += 1 + strlen (opt[i].argumentHelp);
106     }
107     if (slen > BORDER)
108     {
109       printf ("\n%*s", BORDER, "");
110       slen = BORDER;
111     }
112     if (slen < BORDER)
113     {
114       printf ("%*s", (int) (BORDER - slen), "");
115       slen = BORDER;
116     }
117     if (0 < strlen (opt[i].description))
118       trans = gettext (opt[i].description);
119     else
120       trans = "";
121     ml = strlen (trans);
122     p = 0;
123 OUTER:
124     while (ml - p > 78 - slen)
125     {
126       for (j = p + 78 - slen; j > p; j--)
127       {
128         if (isspace ((unsigned char) trans[j]))
129         {
130           scp = GNUNET_malloc (j - p + 1);
131           memcpy (scp, &trans[p], j - p);
132           scp[j - p] = '\0';
133           printf ("%s\n%*s", scp, BORDER + 2, "");
134           GNUNET_free (scp);
135           p = j + 1;
136           slen = BORDER + 2;
137           goto OUTER;
138         }
139       }
140       /* could not find space to break line */
141       scp = GNUNET_malloc (78 - slen + 1);
142       memcpy (scp, &trans[p], 78 - slen);
143       scp[78 - slen] = '\0';
144       printf ("%s\n%*s", scp, BORDER + 2, "");
145       GNUNET_free (scp);
146       slen = BORDER + 2;
147       p = p + 78 - slen;
148     }
149     /* print rest */
150     if (p < ml)
151       printf ("%s\n", &trans[p]);
152     if (strlen (trans) == 0)
153       printf ("\n");
154     i++;
155   }
156   printf ("Report bugs to gnunet-developers@gnu.org.\n"
157           "GNUnet home page: http://www.gnu.org/software/gnunet/\n"
158           "General help using GNU software: http://www.gnu.org/gethelp/\n");
159   return GNUNET_NO;
160 }
161
162
163 /**
164  * Set an option of type 'unsigned int' from the command line. Each
165  * time the option flag is given, the value is incremented by one.
166  * A pointer to this function should be passed as part of the
167  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
168  * of this type.  It should be followed by a pointer to a value of
169  * type 'int'.
170  *
171  * @param ctx command line processing context
172  * @param scls additional closure (will point to the 'int')
173  * @param option name of the option
174  * @param value not used (NULL)
175  * @return #GNUNET_OK
176  */
177 int
178 GNUNET_GETOPT_increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext
179                                *ctx, void *scls, const char *option,
180                                const char *value)
181 {
182   int *val = scls;
183
184   (*val)++;
185   return GNUNET_OK;
186 }
187
188
189 /**
190  * Set an option of type 'int' from the command line to 1 if the
191  * given option is present.
192  * A pointer to this function should be passed as part of the
193  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
194  * of this type.  It should be followed by a pointer to a value of
195  * type 'int'.
196  *
197  * @param ctx command line processing context
198  * @param scls additional closure (will point to the 'int')
199  * @param option name of the option
200  * @param value not used (NULL)
201  * @return #GNUNET_OK
202  */
203 int
204 GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
205                        void *scls, const char *option, const char *value)
206 {
207   int *val = scls;
208
209   *val = 1;
210   return GNUNET_OK;
211 }
212
213
214 /**
215  * Set an option of type 'char *' from the command line.
216  * A pointer to this function should be passed as part of the
217  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
218  * of this type.  It should be followed by a pointer to a value of
219  * type 'char *', which will be allocated with the requested string.
220  *
221  * @param ctx command line processing context
222  * @param scls additional closure (will point to the 'char *',
223  *             which will be allocated)
224  * @param option name of the option
225  * @param value actual value of the option (a string)
226  * @return #GNUNET_OK
227  */
228 int
229 GNUNET_GETOPT_set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
230                           void *scls, const char *option, const char *value)
231 {
232   char **val = scls;
233
234   GNUNET_assert (value != NULL);
235   GNUNET_free_non_null (*val);
236   *val = GNUNET_strdup (value);
237   return GNUNET_OK;
238 }
239
240
241 int
242 GNUNET_GETOPT_set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
243                             void *scls, const char *option, const char *value)
244 {
245   char **val = scls;
246
247   GNUNET_assert (value != NULL);
248   GNUNET_free_non_null (*val);
249   *val = GNUNET_STRINGS_filename_expand (value);
250   return GNUNET_OK;
251 }
252
253 /**
254  * Set an option of type 'unsigned long long' from the command line.
255  * A pointer to this function should be passed as part of the
256  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
257  * of this type.  It should be followed by a pointer to a value of
258  * type 'unsigned long long'.
259  *
260  * @param ctx command line processing context
261  * @param scls additional closure (will point to the 'unsigned long long')
262  * @param option name of the option
263  * @param value actual value of the option as a string.
264  * @return #GNUNET_OK if parsing the value worked
265  */
266 int
267 GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
268                          void *scls, const char *option, const char *value)
269 {
270   unsigned long long *val = scls;
271
272   if (1 != SSCANF (value, "%llu", val))
273   {
274     FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option);
275     return GNUNET_SYSERR;
276   }
277   return GNUNET_OK;
278 }
279
280
281 /**
282  * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
283  * A pointer to this function should be passed as part of the
284  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
285  * of this type.  It should be followed by a pointer to a value of
286  * type 'struct GNUNET_TIME_Relative'.
287  *
288  * @param ctx command line processing context
289  * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
290  * @param option name of the option
291  * @param value actual value of the option as a string.
292  * @return #GNUNET_OK if parsing the value worked
293  */
294 int
295 GNUNET_GETOPT_set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
296                                  void *scls, const char *option, const char *value)
297 {
298   struct GNUNET_TIME_Relative *val = scls;
299
300   if (GNUNET_OK !=
301       GNUNET_STRINGS_fancy_time_to_relative (value,
302                                              val))
303   {
304     FPRINTF (stderr, _("You must pass relative time to the `%s' option.\n"), option);
305     return GNUNET_SYSERR;
306   }
307   return GNUNET_OK;
308 }
309
310
311 /**
312  * Set an option of type 'unsigned int' from the command line.
313  * A pointer to this function should be passed as part of the
314  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
315  * of this type.  It should be followed by a pointer to a value of
316  * type 'unsigned int'.
317  *
318  * @param ctx command line processing context
319  * @param scls additional closure (will point to the 'unsigned int')
320  * @param option name of the option
321  * @param value actual value of the option as a string.
322  * @return #GNUNET_OK if parsing the value worked
323  */
324 int
325 GNUNET_GETOPT_set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
326                         void *scls, const char *option, const char *value)
327 {
328   unsigned int *val = scls;
329
330   if (1 != SSCANF (value, "%u", val))
331   {
332     FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option);
333     return GNUNET_SYSERR;
334   }
335   return GNUNET_OK;
336 }
337
338
339 /* end of getopt_helpers.c */