]> git.ozlabs.org Git - ccan/blob - ccan/opt/helpers.c
ccan: Correct some poor conventions in _info includes
[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_set_floatval(const char *arg, float *f)
120 {
121         double d;
122         char *err;
123
124         err = opt_set_doubleval(arg, &d);
125         if (err)
126                 return err;
127
128         *f = d;
129         if (*f != d)
130                 return arg_bad("'%s' is out of range", arg);
131
132         return NULL;
133 }
134
135 void opt_show_floatval(char buf[OPT_SHOW_LEN], const float *f)
136 {
137         double d = *f;
138         opt_show_doubleval(buf, &d);
139 }
140
141 char *opt_set_doubleval(const char *arg, double *d)
142 {
143         char *endp;
144
145         /* This is how the manpage says to do it.  Yech. */
146         errno = 0;
147         /* Don't assume strtof */
148         *d = strtod(arg, &endp);
149         if (*endp || !arg[0])
150                 return arg_bad("'%s' is not a number", arg);
151         if (errno)
152                 return arg_bad("'%s' is out of range", arg);
153
154         return NULL;
155 }
156
157 void opt_show_doubleval(char buf[OPT_SHOW_LEN], const double *d)
158 {
159         snprintf(buf, OPT_SHOW_LEN, "%f", *d);
160 }
161
162 char *opt_inc_intval(int *i)
163 {
164         (*i)++;
165         return NULL;
166 }
167
168 /* Display version string. */
169 char *opt_version_and_exit(const char *version)
170 {
171         printf("%s\n", version);
172         /* Don't have valgrind complain! */
173         opt_free_table();
174         exit(0);
175 }
176
177 char *opt_usage_and_exit(const char *extra)
178 {
179         char *usage = opt_usage(opt_argv0, extra);
180         printf("%s", usage);
181         /* Don't have valgrind complain! */
182         opt_alloc.free(usage);
183         opt_free_table();
184         exit(0);
185 }
186
187 void opt_show_bool(char buf[OPT_SHOW_LEN], const bool *b)
188 {
189         strncpy(buf, *b ? "true" : "false", OPT_SHOW_LEN);
190 }
191
192 void opt_show_invbool(char buf[OPT_SHOW_LEN], const bool *b)
193 {
194         strncpy(buf, *b ? "false" : "true", OPT_SHOW_LEN);
195 }
196
197 void opt_show_charp(char buf[OPT_SHOW_LEN], char *const *p)
198 {
199         size_t len = strlen(*p);
200         buf[0] = '"';
201         if (len > OPT_SHOW_LEN - 2)
202                 len = OPT_SHOW_LEN - 2;
203         strncpy(buf+1, *p, len);
204         buf[1+len] = '"';
205         if (len < OPT_SHOW_LEN - 2)
206                 buf[2+len] = '\0';
207 }
208
209 /* Show an integer value, various forms. */
210 void opt_show_intval(char buf[OPT_SHOW_LEN], const int *i)
211 {
212         snprintf(buf, OPT_SHOW_LEN, "%i", *i);
213 }
214
215 void opt_show_uintval(char buf[OPT_SHOW_LEN], const unsigned int *ui)
216 {
217         snprintf(buf, OPT_SHOW_LEN, "%u", *ui);
218 }
219
220 void opt_show_longval(char buf[OPT_SHOW_LEN], const long *l)
221 {
222         snprintf(buf, OPT_SHOW_LEN, "%li", *l);
223 }
224
225 void opt_show_ulongval(char buf[OPT_SHOW_LEN], const unsigned long *ul)
226 {
227         snprintf(buf, OPT_SHOW_LEN, "%lu", *ul);
228 }
229
230 /* a helper function that multiplies out an argument's kMGTPE suffix in the
231  * long long int range, and perform checks common to all integer destinations.
232  *
233  * The base will be either 1000 or 1024, corresponding with the '_si' and
234  * '_bi' functions.
235  */
236
237 static char *set_llong_with_suffix(const char *arg, long long *ll,
238                                    const long long base)
239 {
240         char *endp;
241         if (!arg[0])
242                 return arg_bad("'%s' (an empty string) is not a number", arg);
243
244         errno = 0;
245         *ll = strtoll(arg, &endp, 0);
246         if (errno)
247                 return arg_bad("'%s' is out of range", arg);
248         if (*endp){
249                 /*The string continues with non-digits.  If there is just one
250                   letter and it is a known multiplier suffix, use it.*/
251                 if (endp[1])
252                         return arg_bad("'%s' is not a number (suffix too long)", arg);
253                 long long mul;
254                 switch(*endp){
255                 case 'K':
256                 case 'k':
257                         mul = base;
258                         break;
259                 case 'M':
260                 case 'm':
261                         mul = base * base;
262                         break;
263                 case 'G':
264                 case 'g':
265                         mul = base * base * base;
266                         break;
267                 case 'T':
268                 case 't':
269                         mul = base * base * base * base;
270                         break;
271                 case 'P':
272                         mul = base * base * base * base * base;
273                         break;
274                 case 'E':
275                         mul = base * base * base * base * base * base;
276                         break;
277                 /* This is as far as we can go in 64 bits ('E' is 2 ^ 60) */
278                 default:
279                         return arg_bad("'%s' is not a number (unknown suffix)",
280                                        arg);
281                 }
282                 if (*ll > LLONG_MAX / mul || *ll < LLONG_MIN / mul)
283                         return arg_bad("'%s' is out of range", arg);
284                 *ll *= mul;
285         }
286         return NULL;
287 }
288
289 /* Middle layer helpers that perform bounds checks for specific target sizes
290  * and signednesses.
291  */
292 static char * set_ulonglong_with_suffix(const char *arg, unsigned long long *ull,
293                                         const long base)
294 {
295         long long ll;
296         char *err = set_llong_with_suffix(arg, &ll, base);
297         if (err != NULL)
298                 return err;
299         if (ll < 0)
300                 return arg_bad("'%s' is negative but destination is unsigned", arg);
301         *ull = ll;
302         return NULL;
303 }
304
305 static char * set_long_with_suffix(const char *arg, long *l, const long base)
306 {
307         long long ll;
308         char *err = set_llong_with_suffix(arg, &ll, base);
309         if (err != NULL) /*an error*/
310                 return err;
311
312         *l = ll;
313         /* Beware truncation, but don't generate untestable code. */
314         if (sizeof(*l) != sizeof(ll) && *l != ll)
315                 return arg_bad("value '%s' does not fit into a long", arg);
316         return NULL;
317 }
318
319 static char * set_ulong_with_suffix(const char *arg, unsigned long *ul, const long base)
320 {
321         long long ll;
322         char *err = set_llong_with_suffix(arg, &ll, base);
323         if (err != NULL)
324                 return err;
325         if (ll < 0)
326                 return arg_bad("'%s' is negative but destination is unsigned", arg);
327         *ul = ll;
328         /* Beware truncation, but don't generate untestable code. */
329         if (sizeof(*ul) != sizeof(ll) && *ul != ll)
330                 return arg_bad("value '%s' does not fit into an unsigned long", arg);
331         return NULL;
332 }
333
334 static char * set_int_with_suffix(const char *arg, int *i, const long base)
335 {
336         long long ll;
337         char *err = set_llong_with_suffix(arg, &ll, base);
338         if (err != NULL) /*an error*/
339                 return err;
340
341         *i = ll;
342         if (*i != ll)
343                 return arg_bad("value '%s' does not fit into an int", arg);
344         return NULL;
345 }
346
347 static char * set_uint_with_suffix(const char *arg, unsigned int *u, const long base)
348 {
349         long long ll;
350         char *err = set_llong_with_suffix(arg, &ll, base);
351         if (err != NULL)
352                 return err;
353         if (ll < 0)
354                 return arg_bad("'%s' is negative but destination is unsigned", arg);
355         *u = ll;
356         if (*u != ll)
357                 return arg_bad("value '%s' does not fit into an unsigned int", arg);
358         return NULL;
359 }
360
361 /*Set an integer, with decimal or binary suffixes.
362   The accepted suffixes are k/K, M/m, G/g, T, P, E.
363
364   The *_bi functions multiply the numeric value by a power of 1024, while the
365   *_si functions multiply by a power of 1000.
366  */
367
368 char * opt_set_ulonglongval_bi(const char *arg, unsigned long long *ll)
369 {
370         return set_ulonglong_with_suffix(arg, ll, 1024);
371 }
372
373 char * opt_set_ulonglongval_si(const char *arg, unsigned long long *ll)
374 {
375         return set_ulonglong_with_suffix(arg, ll, 1000);
376 }
377
378 char * opt_set_longlongval_bi(const char *arg, long long *ll)
379 {
380         return set_llong_with_suffix(arg, ll, 1024);
381 }
382
383 char * opt_set_longlongval_si(const char *arg, long long *ll)
384 {
385         return set_llong_with_suffix(arg, ll, 1000);
386 }
387
388 char * opt_set_longval_bi(const char *arg, long *l)
389 {
390         return set_long_with_suffix(arg, l, 1024);
391 }
392
393 char * opt_set_longval_si(const char *arg, long *l)
394 {
395         return set_long_with_suffix(arg, l, 1000);
396 }
397
398 char * opt_set_ulongval_bi(const char *arg, unsigned long *ul)
399 {
400         return set_ulong_with_suffix(arg, ul, 1024);
401 }
402
403 char * opt_set_ulongval_si(const char *arg, unsigned long *ul)
404 {
405         return set_ulong_with_suffix(arg, ul, 1000);
406 }
407
408 char * opt_set_intval_bi(const char *arg, int *i)
409 {
410         return set_int_with_suffix(arg, i, 1024);
411 }
412
413 char * opt_set_intval_si(const char *arg, int *i)
414 {
415         return set_int_with_suffix(arg, i, 1000);
416 }
417
418 char * opt_set_uintval_bi(const char *arg, unsigned int *u)
419 {
420         return set_uint_with_suffix(arg, u, 1024);
421 }
422
423 char * opt_set_uintval_si(const char *arg, unsigned int *u)
424 {
425         return set_uint_with_suffix(arg, u, 1000);
426 }
427
428 /*static helpers for showing values with kMGTPE suffixes.  In this case there
429   are separate but essentially identical functions for signed and unsigned
430   values, so that unsigned values greater than LLONG_MAX get suffixes.
431  */
432 static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll,
433                                     const long long base)
434 {
435         const char *suffixes = "kMGTPE";
436         int i;
437         if (ll == 0){
438                 /*zero is special because everything divides it (you'd get "0E")*/
439                 snprintf(buf, OPT_SHOW_LEN, "0");
440                 return;
441         }
442         for (i = 0; i < strlen(suffixes); i++){
443                 long long tmp = ll / base;
444                 if (tmp * base != ll)
445                         break;
446                 ll = tmp;
447         }
448         if (i == 0)
449                 snprintf(buf, OPT_SHOW_LEN, "%"PRId64, (int64_t)ll);
450         else
451                 snprintf(buf, OPT_SHOW_LEN, "%"PRId64"%c", (int64_t)ll, suffixes[i - 1]);
452 }
453
454 static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull,
455                                     const unsigned base)
456 {
457         const char *suffixes = "kMGTPE";
458         int i;
459         if (ull == 0){
460                 /*zero is special because everything divides it (you'd get "0E")*/
461                 snprintf(buf, OPT_SHOW_LEN, "0");
462                 return;
463         }
464         for (i = 0; i < strlen(suffixes); i++){
465                 unsigned long long tmp = ull / base;
466                 if (tmp * base != ull)
467                         break;
468                 ull = tmp;
469         }
470         if (i == 0)
471                 snprintf(buf, OPT_SHOW_LEN, "%"PRIu64, (uint64_t)ull);
472         else
473                 snprintf(buf, OPT_SHOW_LEN, "%"PRIu64"%c", (uint64_t)ull, suffixes[i - 1]);
474 }
475
476 /* _bi, signed */
477 void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x)
478 {
479         show_llong_with_suffix(buf, *x, 1024);
480 }
481
482 void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x)
483 {
484         show_llong_with_suffix(buf, *x, 1024);
485 }
486
487 void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x)
488 {
489         show_llong_with_suffix(buf, *x, 1024);
490 }
491
492 /* _bi, unsigned */
493 void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x)
494 {
495         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
496 }
497
498 void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x)
499 {
500         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
501 }
502
503 void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x)
504 {
505         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
506 }
507
508 /* _si, signed */
509 void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x)
510 {
511         show_llong_with_suffix(buf, (long long) *x, 1000);
512 }
513
514 void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x)
515 {
516         show_llong_with_suffix(buf, (long long) *x, 1000);
517 }
518
519 void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x)
520 {
521         show_llong_with_suffix(buf, *x, 1000);
522 }
523
524 /* _si, unsigned */
525 void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x)
526 {
527         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
528 }
529
530 void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x)
531 {
532         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
533 }
534
535 void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x)
536 {
537         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
538 }
539