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