ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/loadvars.c
Revision: 2.21
Committed: Sat Jun 10 20:20:51 2023 UTC (10 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.20: +2 -2 lines
Log Message:
fix: Now squeezes unquoted spaces across escaped newlines

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: loadvars.c,v 2.20 2023/06/10 15:49:55 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])|(ass[i]==NOCHAR))
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 void
270 strvalue( /* check for single (quoted) string value */
271 VARIABLE *vp
272 )
273 {
274 if (!vp->nass) return;
275 onevalue(vp);
276 if ((vp->value[0] == '"') | (vp->value[0] == '\'')) {
277 char *cp = vp->value + strlen(vp->value+1);
278 if ((cp != vp->value) & (*cp == vp->value[0])) {
279 vp->value++; /* elide quotation marks */
280 *cp = '\0';
281 }
282 }
283 }
284
285
286 void
287 intvalue( /* check integer variable for legal values */
288 VARIABLE *vp
289 )
290 {
291 if (!vp->nass) return;
292 onevalue(vp);
293 if (isint(vp->value)) return;
294 fprintf(stderr, "%s: illegal value for integer variable '%s'\n",
295 progname, vp->name);
296 quit(1);
297 }
298
299
300 void
301 fltvalue( /* check float variable for legal values */
302 VARIABLE *vp
303 )
304 {
305 if (!vp->nass) return;
306 onevalue(vp);
307 if (isflt(vp->value)) return;
308 fprintf(stderr, "%s: illegal value for real variable '%s'\n",
309 progname, vp->name);
310 quit(1);
311 }
312
313
314 void
315 printvars( /* print variable values */
316 FILE *fp
317 )
318 {
319 int i, j, k, clipline;
320 char *cp;
321
322 for (i = 0; i < NVARS; i++) /* print each variable */
323 for (j = 0; j < vdef(i); j++) { /* print each assignment */
324 fputs(vnam(i), fp);
325 fputs("= ", fp);
326 k = clipline = ( vv[i].fixval == catvalues ? 64 : 236 )
327 - strlen(vnam(i)) ;
328 cp = nvalue(i, j);
329 while (*cp) {
330 putc(*cp++, fp);
331 if (--k <= 0) { /* line too long */
332 while (*cp && !isspace(*cp))
333 fputc(*cp++, fp); /* finish this word */
334 if (*cp) { /* start new line */
335 if (vv[i].fixval == catvalues) {
336 fputc('\n', fp);
337 fputs(vnam(i), fp);
338 fputc('=', fp);
339 } else
340 fputs(" \\\n", fp);
341 k = clipline;
342 }
343 }
344 }
345 fputc('\n', fp);
346 }
347 fflush(fp);
348 }