ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/readobj.c
Revision: 2.25
Committed: Tue Feb 7 20:28:16 2023 UTC (14 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.24: +8 -1 lines
Log Message:
perf: added calls to flockfile()/funlockfile() for more efficient reading

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: readobj.c,v 2.24 2020/10/17 16:39:23 greg Exp $";
3 #endif
4 /*
5 * readobj.c - routines for reading in object descriptions.
6 *
7 * External symbols declared in object.h
8 */
9
10 #include "copyright.h"
11
12 #include <ctype.h>
13 #include <string.h>
14 #include <stdio.h>
15
16 #include "platform.h"
17 #include "paths.h"
18 #include "standard.h"
19 #include "object.h"
20 #include "otypes.h"
21
22
23 OBJREC *objblock[MAXOBJBLK]; /* our objects */
24 OBJECT nobjects = 0; /* # of objects */
25
26
27 void
28 readobj( /* read in an object file or stream */
29 char *inpspec
30 )
31 {
32 OBJECT lastobj;
33 FILE *infp;
34 char buf[2048];
35 int c;
36
37 lastobj = nobjects;
38 if (inpspec == NULL) {
39 infp = stdin;
40 inpspec = "standard input";
41 } else if (inpspec[0] == '!') {
42 if ((infp = popen(inpspec+1, "r")) == NULL) {
43 sprintf(errmsg, "cannot execute \"%s\"", inpspec);
44 error(SYSTEM, errmsg);
45 }
46 } else if ((infp = fopen(inpspec, "r")) == NULL) {
47 sprintf(errmsg, "cannot open scene file \"%s\"", inpspec);
48 error(SYSTEM, errmsg);
49 }
50 #ifdef getc_unlocked /* avoid stupid semaphores */
51 flockfile(infp);
52 #endif
53 while ((c = getc(infp)) != EOF) {
54 if (isspace(c))
55 continue;
56 if (c == '#') { /* comment */
57 fgets(buf, sizeof(buf), infp);
58 } else if (c == '!') { /* command */
59 ungetc(c, infp);
60 fgetline(buf, sizeof(buf), infp);
61 readobj(buf);
62 } else { /* object */
63 ungetc(c, infp);
64 getobject(inpspec, infp);
65 }
66 }
67 if (inpspec[0] == '!')
68 pclose(infp);
69 else if (infp != stdin)
70 fclose(infp);
71 #ifdef getc_unlocked
72 else
73 funlockfile(infp);
74 #endif
75 if (nobjects == lastobj) {
76 sprintf(errmsg, "(%s): empty file", inpspec);
77 error(WARNING, errmsg);
78 }
79 }
80
81
82 void
83 getobject( /* read the next object */
84 char *name,
85 FILE *fp
86 )
87 {
88 #define OALIAS -2
89 OBJECT obj;
90 char sbuf[MAXSTR];
91 int rval;
92 OBJREC *objp;
93
94 if ((obj = newobject()) == OVOID)
95 error(SYSTEM, "out of object space");
96 objp = objptr(obj);
97 /* get modifier */
98 strcpy(sbuf, "EOF");
99 fgetword(sbuf, MAXSTR, fp);
100 if (strchr(sbuf, '\t')) {
101 sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"",
102 name, sbuf);
103 error(USER, errmsg);
104 }
105 if (!strcmp(sbuf, VOIDID))
106 objp->omod = OVOID;
107 else if (!strcmp(sbuf, ALIASMOD))
108 objp->omod = OALIAS;
109 else if ((objp->omod = modifier(sbuf)) == OVOID) {
110 sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf);
111 error(USER, errmsg);
112 }
113 /* get type */
114 strcpy(sbuf, "EOF");
115 fgetword(sbuf, MAXSTR, fp);
116 if ((objp->otype = otype(sbuf)) < 0) {
117 sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf);
118 error(USER, errmsg);
119 }
120 /* get identifier */
121 sbuf[0] = '\0';
122 fgetword(sbuf, MAXSTR, fp);
123 if (strchr(sbuf, '\t')) {
124 sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"",
125 name, sbuf);
126 error(USER, errmsg);
127 }
128 objp->oname = savqstr(sbuf);
129 /* get arguments */
130 if (objp->otype == MOD_ALIAS) {
131 OBJECT alias;
132 strcpy(sbuf, "EOF");
133 fgetword(sbuf, MAXSTR, fp);
134 if ((alias = modifier(sbuf)) == OVOID) {
135 sprintf(errmsg, "(%s): bad reference \"%s\"",
136 name, sbuf);
137 objerror(objp, USER, errmsg);
138 }
139 if (objp->omod == OALIAS ||
140 objp->omod == objptr(alias)->omod) {
141 objp->omod = alias;
142 } else {
143 objp->oargs.sarg = (char **)malloc(sizeof(char *));
144 if (objp->oargs.sarg == NULL)
145 error(SYSTEM, "out of memory in getobject");
146 objp->oargs.nsargs = 1;
147 objp->oargs.sarg[0] = savestr(sbuf);
148 }
149 } else if ((rval = readfargs(&objp->oargs, fp)) == 0) {
150 sprintf(errmsg, "(%s): bad arguments", name);
151 objerror(objp, USER, errmsg);
152 } else if (rval < 0) {
153 sprintf(errmsg, "(%s): error reading scene", name);
154 error(SYSTEM, errmsg);
155 }
156 if (objp->omod == OALIAS) {
157 sprintf(errmsg, "(%s): inappropriate use of '%s' modifier",
158 name, ALIASMOD);
159 objerror(objp, USER, errmsg);
160 }
161 /* initialize */
162 objp->os = NULL;
163
164 insertobject(obj); /* add to global structure */
165 #undef OALIAS
166 }
167
168
169 OBJECT
170 newobject(void) /* get a new object */
171 {
172 int i;
173
174 if ((nobjects & (OBJBLKSIZ-1)) == 0) { /* new block */
175 errno = 0;
176 i = nobjects >> OBJBLKSHFT;
177 if (i >= MAXOBJBLK)
178 return(OVOID);
179 objblock[i] = (OBJREC *)calloc(OBJBLKSIZ, sizeof(OBJREC));
180 if (objblock[i] == NULL)
181 return(OVOID);
182 }
183 return(nobjects++);
184 }
185
186 void
187 freeobjects( /* free a range of objects */
188 int firstobj,
189 int nobjs
190 )
191 {
192 int obj;
193 /* check bounds */
194 if (firstobj < 0)
195 return;
196 if (nobjs <= 0)
197 return;
198 if (firstobj + nobjs > nobjects)
199 return;
200 /* clear objects */
201 for (obj = firstobj+nobjs; obj-- > firstobj; ) {
202 OBJREC *o = objptr(obj);
203 free_os(o); /* free client memory */
204 freeqstr(o->oname);
205 freefargs(&o->oargs);
206 memset((void *)o, '\0', sizeof(OBJREC));
207 }
208 /* free objects off end */
209 for (obj = nobjects; obj-- > 0; )
210 if (objptr(obj)->oname != NULL)
211 break;
212 if (++obj >= nobjects)
213 return;
214 while (nobjects > obj) /* free empty end blocks */
215 if ((--nobjects & (OBJBLKSIZ-1)) == 0) {
216 int i = nobjects >> OBJBLKSHFT;
217 free((void *)objblock[i]);
218 objblock[i] = NULL;
219 }
220 truncobjndx(); /* truncate modifier look-up */
221 }