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