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