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