]> git.ozlabs.org Git - ccan/blob - ccan/opt/helpers.c
failtest: add --trace to replace --tracepath
[ccan] / ccan / opt / helpers.c
1 /* Licensed under GPLv3+ - see LICENSE file for details */
2 #include <ccan/opt/opt.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <limits.h>
8 #include "private.h"
9
10 /* Upper bound to sprintf this simple type?  Each 3 bits < 1 digit. */
11 #define CHAR_SIZE(type) (((sizeof(type)*CHAR_BIT + 2) / 3) + 1)
12
13 /* FIXME: asprintf module? */
14 static char *arg_bad(const char *fmt, const char *arg)
15 {
16         char *str = malloc(strlen(fmt) + strlen(arg));
17         sprintf(str, fmt, arg);
18         return str;
19 }
20
21 char *opt_set_bool(bool *b)
22 {
23         *b = true;
24         return NULL;
25 }
26
27 char *opt_set_invbool(bool *b)
28 {
29         *b = false;
30         return NULL;
31 }
32
33 char *opt_set_bool_arg(const char *arg, bool *b)
34 {
35         if (!strcasecmp(arg, "yes") || !strcasecmp(arg, "true"))
36                 return opt_set_bool(b);
37         if (!strcasecmp(arg, "no") || !strcasecmp(arg, "false"))
38                 return opt_set_invbool(b);
39
40         return opt_invalid_argument(arg);
41 }
42
43 char *opt_set_invbool_arg(const char *arg, bool *b)
44 {
45         char *err = opt_set_bool_arg(arg, b);
46
47         if (!err)
48                 *b = !*b;
49         return err;
50 }
51
52 /* Set a char *. */
53 char *opt_set_charp(const char *arg, char **p)
54 {
55         *p = (char *)arg;
56         return NULL;
57 }
58
59 /* Set an integer value, various forms.
60    FIXME: set to 1 on arg == NULL ? */
61 char *opt_set_intval(const char *arg, int *i)
62 {
63         long l;
64         char *err = opt_set_longval(arg, &l);
65
66         if (err)
67                 return err;
68         *i = l;
69         /* Beware truncation, but don't generate untestable code. */
70         if (sizeof(*i) != sizeof(l) && *i != l)
71                 return arg_bad("value '%s' does not fit into an integer", arg);
72         return err;
73 }
74
75 char *opt_set_uintval(const char *arg, unsigned int *ui)
76 {
77         int i;
78         char *err = opt_set_intval(arg, &i);
79
80         if (err)
81                 return err;
82         if (i < 0)
83                 return arg_bad("'%s' is negative but destination is unsigned", arg);
84         *ui = i;
85         return NULL;
86 }
87
88 char *opt_set_longval(const char *arg, long *l)
89 {
90         char *endp;
91
92         /* This is how the manpage says to do it.  Yech. */
93         errno = 0;
94         *l = strtol(arg, &endp, 0);
95         if (*endp || !arg[0])
96                 return arg_bad("'%s' is not a number", arg);
97         if (errno)
98                 return arg_bad("'%s' is out of range", arg);
99         return NULL;
100 }
101
102 char *opt_set_ulongval(const char *arg, unsigned long *ul)
103 {
104         long int l;
105         char *err;
106
107         err = opt_set_longval(arg, &l);
108         if (err)
109                 return err;
110         *ul = l;
111         if (l < 0)
112                 return arg_bad("'%s' is negative but destination is unsigned", arg);
113         return NULL;
114 }
115
116 char *opt_inc_intval(int *i)
117 {
118         (*i)++;
119         return NULL;
120 }
121
122 /* Display version string. */
123 char *opt_version_and_exit(const char *version)
124 {
125         printf("%s\n", version);
126         exit(0);
127 }
128
129 char *opt_usage_and_exit(const char *extra)
130 {
131         printf("%s", opt_usage(opt_argv0, extra));
132         exit(0);
133 }
134
135 void opt_show_bool(char buf[OPT_SHOW_LEN], const bool *b)
136 {
137         strncpy(buf, *b ? "true" : "false", OPT_SHOW_LEN);
138 }
139
140 void opt_show_invbool(char buf[OPT_SHOW_LEN], const bool *b)
141 {
142         strncpy(buf, *b ? "false" : "true", OPT_SHOW_LEN);
143 }
144
145 void opt_show_charp(char buf[OPT_SHOW_LEN], char *const *p)
146 {
147         size_t len = strlen(*p);
148         buf[0] = '"';
149         if (len > OPT_SHOW_LEN - 2)
150                 len = OPT_SHOW_LEN - 2;
151         strncpy(buf+1, *p, len);
152         buf[1+len] = '"';
153         if (len < OPT_SHOW_LEN - 2)
154                 buf[2+len] = '\0';
155 }
156
157 /* Show an integer value, various forms. */
158 void opt_show_intval(char buf[OPT_SHOW_LEN], const int *i)
159 {
160         snprintf(buf, OPT_SHOW_LEN, "%i", *i);
161 }
162
163 void opt_show_uintval(char buf[OPT_SHOW_LEN], const unsigned int *ui)
164 {
165         snprintf(buf, OPT_SHOW_LEN, "%u", *ui);
166 }
167
168 void opt_show_longval(char buf[OPT_SHOW_LEN], const long *l)
169 {
170         snprintf(buf, OPT_SHOW_LEN, "%li", *l);
171 }
172
173 void opt_show_ulongval(char buf[OPT_SHOW_LEN], const unsigned long *ul)
174 {
175         snprintf(buf, OPT_SHOW_LEN, "%lu", *ul);
176 }
177
178 /* a helper function that multiplies out an argument's kMGTPE suffix in the
179  * long long int range, and perform checks common to all integer destinations.
180  *
181  * The base will be either 1000 or 1024, corresponding with the '_si' and
182  * '_bi' functions.
183  */
184
185 static char *set_llong_with_suffix(const char *arg, long long *ll,
186                                    const long long base)
187 {
188         char *endp;
189         if (!arg[0])
190                 return arg_bad("'%s' (an empty string) is not a number", arg);
191
192         errno = 0;
193         *ll = strtoll(arg, &endp, 0);
194         if (errno)
195                 return arg_bad("'%s' is out of range", arg);
196         if (*endp){
197                 /*The string continues with non-digits.  If there is just one
198                   letter and it is a known multiplier suffix, use it.*/
199                 if (endp[1])
200                         return arg_bad("'%s' is not a number (suffix too long)", arg);
201                 long long mul;
202                 switch(*endp){
203                 case 'K':
204                 case 'k':
205                         mul = base;
206                         break;
207                 case 'M':
208                 case 'm':
209                         mul = base * base;
210                         break;
211                 case 'G':
212                 case 'g':
213                         mul = base * base * base;
214                         break;
215                 case 'T':
216                 case 't':
217                         mul = base * base * base * base;
218                         break;
219                 case 'P':
220                         mul = base * base * base * base * base;
221                         break;
222                 case 'E':
223                         mul = base * base * base * base * base * base;
224                         break;
225                 /* This is as far as we can go in 64 bits ('E' is 2 ^ 60) */
226                 default:
227                         return arg_bad("'%s' is not a number (unknown suffix)",
228                                        arg);
229                 }
230                 if (*ll > LLONG_MAX / mul || *ll < LLONG_MIN / mul)
231                         return arg_bad("'%s' is out of range", arg);
232                 *ll *= mul;
233         }
234         return NULL;
235 }
236
237 /* Middle layer helpers that perform bounds checks for specific target sizes
238  * and signednesses.
239  */
240 static char * set_ulonglong_with_suffix(const char *arg, unsigned long long *ull,
241                                         const long base)
242 {
243         long long ll;
244         char *err = set_llong_with_suffix(arg, &ll, base);
245         if (err != NULL)
246                 return err;
247         if (ll < 0)
248                 return arg_bad("'%s' is negative but destination is unsigned", arg);
249         *ull = ll;
250         return NULL;
251 }
252
253 static char * set_long_with_suffix(const char *arg, long *l, const long base)
254 {
255         long long ll;
256         char *err = set_llong_with_suffix(arg, &ll, base);
257         if (err != NULL) /*an error*/
258                 return err;
259
260         *l = ll;
261         /* Beware truncation, but don't generate untestable code. */
262         if (sizeof(*l) != sizeof(ll) && *l != ll)
263                 return arg_bad("value '%s' does not fit into a long", arg);
264         return NULL;
265 }
266
267 static char * set_ulong_with_suffix(const char *arg, unsigned long *ul, const long base)
268 {
269         long long ll;
270         char *err = set_llong_with_suffix(arg, &ll, base);
271         if (err != NULL)
272                 return err;
273         if (ll < 0)
274                 return arg_bad("'%s' is negative but destination is unsigned", arg);
275         *ul = ll;
276         /* Beware truncation, but don't generate untestable code. */
277         if (sizeof(*ul) != sizeof(ll) && *ul != ll)
278                 return arg_bad("value '%s' does not fit into an unsigned long", arg);
279         return NULL;
280 }
281
282 static char * set_int_with_suffix(const char *arg, int *i, const long base)
283 {
284         long long ll;
285         char *err = set_llong_with_suffix(arg, &ll, base);
286         if (err != NULL) /*an error*/
287                 return err;
288
289         *i = ll;
290         if (*i != ll)
291                 return arg_bad("value '%s' does not fit into an int", arg);
292         return NULL;
293 }
294
295 static char * set_uint_with_suffix(const char *arg, unsigned int *u, const long base)
296 {
297         long long ll;
298         char *err = set_llong_with_suffix(arg, &ll, base);
299         if (err != NULL)
300                 return err;
301         if (ll < 0)
302                 return arg_bad("'%s' is negative but destination is unsigned", arg);
303         *u = ll;
304         if (*u != ll)
305                 return arg_bad("value '%s' does not fit into an unsigned int", arg);
306         return NULL;
307 }
308
309 /*Set an integer, with decimal or binary suffixes.
310   The accepted suffixes are k/K, M/m, G/g, T, P, E.
311
312   The *_bi functions multiply the numeric value by a power of 1024, while the
313   *_si functions multiply by a power of 1000.
314  */
315
316 char * opt_set_ulonglongval_bi(const char *arg, unsigned long long *ll)
317 {
318         return set_ulonglong_with_suffix(arg, ll, 1024);
319 }
320
321 char * opt_set_ulonglongval_si(const char *arg, unsigned long long *ll)
322 {
323         return set_ulonglong_with_suffix(arg, ll, 1000);
324 }
325
326 char * opt_set_longlongval_bi(const char *arg, long long *ll)
327 {
328         return set_llong_with_suffix(arg, ll, 1024);
329 }
330
331 char * opt_set_longlongval_si(const char *arg, long long *ll)
332 {
333         return set_llong_with_suffix(arg, ll, 1000);
334 }
335
336 char * opt_set_longval_bi(const char *arg, long *l)
337 {
338         return set_long_with_suffix(arg, l, 1024);
339 }
340
341 char * opt_set_longval_si(const char *arg, long *l)
342 {
343         return set_long_with_suffix(arg, l, 1000);
344 }
345
346 char * opt_set_ulongval_bi(const char *arg, unsigned long *ul)
347 {
348         return set_ulong_with_suffix(arg, ul, 1024);
349 }
350
351 char * opt_set_ulongval_si(const char *arg, unsigned long *ul)
352 {
353         return set_ulong_with_suffix(arg, ul, 1000);
354 }
355
356 char * opt_set_intval_bi(const char *arg, int *i)
357 {
358         return set_int_with_suffix(arg, i, 1024);
359 }
360
361 char * opt_set_intval_si(const char *arg, int *i)
362 {
363         return set_int_with_suffix(arg, i, 1000);
364 }
365
366 char * opt_set_uintval_bi(const char *arg, unsigned int *u)
367 {
368         return set_uint_with_suffix(arg, u, 1024);
369 }
370
371 char * opt_set_uintval_si(const char *arg, unsigned int *u)
372 {
373         return set_uint_with_suffix(arg, u, 1000);
374 }
375
376 /*static helpers for showing values with kMGTPE suffixes.  In this case there
377   are separate but essentially identical functions for signed and unsigned
378   values, so that unsigned values greater than LLONG_MAX get suffixes.
379  */
380 static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll,
381                                     const long long base)
382 {
383         const char *suffixes = "kMGTPE";
384         int i;
385         if (ll == 0){
386                 /*zero is special because everything divides it (you'd get "0E")*/
387                 snprintf(buf, OPT_SHOW_LEN, "0");
388                 return;
389         }
390         for (i = 0; i < strlen(suffixes); i++){
391                 long long tmp = ll / base;
392                 if (tmp * base != ll)
393                         break;
394                 ll = tmp;
395         }
396         if (i == 0)
397                 snprintf(buf, OPT_SHOW_LEN, "%lld", ll);
398         else
399                 snprintf(buf, OPT_SHOW_LEN, "%lld%c", ll, suffixes[i - 1]);
400 }
401
402 static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull,
403                                     const unsigned base)
404 {
405         const char *suffixes = "kMGTPE";
406         int i;
407         if (ull == 0){
408                 /*zero is special because everything divides it (you'd get "0E")*/
409                 snprintf(buf, OPT_SHOW_LEN, "0");
410                 return;
411         }
412         for (i = 0; i < strlen(suffixes); i++){
413                 unsigned long long tmp = ull / base;
414                 if (tmp * base != ull)
415                         break;
416                 ull = tmp;
417         }
418         if (i == 0)
419                 snprintf(buf, OPT_SHOW_LEN, "%llu", ull);
420         else
421                 snprintf(buf, OPT_SHOW_LEN, "%llu%c", ull, suffixes[i - 1]);
422 }
423
424 /* _bi, signed */
425 void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x)
426 {
427         show_llong_with_suffix(buf, *x, 1024);
428 }
429
430 void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x)
431 {
432         show_llong_with_suffix(buf, *x, 1024);
433 }
434
435 void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x)
436 {
437         show_llong_with_suffix(buf, *x, 1024);
438 }
439
440 /* _bi, unsigned */
441 void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x)
442 {
443         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
444 }
445
446 void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x)
447 {
448         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
449 }
450
451 void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x)
452 {
453         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
454 }
455
456 /* _si, signed */
457 void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x)
458 {
459         show_llong_with_suffix(buf, (long long) *x, 1000);
460 }
461
462 void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x)
463 {
464         show_llong_with_suffix(buf, (long long) *x, 1000);
465 }
466
467 void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x)
468 {
469         show_llong_with_suffix(buf, *x, 1000);
470 }
471
472 /* _si, unsigned */
473 void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x)
474 {
475         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
476 }
477
478 void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x)
479 {
480         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
481 }
482
483 void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x)
484 {
485         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
486 }
487