ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/loadvars.c
Revision: 2.19
Committed: Fri Jun 9 22:52:47 2023 UTC (11 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.18: +12 -5 lines
Log Message:
fix: Preserve spaces in quoted strings

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: loadvars.c,v 2.18 2023/06/05 16:32:42 greg Exp $";
3 #endif
4 /*
5 * Routines for loading and checking variables from file.
6 */
7
8 #include "copyright.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13
14 #include "standard.h"
15 #include "vars.h"
16
17 #define NOCHAR 127 /* constant for character to delete */
18
19 extern char *fgetline();
20
21
22 void
23 loadvars( /* load variables into vv from file */
24 const char *rfname
25 )
26 {
27 FILE *fp;
28 char buf[512];
29 char *cp;
30
31 if (rfname == NULL)
32 fp = stdin;
33 else if ((fp = fopen(rfname, "r")) == NULL) {
34 perror(rfname);
35 quit(1);
36 }
37 while (fgetline(buf, sizeof(buf), fp) != NULL) {
38 for (cp = buf; *cp; cp++) {
39 switch (*cp) {
40 case '\\':
41 *cp++ = NOCHAR;
42 continue;
43 case '#':
44 *cp = '\0';
45 break;
46 default:
47 continue;
48 }
49 break;
50 }
51 if (setvariable(buf, matchvar) < 0) {
52 fprintf(stderr, "%s: unknown variable: %s\n",
53 rfname, buf);
54 quit(1);
55 }
56 }
57 if (fp != stdin)
58 fclose(fp);
59 }
60
61
62 int
63 setvariable( /* assign variable according to string */
64 const char *ass,
65 VARIABLE *(*mv)(const char*)
66 )
67 {
68 int quote = '\0';
69 char varname[32];
70 int n;
71 char *cp;
72 VARIABLE *vp;
73 int i;
74
75 while (isspace(*ass)) /* skip leading space */
76 ass++;
77 cp = varname; /* extract name */
78 while (cp < varname+sizeof(varname)-1
79 && *ass && !isspace(*ass) && *ass != '=')
80 *cp++ = *ass++;
81 *cp = '\0';
82 if (!varname[0])
83 return(0); /* no variable name! */
84 /* trim value */
85 while (isspace(*ass) || *ass == '=')
86 ass++;
87 for (n = strlen(ass); n > 0; n--)
88 if (!isspace(ass[n-1]))
89 break;
90 if (!n)
91 return(0); /* no assignment */
92 /* match variable from list */
93 vp = (*mv)(varname);
94 if (vp == NULL)
95 return(-1);
96 /* assign new value */
97 if ( (i = vp->nass) ) {
98 cp = vp->value;
99 while (i--)
100 while (*cp++)
101 ;
102 i = cp - vp->value;
103 vp->value = (char *)realloc((void *)vp->value, i+n+1);
104 } else
105 vp->value = (char *)malloc(n+1);
106 if (vp->value == NULL) {
107 perror(progname);
108 quit(1);
109 }
110 cp = vp->value+i; /* copy value */
111 *cp = *ass;
112 for (i = 1; i <= n; i++) {
113 if (ass[i] == NOCHAR)
114 continue;
115 if (quote) { /* don't change quoted parts */
116 quote *= (ass[i] != quote);
117 } else { /* otherwise, squeeze spaces */
118 if (isspace(*cp))
119 while (isspace(ass[i]))
120 i++;
121 if ((ass[i] == '"') | (ass[i] == '\''))
122 quote = ass[i];
123 }
124 *++cp = ass[i];
125 }
126 if (isspace(*cp)) /* remove trailing space */
127 *cp = '\0';
128 return(++vp->nass);
129 }
130
131
132 VARIABLE *
133 matchvar( /* match a variable by its name */
134 const char *nam
135 )
136 {
137 int n = strlen(nam);
138 int i;
139
140 for (i = 0; i < NVARS; i++)
141 if (n >= vv[i].nick && !strncmp(nam, vv[i].name, n))
142 return(vv+i);
143 return(NULL);
144 }
145
146
147 char *
148 nvalue( /* return nth variable value */
149 int vn,
150 int n
151 )
152 {
153 char *cp;
154
155 if ((vval(vn) == NULL) | (n < 0) | (n >= vdef(vn)))
156 return(NULL);
157 cp = vval(vn);
158 while (n--)
159 while (*cp++)
160 ;
161 return(cp);
162 }
163
164
165 void
166 checkvalues(void) /* check assignments */
167 {
168 int i;
169
170 for (i = 0; i < NVARS; i++)
171 if (vv[i].fixval != NULL)
172 (*vv[i].fixval)(vv+i);
173 }
174
175
176 void
177 onevalue( /* only one assignment for this variable */
178 VARIABLE *vp
179 )
180 {
181 if (vp->nass < 2)
182 return;
183 if (!nowarn)
184 fprintf(stderr,
185 "%s: warning - multiple assignment of variable '%s'\n",
186 progname, vp->name);
187 do
188 vp->value += strlen(vp->value)+1;
189 while (--vp->nass > 1);
190 }
191
192
193 void
194 catvalues( /* concatenate variable values */
195 VARIABLE *vp
196 )
197 {
198 char *cp;
199
200 if (vp->nass < 2)
201 return;
202 for (cp = vp->value; vp->nass > 1; vp->nass--) {
203 while (*cp)
204 cp++;
205 *cp++ = ' ';
206 }
207 }
208
209
210 int
211 badmatch( /* case insensitive truncated comparison */
212 char *tv,
213 char *cv
214 )
215 {
216 if (!*tv) return(1); /* null string cannot match */
217 do
218 if (UPPER(*tv) != *cv++)
219 return(1);
220 while (*++tv);
221 return(0); /* OK */
222 }
223
224
225 void
226 boolvalue( /* check boolean for legal values */
227 VARIABLE *vp
228 )
229 {
230 if (!vp->nass) return;
231 onevalue(vp);
232 switch (UPPER(vp->value[0])) {
233 case 'T':
234 if (badmatch(vp->value, "TRUE")) break;
235 return;
236 case 'F':
237 if (badmatch(vp->value, "FALSE")) break;
238 return;
239 }
240 fprintf(stderr, "%s: illegal value for boolean variable '%s'\n",
241 progname, vp->name);
242 quit(1);
243 }
244
245
246 void
247 qualvalue( /* check qualitative var. for legal values */
248 VARIABLE *vp
249 )
250 {
251 if (!vp->nass) return;
252 onevalue(vp);
253 switch (UPPER(vp->value[0])) {
254 case 'L':
255 if (badmatch(vp->value, "LOW")) break;
256 return;
257 case 'M':
258 if (badmatch(vp->value, "MEDIUM")) break;
259 return;
260 case 'H':
261 if (badmatch(vp->value, "HIGH")) break;
262 return;
263 }
264 fprintf(stderr, "%s: illegal value for qualitative variable '%s'\n",
265 progname, vp->name);
266 quit(1);
267 }
268
269
270 void
271 intvalue( /* check integer variable for legal values */
272 VARIABLE *vp
273 )
274 {
275 if (!vp->nass) return;
276 onevalue(vp);
277 if (isint(vp->value)) return;
278 fprintf(stderr, "%s: illegal value for integer variable '%s'\n",
279 progname, vp->name);
280 quit(1);
281 }
282
283
284 void
285 fltvalue( /* check float variable for legal values */
286 VARIABLE *vp
287 )
288 {
289 if (!vp->nass) return;
290 onevalue(vp);
291 if (isflt(vp->value)) return;
292 fprintf(stderr, "%s: illegal value for real variable '%s'\n",
293 progname, vp->name);
294 quit(1);
295 }
296
297
298 void
299 printvars( /* print variable values */
300 FILE *fp
301 )
302 {
303 int i, j, k, clipline;
304 char *cp;
305
306 for (i = 0; i < NVARS; i++) /* print each variable */
307 for (j = 0; j < vdef(i); j++) { /* print each assignment */
308 fputs(vnam(i), fp);
309 fputs("= ", fp);
310 k = clipline = ( vv[i].fixval == catvalues ? 64 : 236 )
311 - strlen(vnam(i)) ;
312 cp = nvalue(i, j);
313 while (*cp) {
314 putc(*cp++, fp);
315 if (--k <= 0) { /* line too long */
316 while (*cp && !isspace(*cp))
317 fputc(*cp++, fp); /* finish this word */
318 if (*cp) { /* start new line */
319 if (vv[i].fixval == catvalues) {
320 fputc('\n', fp);
321 fputs(vnam(i), fp);
322 fputc('=', fp);
323 } else
324 fputs(" \\\n", fp);
325 k = clipline;
326 }
327 }
328 }
329 fputc('\n', fp);
330 }
331 fflush(fp);
332 }