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