]> git.ozlabs.org Git - ccan/blob - ccan/opt/helpers.c
tdb2: test: fix run-57-die-during-transaction.c to be more efficient.
[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         if (*l != ll)
262                 return arg_bad("value '%s' does not fit into a long", arg);
263         return NULL;
264 }
265
266 static char * set_ulong_with_suffix(const char *arg, unsigned long *ul, const long base)
267 {
268         long long ll;
269         char *err = set_llong_with_suffix(arg, &ll, base);
270         if (err != NULL)
271                 return err;
272         if (ll < 0)
273                 return arg_bad("'%s' is negative but destination is unsigned", arg);
274         *ul = ll;
275         if (*ul != ll)
276                 return arg_bad("value '%s' does not fit into an unsigned long", arg);
277         return NULL;
278 }
279
280 static char * set_int_with_suffix(const char *arg, int *i, const long base)
281 {
282         long long ll;
283         char *err = set_llong_with_suffix(arg, &ll, base);
284         if (err != NULL) /*an error*/
285                 return err;
286
287         *i = ll;
288         if (*i != ll)
289                 return arg_bad("value '%s' does not fit into an int", arg);
290         return NULL;
291 }
292
293 static char * set_uint_with_suffix(const char *arg, unsigned int *u, const long base)
294 {
295         long long ll;
296         char *err = set_llong_with_suffix(arg, &ll, base);
297         if (err != NULL)
298                 return err;
299         if (ll < 0)
300                 return arg_bad("'%s' is negative but destination is unsigned", arg);
301         *u = ll;
302         if (*u != ll)
303                 return arg_bad("value '%s' does not fit into an unsigned int", arg);
304         return NULL;
305 }
306
307 /*Set an integer, with decimal or binary suffixes.
308   The accepted suffixes are k/K, M/m, G/g, T, P, E.
309
310   The *_bi functions multiply the numeric value by a power of 1024, while the
311   *_si functions multiply by a power of 1000.
312  */
313
314 char * opt_set_ulonglongval_bi(const char *arg, unsigned long long *ll)
315 {
316         return set_ulonglong_with_suffix(arg, ll, 1024);
317 }
318
319 char * opt_set_ulonglongval_si(const char *arg, unsigned long long *ll)
320 {
321         return set_ulonglong_with_suffix(arg, ll, 1000);
322 }
323
324 char * opt_set_longlongval_bi(const char *arg, long long *ll)
325 {
326         return set_llong_with_suffix(arg, ll, 1024);
327 }
328
329 char * opt_set_longlongval_si(const char *arg, long long *ll)
330 {
331         return set_llong_with_suffix(arg, ll, 1000);
332 }
333
334 char * opt_set_longval_bi(const char *arg, long *l)
335 {
336         return set_long_with_suffix(arg, l, 1024);
337 }
338
339 char * opt_set_longval_si(const char *arg, long *l)
340 {
341         return set_long_with_suffix(arg, l, 1000);
342 }
343
344 char * opt_set_ulongval_bi(const char *arg, unsigned long *ul)
345 {
346         return set_ulong_with_suffix(arg, ul, 1024);
347 }
348
349 char * opt_set_ulongval_si(const char *arg, unsigned long *ul)
350 {
351         return set_ulong_with_suffix(arg, ul, 1000);
352 }
353
354 char * opt_set_intval_bi(const char *arg, int *i)
355 {
356         return set_int_with_suffix(arg, i, 1024);
357 }
358
359 char * opt_set_intval_si(const char *arg, int *i)
360 {
361         return set_int_with_suffix(arg, i, 1000);
362 }
363
364 char * opt_set_uintval_bi(const char *arg, unsigned int *u)
365 {
366         return set_uint_with_suffix(arg, u, 1024);
367 }
368
369 char * opt_set_uintval_si(const char *arg, unsigned int *u)
370 {
371         return set_uint_with_suffix(arg, u, 1000);
372 }
373
374 /*static helpers for showing values with kMGTPE suffixes.  In this case there
375   are separate but essentially identical functions for signed and unsigned
376   values, so that unsigned values greater than LLONG_MAX get suffixes.
377  */
378 static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll,
379                                     const long long base)
380 {
381         const char *suffixes = "kMGTPE";
382         int i;
383         if (ll == 0){
384                 /*zero is special because everything divides it (you'd get "0E")*/
385                 snprintf(buf, OPT_SHOW_LEN, "0");
386                 return;
387         }
388         for (i = 0; i < strlen(suffixes); i++){
389                 long long tmp = ll / base;
390                 if (tmp * base != ll)
391                         break;
392                 ll = tmp;
393         }
394         if (i == 0)
395                 snprintf(buf, OPT_SHOW_LEN, "%lld", ll);
396         else
397                 snprintf(buf, OPT_SHOW_LEN, "%lld%c", ll, suffixes[i - 1]);
398 }
399
400 static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull,
401                                     const unsigned base)
402 {
403         const char *suffixes = "kMGTPE";
404         int i;
405         if (ull == 0){
406                 /*zero is special because everything divides it (you'd get "0E")*/
407                 snprintf(buf, OPT_SHOW_LEN, "0");
408                 return;
409         }
410         for (i = 0; i < strlen(suffixes); i++){
411                 unsigned long long tmp = ull / base;
412                 if (tmp * base != ull)
413                         break;
414                 ull = tmp;
415         }
416         if (i == 0)
417                 snprintf(buf, OPT_SHOW_LEN, "%llu", ull);
418         else
419                 snprintf(buf, OPT_SHOW_LEN, "%llu%c", ull, suffixes[i - 1]);
420 }
421
422 /* _bi, signed */
423 void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x)
424 {
425         show_llong_with_suffix(buf, *x, 1024);
426 }
427
428 void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x)
429 {
430         show_llong_with_suffix(buf, *x, 1024);
431 }
432
433 void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x)
434 {
435         show_llong_with_suffix(buf, *x, 1024);
436 }
437
438 /* _bi, unsigned */
439 void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x)
440 {
441         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
442 }
443
444 void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x)
445 {
446         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
447 }
448
449 void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x)
450 {
451         show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
452 }
453
454 /* _si, signed */
455 void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x)
456 {
457         show_llong_with_suffix(buf, (long long) *x, 1000);
458 }
459
460 void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x)
461 {
462         show_llong_with_suffix(buf, (long long) *x, 1000);
463 }
464
465 void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x)
466 {
467         show_llong_with_suffix(buf, *x, 1000);
468 }
469
470 /* _si, unsigned */
471 void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x)
472 {
473         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
474 }
475
476 void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x)
477 {
478         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
479 }
480
481 void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x)
482 {
483         show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
484 }
485