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