1 /*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 * $Id: convenience.c,v 1.17 2008/04/30 05:58:33 phk Exp $
9 *
10 * Convenience functions for users
11 *
12 */
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <math.h>
18 #include <string.h>
19 #include "configkit.h"
20
21 #include "phk_expr.h"
22
23 static void
quote(CK_ARG,const char * str)24 quote(CK_ARG, const char *str)
25 {
26 const char *p;
27
28 for (p = str; *p; p++) {
29 if (isspace(*p) || *p == '\\' || *p == '"')
30 break;
31 }
32 if (!*p) {
33 ck_printf(CK_PASS, "%s", str);
34 return;
35 }
36 ck_printf(CK_PASS, "\"");
37 for (p = str; *p; p++) {
38 if (*p == '\\')
39 ck_printf(CK_PASS, "\\\\");
40 else if (*p == '\n')
41 ck_printf(CK_PASS, "\\n");
42 else if (*p == '\r')
43 ck_printf(CK_PASS, "\\r");
44 else if (*p == '\t')
45 ck_printf(CK_PASS, "\t");
46 else if (*p == ' ')
47 ck_printf(CK_PASS, " ");
48 else if (*p == '"')
49 ck_printf(CK_PASS, "\\\"");
50 else if (isspace(*p))
51 ck_printf(CK_PASS, "\\%03o", *p);
52 else
53 ck_printf(CK_PASS, "%c", *p);
54 }
55 ck_printf(CK_PASS, "\"");
56 }
57
58
59 int
ck_WordVar(CK_ARG,const char ** arg,char ** var)60 ck_WordVar(CK_ARG, const char **arg, char **var)
61 {
62
63 if (cfa->flag & (CK_SHOW|CK_CONF)) {
64 if (*var == NULL && (cfa->flag & CK_SHOW))
65 ck_printf(CK_PASS, "%s is unset\n", cfa->tree);
66 else if (*var == NULL)
67 ;
68 else {
69 ck_printf(CK_PASS, "%s ", cfa->tree);
70 quote(CK_PASS, *var);
71 ck_printf(CK_PASS, "\n");
72 }
73 return (0);
74 }
75 if (cfa->flag & CK_NO) {
76 if (*var == NULL)
77 return (0);
78 free(*var);
79 *var = NULL;
80 } else {
81 free(*var);
82 *var = strdup(*arg);
83 }
84 return (1);
85 }
86
87 int
ck_UintVar(CK_ARG,unsigned * arg,unsigned * var,unsigned defval)88 ck_UintVar(CK_ARG, unsigned *arg, unsigned *var, unsigned defval)
89 {
90
91 if (cfa->flag & (CK_SHOW|CK_CONF)) {
92 if (*var == defval && (cfa->flag & CK_SHOW))
93 ck_printf(CK_PASS, "%s is unset (%u)\n",
94 cfa->tree, defval);
95 else if (*var == defval)
96 ;
97 else
98 ck_printf(CK_PASS, "%s %u\n", cfa->tree, *var);
99 return (0);
100 }
101 if (cfa->flag & CK_NO) {
102 if (*var == defval)
103 return (0);
104 *var = defval;
105 } else {
106 *var = *arg;
107 }
108 return (1);
109 }
110
111 static int
issame(double a,double b)112 issame(double a, double b)
113 {
114 if (isnan(a) && isnan(b))
115 return (1);
116 if (a == b)
117 return (1);
118 return (0);
119 }
120
121 int
ck_RealVar(CK_ARG,double * arg,double * var,double defval,const char * fmt)122 ck_RealVar(CK_ARG, double *arg, double *var, double defval, const char *fmt)
123 {
124 char fmtbuf[BUFSIZ];
125
126 if (cfa->flag & (CK_SHOW|CK_CONF)) {
127 if (issame(*var, defval) && (cfa->flag & CK_SHOW)) {
128 sprintf(fmtbuf, "%%s is unset (%s)\n", fmt);
129 ck_printf(CK_PASS, fmtbuf, cfa->tree, *var);
130 } else if (issame(*var, defval)) {
131 ;
132 } else {
133 sprintf(fmtbuf, "%%s %s\n", fmt);
134 ck_printf(CK_PASS, fmtbuf, cfa->tree, *var);
135 }
136 return (0);
137 }
138 if (cfa->flag & CK_NO) {
139 if (*var == defval)
140 return (0);
141 *var = defval;
142 } else {
143 *var = *arg;
144 }
145 return (1);
146 }
147
148 int
ck_RealVar2(CK_ARG,const char ** arg,double * var,char ** strvar,double defval,const char * fmt)149 ck_RealVar2(CK_ARG, const char **arg, double *var, char **strvar, double defval, const char *fmt)
150 {
151 char fmtbuf[BUFSIZ];
152 char *ers;
153
154 if (cfa->flag & (CK_SHOW|CK_CONF)) {
155 if (*strvar == NULL && (cfa->flag & CK_SHOW)) {
156 sprintf(fmtbuf, "%%s is unset (%s)\n", fmt);
157 ck_printf(CK_PASS, fmtbuf, cfa->tree, *var);
158 } else if (*strvar == NULL) {
159 ;
160 } else {
161 sprintf(fmtbuf, "%s %s\t# \"%s\"\n",
162 cfa->tree, fmt, *strvar);
163 ck_printf(CK_PASS, fmtbuf, *var);
164 }
165 return (0);
166 }
167 free(*strvar);
168 *strvar = NULL;
169 if (cfa->flag & CK_NO) {
170 if (*var == defval)
171 return (0);
172 *var = defval;
173 } else {
174 *strvar = strdup(*arg);
175 assert(*strvar != NULL);
176 *var = phk_expr(*arg, &ers);
177 if (ers != NULL)
178 ck_printf(CK_PASS, "%s", ers);
179 }
180 return (1);
181 }
182
183 int
ck_BoolKeyVar(CK_ARG,const char ** key,const char * name,unsigned * bits,unsigned bit,unsigned defval)184 ck_BoolKeyVar(CK_ARG, const char **key, const char *name, unsigned *bits, unsigned bit, unsigned defval)
185 {
186
187 if (defval)
188 defval = bit;
189
190 if (key != NULL && strcmp(*key, name))
191 return (0);
192 if (cfa->flag & CK_CONF) {
193 if ((*bits & bit) != defval)
194 ck_printf(CK_PASS, "%s %s\n", cfa->tree, name);
195 return (0);
196 }
197 if (cfa->flag & CK_SHOW) {
198 if ((*bits & bit) != defval)
199 ck_printf(CK_PASS, "%s %s is enabled\n",
200 cfa->tree, name);
201 else
202 ck_printf(CK_PASS, "%s %s is disabled\n",
203 cfa->tree, name);
204 return (0);
205 }
206 if (key == NULL)
207 return (0);
208 if (cfa->flag & CK_NO) {
209 *bits &= ~bit;
210 } else {
211 *bits |= bit;
212 }
213 return (1);
214 }
215
216 int
ck_BoolVar(CK_ARG,unsigned * bits,unsigned bit,unsigned defval)217 ck_BoolVar(CK_ARG, unsigned *bits, unsigned bit, unsigned defval)
218 {
219
220 if (defval)
221 defval = bit;
222
223 if (cfa->flag & CK_CONF) {
224 if ((*bits & bit) != defval)
225 ck_printf(CK_PASS, "%s\n", cfa->tree);
226 return (0);
227 }
228 if (cfa->flag & CK_SHOW) {
229 if ((*bits & bit) != defval)
230 ck_printf(CK_PASS, "%s is enabled\n", cfa->tree);
231 else
232 ck_printf(CK_PASS, "%s is disabled\n", cfa->tree);
233 return (0);
234 }
235 if (cfa->flag & CK_NO) {
236 *bits &= ~bit;
237 } else {
238 *bits |= bit;
239 }
240 return (1);
241 }
242
243