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 (11 months 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.21 static const char RCSid[] = "$Id: loadvars.c,v 2.20 2023/06/10 15:49:55 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Routines for loading and checking variables from file.
6     */
7    
8 greg 2.10 #include "copyright.h"
9 greg 2.9
10 greg 2.1 #include <stdio.h>
11 greg 2.9 #include <stdlib.h>
12 greg 2.1 #include <ctype.h>
13 schorsch 2.12
14     #include "standard.h"
15 greg 2.1 #include "vars.h"
16    
17     #define NOCHAR 127 /* constant for character to delete */
18    
19 greg 2.4 extern char *fgetline();
20    
21 greg 2.1
22 greg 2.9 void
23 greg 2.15 loadvars( /* load variables into vv from file */
24 greg 2.17 const char *rfname
25 greg 2.15 )
26 greg 2.1 {
27     FILE *fp;
28     char buf[512];
29 greg 2.15 char *cp;
30 greg 2.1
31     if (rfname == NULL)
32     fp = stdin;
33     else if ((fp = fopen(rfname, "r")) == NULL) {
34     perror(rfname);
35 greg 2.5 quit(1);
36 greg 2.1 }
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 greg 2.6 if (setvariable(buf, matchvar) < 0) {
52     fprintf(stderr, "%s: unknown variable: %s\n",
53     rfname, buf);
54     quit(1);
55     }
56 greg 2.1 }
57 greg 2.16 if (fp != stdin)
58     fclose(fp);
59 greg 2.1 }
60    
61    
62 greg 2.6 int
63 greg 2.15 setvariable( /* assign variable according to string */
64 greg 2.17 const char *ass,
65 greg 2.18 VARIABLE *(*mv)(const char*)
66 greg 2.15 )
67 greg 2.1 {
68 greg 2.19 int quote = '\0';
69 greg 2.1 char varname[32];
70     int n;
71 greg 2.15 char *cp;
72     VARIABLE *vp;
73     int i;
74 greg 2.1
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 greg 2.6 return(0); /* no variable name! */
84 greg 2.1 /* 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 greg 2.6 if (!n)
91     return(0); /* no assignment */
92 greg 2.1 /* match variable from list */
93 greg 2.6 vp = (*mv)(varname);
94     if (vp == NULL)
95     return(-1);
96 greg 2.1 /* assign new value */
97 schorsch 2.13 if ( (i = vp->nass) ) {
98 greg 2.1 cp = vp->value;
99     while (i--)
100     while (*cp++)
101     ;
102     i = cp - vp->value;
103 greg 2.11 vp->value = (char *)realloc((void *)vp->value, i+n+1);
104 greg 2.1 } else
105 greg 2.9 vp->value = (char *)malloc(n+1);
106 greg 2.1 if (vp->value == NULL) {
107     perror(progname);
108 greg 2.5 quit(1);
109 greg 2.1 }
110 greg 2.19 cp = vp->value+i; /* copy value */
111 greg 2.1 *cp = *ass;
112     for (i = 1; i <= n; i++) {
113     if (ass[i] == NOCHAR)
114     continue;
115 greg 2.19 if (quote) { /* don't change quoted parts */
116     quote *= (ass[i] != quote);
117     } else { /* otherwise, squeeze spaces */
118     if (isspace(*cp))
119 greg 2.21 while (isspace(ass[i])|(ass[i]==NOCHAR))
120 greg 2.19 i++;
121     if ((ass[i] == '"') | (ass[i] == '\''))
122     quote = ass[i];
123     }
124 greg 2.1 *++cp = ass[i];
125     }
126     if (isspace(*cp)) /* remove trailing space */
127     *cp = '\0';
128 greg 2.6 return(++vp->nass);
129 greg 2.1 }
130    
131    
132     VARIABLE *
133 greg 2.15 matchvar( /* match a variable by its name */
134 greg 2.17 const char *nam
135 greg 2.15 )
136 greg 2.1 {
137     int n = strlen(nam);
138 greg 2.15 int i;
139 greg 2.1
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 greg 2.15 nvalue( /* return nth variable value */
149     int vn,
150     int n
151     )
152 greg 2.1 {
153 greg 2.15 char *cp;
154 greg 2.1
155 schorsch 2.13 if ((vval(vn) == NULL) | (n < 0) | (n >= vdef(vn)))
156 greg 2.1 return(NULL);
157 greg 2.2 cp = vval(vn);
158 greg 2.1 while (n--)
159     while (*cp++)
160     ;
161     return(cp);
162     }
163    
164    
165 greg 2.9 void
166 greg 2.15 checkvalues(void) /* check assignments */
167 greg 2.1 {
168 greg 2.15 int i;
169 greg 2.1
170     for (i = 0; i < NVARS; i++)
171     if (vv[i].fixval != NULL)
172     (*vv[i].fixval)(vv+i);
173     }
174    
175    
176 greg 2.9 void
177 greg 2.15 onevalue( /* only one assignment for this variable */
178     VARIABLE *vp
179     )
180 greg 2.1 {
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 greg 2.9 void
194 greg 2.15 catvalues( /* concatenate variable values */
195     VARIABLE *vp
196     )
197 greg 2.1 {
198 greg 2.15 char *cp;
199 greg 2.1
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 greg 2.15 badmatch( /* case insensitive truncated comparison */
212     char *tv,
213     char *cv
214     )
215 greg 2.1 {
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 greg 2.9 void
226 greg 2.15 boolvalue( /* check boolean for legal values */
227     VARIABLE *vp
228     )
229 greg 2.1 {
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 greg 2.5 quit(1);
243 greg 2.1 }
244    
245    
246 greg 2.9 void
247 greg 2.15 qualvalue( /* check qualitative var. for legal values */
248     VARIABLE *vp
249     )
250 greg 2.1 {
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 greg 2.5 quit(1);
267 greg 2.1 }
268    
269 greg 2.20 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 greg 2.1
286 greg 2.9 void
287 greg 2.15 intvalue( /* check integer variable for legal values */
288     VARIABLE *vp
289     )
290 greg 2.1 {
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 greg 2.5 quit(1);
297 greg 2.1 }
298    
299    
300 greg 2.9 void
301 greg 2.15 fltvalue( /* check float variable for legal values */
302     VARIABLE *vp
303     )
304 greg 2.1 {
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 greg 2.5 quit(1);
311 greg 2.1 }
312    
313    
314 greg 2.9 void
315 greg 2.15 printvars( /* print variable values */
316     FILE *fp
317     )
318 greg 2.1 {
319     int i, j, k, clipline;
320 greg 2.15 char *cp;
321 greg 2.1
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 gwlarson 2.8 k = clipline = ( vv[i].fixval == catvalues ? 64 : 236 )
327 greg 2.1 - strlen(vnam(i)) ;
328 greg 2.2 cp = nvalue(i, j);
329 greg 2.1 while (*cp) {
330     putc(*cp++, fp);
331     if (--k <= 0) { /* line too long */
332     while (*cp && !isspace(*cp))
333 gwlarson 2.7 fputc(*cp++, fp); /* finish this word */
334 greg 2.1 if (*cp) { /* start new line */
335 gwlarson 2.7 if (vv[i].fixval == catvalues) {
336     fputc('\n', fp);
337     fputs(vnam(i), fp);
338     fputc('=', fp);
339     } else
340     fputs(" \\\n", fp);
341 greg 2.1 k = clipline;
342     }
343     }
344     }
345 gwlarson 2.7 fputc('\n', fp);
346 greg 2.1 }
347     fflush(fp);
348     }