]> git.ozlabs.org Git - ccan/blob - ccan/opt/helpers.c
2c771bc3309062aa7cfea03423f719128f3c9686
[ccan] / ccan / opt / helpers.c
1 /* Licensed under GPLv2+ - see LICENSE file for details */
2 #include <ccan/opt/opt.h>
3 #include <ccan/cast/cast.h>
4 #include <inttypes.h>
5 #include <string.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <limits.h>
11 #include "private.h"
12
13 /* Upper bound to sprintf this simple type?  Each 3 bits < 1 digit. */
14 #define CHAR_SIZE(type) (((sizeof(type)*CHAR_BIT + 2) / 3) + 1)
15
16 /* FIXME: asprintf module? */
17 static char *arg_bad(const char *fmt, const char *arg)
18 {
19         char *str = malloc(strlen(fmt) + strlen(arg));
20         sprintf(str, fmt, arg);
21         return str;
22 }
23
24 char *opt_set_bool(bool *b)
25 {
26         *b = true;
27         return NULL;
28 }
29
30 char *opt_set_invbool(bool *b)
31 {
32         *b = false;
33         return NULL;
34 }
35
36 char *opt_set_bool_arg(const char *arg, bool *b)
37 {
38         if (!strcasecmp(arg, "yes") || !strcasecmp(arg, "true"))
39                 return opt_set_bool(b);
40         if (!strcasecmp(arg, "no") || !strcasecmp(arg, "false"))
41                 return opt_set_invbool(b);
42
43         return opt_invalid_argument(arg);
44 }
45
46 char *opt_set_invbool_arg(const char *arg, bool *b)
47 {
48         char *err = opt_set_bool_arg(arg, b);
49
50         if (!err)
51                 *b = !*b;
52         return err;
53 }
54
55 /* Set a char *. */
56 char *opt_set_charp(const char *arg, char **p)
57 {
58         *p = cast_const(char *, arg);
59         return NULL;
60 }
61
62 /* Set an integer value, various forms.
63    FIXME: set to 1 on arg == NULL ? */
64 char *opt_set_intval(const char *arg, int *i)
65 {
66         long l;
67         char *err = opt_set_longval(arg, &l);
68
69         if (err)
70                 return err;
71         *i = l;
72         /* Beware truncation, but don't generate untestable code. */
73         if (sizeof(*i) != sizeof(l) && *i != l)
74                 return arg_bad("value '%s' does not fit into an integer", arg);
75         return err;
76 }
77
78 char *opt_set_uintval(const char *arg, unsigned int *ui)
79 {
80         int i;
81         char *err = opt_set_intval(arg, &i);
82
83         if (err)
84                 return err;
85         if (i < 0)
86                 return arg_bad("'%s' is negative but destination is unsigned", arg);
87         *ui = i;
88         return NULL;
89 }
90
91 char *opt_set_longval(const char *arg, long *l)
92 {
93         char *endp;
94
95         /* This is how the manpage says to do it.  Yech. */
96         errno = 0;
97         *l = strtol(arg, &endp, 0);
98         if (*endp || !arg[0])
99                 return arg_bad("'%s' is not a number", arg);
100         if (errno)
101                 return arg_bad("'%s' is out of range", arg);
102         return NULL;
103 }
104
105 char *opt_set_ulongval(const char *arg, unsigned long *ul)
106 {
107         long int l;
108         char *err;
109
110         err = opt_set_longval(arg, &l);
111         if (err)
112                 return err;
113         *ul = l;
114         if (l < 0)
115                 return arg_bad("'%s' is negative but destination is unsigned", arg);
116         return NULL;
117 }
118
119 char *opt_inc_intval(int *i)
120 {
121         (*i)++;
122         return NULL;
123 }
124
125 /* Display version string. */
126 char *opt_version_and_exit(const char *version)
127 {
128         printf("%s\n", version);
129         /* Don't have valgrind complain! */
130         opt_free_table();
131         exit(0);
132 }
133
134 char *opt_usage_and_exit(const char *extra)
135 {
136         char *usage = opt_usage(opt_argv0, extra);
137         printf("%s", usage);
138         /* Don't have valgrind complain! */
139         opt_alloc.free(usage);
140         opt_free_table();
141         exit(0);
142 }
143
144 void opt_show_bool(char buf[OPT_SHOW_LEN], const bool *b)
145 {
146         strncpy(buf, *b ? "true" : "false", OPT_SHOW_LEN);
147 }
148
149 void opt_show_invbool(char buf[OPT_SHOW_LEN], const bool *b)
150 {
151         strncpy(buf, *b ? "false" : "true", OPT_SHOW_LEN);
152 }
153
154 void opt_show_charp(char buf[OPT_SHOW_LEN], char *const *p)
155 {
156         size_t len = strlen(*p);
157         buf[0] = '"';
158         if (len > OPT_SHOW_LEN - 2)
159                 len = OPT_SHOW_LEN - 2;
160         strncpy(buf+1, *p, len);
161         buf[1+len] = '"';
162         if (len < OPT_SHOW_LEN - 2)
163                 buf[2+len] = '\0';
164 }
165
166 /* Show an integer value, various forms. */
167 void opt_show_intval(char buf[OPT_SHOW_LEN], const int *i)
168 {
169         snprintf(buf, OPT_SHOW_LEN, "%i", *i);
170 }
171
172 void opt_show_uintval(char buf[OPT_SHOW_LEN], const unsigned int *ui)
173 {
174         snprintf(buf, OPT_SHOW_LEN, "%u", *ui);
175 }
176
177 void opt_show_longval(char buf[OPT_SHOW_LEN], const long *l)
178 {
179         snprintf(buf, OPT_SHOW_LEN, "%li", *l);
180 }
181
182 void opt_show_ulongval(char buf[OPT_SHOW_LEN], const unsigned long *ul)
183 {
184         snprintf(buf, OPT_SHOW_LEN, "%lu", *ul);
185 }
186
187 /* a helper function that multiplies out an argument's kMGTPE suffix in the
188  * long long int range, and perform checks common to all integer destinations.
189  *
190  * The base will be either 1000 or 1024, corresponding with the '_si' and
191  * '_bi' functions.
192  */
193
194 static char *set_llong_with_suffix(const char *arg, long long *ll,
195                                    const long long base)
196 {
197         char *endp;
198         if (!arg[0])
199                 return arg_bad("'%s' (an empty string) is not a number", arg);
200
201         errno = 0;
202         *ll = strtoll(arg, &endp, 0);
203         if (errno)
204                 return arg_bad("'%s' is out of range", arg);
205         if (*endp){
206                 /*The string continues with non-digits.  If there is just one
207                   letter and it is a known multiplier suffix, use it.*/
208                 if (endp[1])
209                         return arg_bad("'%s' is not a number (suffix too long)", arg);
210                 long long mul;
211                 switch(*endp){
212                 case 'K':
213                 case 'k':
214                         mul = base;
215                         break;
216                 case 'M':
217                 case 'm':
218                         mul = base * base;
219                         break;
220                 case 'G':
221                 case 'g':
222                         mul = base * base * base;
223                         break;
224                 case 'T':
225                 case 't':
226                         mul = base * base * base * base;
227                         break;
228                 case 'P':
229                         mul = base * base * base * base * base;
230                         break;
231                 case 'E':
232                         mul = base * base * base * base * base * base;
233                         break;
234                 /* This is as far as we can go in 64 bits ('E' is 2 ^ 60) */
235                 default:
236                         return arg_bad("'%s' is not a number (unknown suffix)",
237                                        arg);
238                 }
239                 if (*ll > LLONG_MAX / mul || *ll < LLONG_MIN / mul)
240                         return arg_bad("'%s' is out of range", arg);
241                 *ll *= mul;
242         }
243         return NULL;
244 }
245
246 /* Middle layer helpers that perform bounds checks for specific target sizes
247  * and signednesses.
248  */
249 static char * set_ulonglong_with_suffix(const char *arg, unsigned long long *ull,
250                                         const long base)
251 {
252         long long ll;
253         char *err = set_llong_with_suffix(arg, &ll, base);
254         if (err != NULL)
255                 return err;
256         if (ll < 0)
257                 return arg_bad("'%s' is negative but destination is unsigned", arg);
258         *ull = ll;
259         return NULL;
260 }
261
262 static char * set_long_with_suffix(const char *arg, long *l, const long base)
263 {
264         long long ll;
265         char *err = set_llong_with_suffix(arg, &ll, base);
266         if (err != NULL) /*an error*/
267                 return err;
268
269         *l = ll;
270         /* Beware truncation, but don't generate untestable code. */
271         if (sizeof(*l) != sizeof(ll) && *l != ll)
272                 return arg_bad("value '%s' does not fit into a long", arg);
273         return NULL;
274 }
275
276 static char * set_ulong_with_suffix(const char *arg, unsigned long *ul, const long base)
277 {
278         long long ll;
279         char *err = set_llong_with_suffix(arg, &ll, base);
280         if (err != NULL)
281                 return err;
282         if (ll < 0)
283                 return arg_bad("'%s' is negative but destination is unsigned", arg);
284         *ul = ll;
285         /* Beware truncation, but don't generate untestable code. */
286         if (sizeof(*ul) != sizeof(ll) && *ul != ll)
287                 return arg_bad("value '%s' does not fit into an unsigned long", arg);
288         return NULL;
289 }
290
291 static char * set_int_with_suffix(const char *arg, int *i, const long base)
292 {
293         long long ll;
294         char *err = set_llong_with_suffix(arg, &ll, base);
295         if (err != NULL) /*an error*/
296                 return err;
297
298         *i = ll;
299         if (*i != ll)
300                 return arg_bad("value '%s' does not fit into an int", arg);
301         return NULL;
302 }
303
304 static char * set_uint_with_suffix(const char *arg, unsigned int *u, const long base)
305 {
306         long long ll;
307         char *err = set_llong_with_suffix(arg, &ll, base);
308         if (err != NULL)
309                 return err;
310         if (ll < 0)
311                 return arg_bad("'%s' is negative but destination is unsigned", arg);
312         *u = ll;
313         if (*u != ll)
314                 return arg_bad("value '%s' does not fit into an unsigned int", arg);
315         return NULL;
316 }
317
318 /*Set an integer, with decimal or binary suffixes.
319   The accepted suffixes are k/K, M/m, G/g, T, P, E.
320
321   The *_bi functions multiply the numeric value by a power of 1024, while the
322   *_si functions multiply by a power of 1000.
323  */
324
325 char * opt_set_ulonglongval_bi(const char *arg, unsigned long long *ll)
326 {
327         return set_ulonglong_with_suffix(arg, ll, 1024);
328 }
329
330 char * opt_set_ulonglongval_si(const char *arg, unsigned long long *ll)
331 {
332         return set_ulonglong_with_suffix(arg, ll, 1000);
333 }
334
335 char * opt_set_longlongval_bi(const char *arg, long long *ll)
336 {
337         return set_llong_with_suffix(arg, ll, 1024);
338 }
339
340 char * opt_set_longlongval_si(const char *arg, long long *ll)
341 {
342         return set_llong_with_suffix(arg, ll, 1000);
343 }
344
345 char * opt_set_longval_bi(const char *arg, long *l)
346 {
347         return set_long_with_suffix(arg, l, 1024);
348 }
349
350 char * opt_set_longval_si(const char *arg, long *l)
351 {
352         return set_long_with_suffix(arg, l, 1000);
353 }
354
355 char * opt_set_ulongval_bi(const char *arg, unsigned long *ul)
356 {
357         return set_ulong_with_suffix(arg, ul, 1024);
358 }
359
360 char * opt_set_ulongval_si(const char *arg, unsigned long *ul)
361 {
362         return set_ulong_with_suffix(arg, ul, 1000);
363 }
364
365 char * opt_set_intval_bi(const char *arg, int *i)
366 {
367         return set_int_with_suffix(arg, i, 1024);
368 }
369
370 char * opt_set_intval_si(const char *arg, int *i)
371 {
372         return set_int_with_suffix(arg, i, 1000);
373 }
374
375 char * opt_set_uintval_bi(const char *arg, unsigned int *u)
376 {
377         return set_uint_with_suffix(arg, u, 1024);
378 }
379
380 char * opt_set_uintval_si(const char *arg, unsigned int *u)
381 {
382         return set_uint_with_suffix(arg, u, 1000);
383 }
384
385 /*static helpers for showing values with kMGTPE suffixes.  In this case there
386   are separate but essentially identical functions for signed and unsigned
387   values, so that unsigned values greater than LLONG_MAX get suffixes.
388  */
389 static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll,
390                                     const long long base)
391 {
392         const char *suffixes = "kMGTPE";
393         int i;
394         if (ll == 0){
395                 /*zero is special because everything divides it (you'd get "0E")*/
396                 snprintf(buf, OPT_SHOW_LEN, "0");
397                 return;
398         }
399         for (i = 0; i < strlen(suffixes); i++){
400                 long long tmp = ll / base;
401                 if (tmp * base != ll)
402                         break;
403                 ll = tmp;
404         }
405         if (i == 0)
406                 snprintf(buf, OPT_SHOW_LEN, "%"PRId64, (int64_t)ll);
407         else
408                 snprintf(buf, OPT_SHOW_LEN, "%"PRId64"%c", (int64_t)ll, suffixes[i - 1]);
409 }
410
411 static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull,
412                                     const unsigned base)
413 {
414         const char *suffixes = "kMGTPE";
415         int i;
416         if (ull == 0){
417                 /*zero is special because everything divides it (you'd get "0E")*/
418                 snprintf(buf, OPT_SHOW_LEN, "0");
419                 return;
420         }
421         for (i = 0; i < strlen(suffixes); i++){
422                 unsigned long long tmp = ull / base;
423                 if (tmp * base != ull)
424                         break;
425                 ull = tmp;
426         }
427         if (i == 0)
428                 snprintf(buf, OPT_SHOW_LEN, "%"PRIu64, (uint64_t)ull);
429         else
430                 snprintf(buf, OPT_SHOW_LEN, "%"PRIu64"%c", (uint64_t)ull, suffixes[i - 1]);
431 }
432
433 /* _bi, signed */
434 void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x)
435 {
436         show_llong_with_suffix(buf, *x, 1024);
437 }
438
439 void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x)
440 {
441         show_llong_with_suffix(buf, *x, 1024);
442 }
443
444 void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x)
445 {
446         show_llong_with_suffix(buf, *x, 1024);
447 }
448
449 /* _bi, unsigned */
450 void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x)
451 {
452         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
453 }
454
455 void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x)
456 {
457         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
458 }
459
460 void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x)
461 {
462         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
463 }
464
465 /* _si, signed */
466 void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x)
467 {
468         show_llong_with_suffix(buf, (long long) *x, 1000);
469 }
470
471 void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x)
472 {
473         show_llong_with_suffix(buf, (long long) *x, 1000);
474 }
475
476 void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x)
477 {
478         show_llong_with_suffix(buf, *x, 1000);
479 }
480
481 /* _si, unsigned */
482 void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x)
483 {
484         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
485 }
486
487 void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x)
488 {
489         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
490 }
491
492 void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x)
493 {
494         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
495 }
496