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