7554c997b252fcf7ceda1c5102a871b08a8fcb04
[ccan] / ccan / opt / helpers.c
1 #include <ccan/opt/opt.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include "private.h"
7
8 /* FIXME: asprintf module? */
9 static char *arg_bad(const char *fmt, const char *arg)
10 {
11         char *str = malloc(strlen(fmt) + strlen(arg));
12         sprintf(str, fmt, arg);
13         return str;
14 }
15
16 char *opt_set_bool(bool *b)
17 {
18         *b = true;
19         return NULL;
20 }
21
22 char *opt_set_invbool(bool *b)
23 {
24         *b = false;
25         return NULL;
26 }
27
28 char *opt_set_bool_arg(const char *arg, bool *b)
29 {
30         if (!strcasecmp(arg, "yes") || !strcasecmp(arg, "true"))
31                 return opt_set_bool(b);
32         if (!strcasecmp(arg, "no") || !strcasecmp(arg, "false"))
33                 return opt_set_invbool(b);
34
35         return opt_invalid_argument(arg);
36 }
37
38 char *opt_set_invbool_arg(const char *arg, bool *b)
39 {
40         char *err = opt_set_bool_arg(arg, b);
41
42         if (!err)
43                 *b = !*b;
44         return err;
45 }
46
47 /* Set a char *. */
48 char *opt_set_charp(const char *arg, char **p)
49 {
50         *p = (char *)arg;
51         return NULL;
52 }
53
54 /* Set an integer value, various forms.  Sets to 1 on arg == NULL. */
55 char *opt_set_intval(const char *arg, int *i)
56 {
57         long l;
58         char *err = opt_set_longval(arg, &l);
59
60         if (err)
61                 return err;
62         *i = l;
63         /* Beware truncation... */
64         if (*i != l)
65                 return arg_bad("value '%s' does not fit into an integer", arg);
66         return err;
67 }
68
69 char *opt_set_uintval(const char *arg, unsigned int *ui)
70 {
71         int i;
72         char *err = opt_set_intval(arg, &i);
73
74         if (err)
75                 return err;
76         if (i < 0)
77                 return arg_bad("'%s' is negative", arg);
78         *ui = i;
79         return NULL;
80 }
81
82 char *opt_set_longval(const char *arg, long *l)
83 {
84         char *endp;
85
86         /* This is how the manpage says to do it.  Yech. */
87         errno = 0;
88         *l = strtol(arg, &endp, 0);
89         if (*endp || !arg[0])
90                 return arg_bad("'%s' is not a number", arg);
91         if (errno == ERANGE)
92                 return arg_bad("'%s' is out of range", arg);
93         if (errno)
94                 return opt_invalid_argument(arg);
95         return NULL;
96 }
97
98 char *opt_set_ulongval(const char *arg, unsigned long *ul)
99 {
100         long int l;
101         char *err;
102         
103         err = opt_set_longval(arg, &l);
104         if (err)
105                 return err;
106         *ul = l;
107         if (l < 0)
108                 return arg_bad("'%s' is negative", arg);
109         return NULL;
110 }
111
112 char *opt_inc_intval(int *i)
113 {
114         (*i)++;
115         return NULL;
116 }
117
118 /* Display version string. */
119 char *opt_show_version_and_exit(const char *version)
120 {
121         printf("%s\n", version);
122         exit(0);
123 }
124
125 char *opt_usage_and_exit(const char *extra)
126 {
127         printf("%s", opt_usage(opt_argv0, extra));
128         exit(0);
129 }