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