ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/modobject.c
Revision: 2.19
Committed: Sat Oct 17 17:48:46 2020 UTC (4 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.18: +12 -5 lines
Log Message:
fix: added caution around NULL modifier names

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: modobject.c,v 2.18 2020/10/17 16:39:23 greg Exp $";
3 #endif
4 /*
5 * Routines for tracking object modifiers
6 *
7 * External symbols declared in object.h
8 */
9
10 #include "copyright.h"
11
12 #include "standard.h"
13
14 #include "object.h"
15
16 #include "otypes.h"
17
18
19 static struct ohtab {
20 int hsiz; /* current table size */
21 OBJECT *htab; /* table, if allocated */
22 } modtab = {100, NULL}, objtab = {1000, NULL}; /* modifiers and objects */
23
24 static int otndx(char *, struct ohtab *);
25
26
27 OBJECT
28 objndx( /* get object number from pointer */
29 OBJREC *op
30 )
31 {
32 int i, j;
33
34 for (i = nobjects>>OBJBLKSHFT; i >= 0; i--) {
35 j = op - objblock[i];
36 if ((j >= 0) & (j < OBJBLKSIZ))
37 return((i<<OBJBLKSHFT) + j);
38 }
39 return(OVOID);
40 }
41
42
43 OBJECT
44 lastmod( /* find modifier definition before obj */
45 OBJECT obj,
46 char *mname
47 )
48 {
49 OBJREC *op;
50 int i;
51
52 i = modifier(mname); /* try hash table first */
53 if ((obj == OVOID) | (i < obj))
54 return(i);
55 for (i = obj; i-- > 0; ) { /* need to search */
56 op = objptr(i);
57 if (ismodifier(op->otype) && op->oname[0] == mname[0] &&
58 !strcmp(op->oname, mname))
59 return(i);
60 }
61 return(OVOID);
62 }
63
64
65 OBJECT
66 modifier( /* get a modifier number from its name */
67 char *mname
68 )
69 {
70 int ndx;
71
72 ndx = otndx(mname, &modtab);
73 return(modtab.htab[ndx]);
74 }
75
76
77 #ifdef GETOBJ
78 OBJECT
79 object( /* get an object number from its name */
80 char *oname
81 )
82 {
83 int ndx;
84
85 ndx = otndx(oname, &objtab);
86 return(objtab.htab[ndx]);
87 }
88 #endif
89
90
91 int
92 eqreal( /* are two real values close enough to equal? */
93 double d1,
94 double d2
95 )
96 {
97 if (d2 != 0.0)
98 d1 = d1/d2 - 1.0;
99 return((-FTINY <= d1) & (d1 <= FTINY));
100 }
101
102
103 int
104 eqobjects( /* check if two objects are equal */
105 OBJECT obj1,
106 OBJECT obj2
107 )
108 {
109 OBJREC *op1, *op2;
110 int i, n;
111
112 while (obj1 != obj2) {
113 if (obj1 == OVOID)
114 return(0);
115 if (obj2 == OVOID)
116 return(0);
117 op1 = objptr(obj1);
118 op2 = objptr(obj2);
119 if (op1->otype != op2->otype)
120 return(0);
121 if (op1->oargs.nsargs != op2->oargs.nsargs)
122 return(0);
123 if (op1->oargs.nfargs != op2->oargs.nfargs)
124 return(0);
125 #ifdef IARGS
126 if (op1->oargs.niargs != op2->oargs.niargs)
127 return(0);
128 for (i = op1->oargs.niargs; i-- > 0; )
129 if (op1->oargs.iarg[i] != op2->oargs.iarg[i])
130 return(0);
131 #endif
132 for (i = op1->oargs.nfargs; i-- > 0; )
133 if (!eqreal(op1->oargs.farg[i], op2->oargs.farg[i]))
134 return(0);
135 n = 0;
136 switch (op1->otype) { /* special cases (KEEP CONSISTENT!) */
137 case MOD_ALIAS:
138 case MAT_ILLUM:
139 case MAT_MIRROR:
140 n = (op1->oargs.nsargs > 0);
141 break;
142 case MIX_FUNC:
143 case MIX_DATA:
144 case MIX_TEXT:
145 case MIX_PICT:
146 n = 2*(op1->oargs.nsargs >= 2);
147 break;
148 case MAT_CLIP:
149 n = op1->oargs.nsargs;
150 break;
151 }
152 /* check other string arguments */
153 for (i = op1->oargs.nsargs; i-- > n; )
154 if (strcmp(op1->oargs.sarg[i], op2->oargs.sarg[i]))
155 return(0);
156 while (n-- > 0) /* check modifier references */
157 if (!eqobjects( lastmod(obj1, op1->oargs.sarg[n]),
158 lastmod(obj2, op2->oargs.sarg[n]) ))
159 return(0);
160 obj1 = op1->omod;
161 obj2 = op2->omod;
162 }
163 return(1);
164 }
165
166
167 void
168 insertobject( /* insert new object into our list */
169 OBJECT obj
170 )
171 {
172 int i;
173
174 if (ismodifier(objptr(obj)->otype)) {
175 i = otndx(objptr(obj)->oname, &modtab);
176 if (eqobjects(obj, modtab.htab[i]))
177 return; /* don't index if same as earlier def. */
178 modtab.htab[i] = obj;
179 }
180 #ifdef GETOBJ
181 else {
182 i = otndx(objptr(obj)->oname, &objtab);
183 objtab.htab[i] = obj;
184 }
185 #endif
186 for (i = 0; addobjnotify[i] != NULL; i++)
187 (*addobjnotify[i])(obj);
188 }
189
190
191 void
192 truncobjndx(void) /* remove bogus table entries past end */
193 {
194 int ndx;
195
196 if (nobjects <= 0) {
197 if (modtab.htab != NULL) {
198 free((void *)modtab.htab);
199 modtab.htab = NULL;
200 modtab.hsiz = 100;
201 }
202 if (objtab.htab != NULL) {
203 free((void *)objtab.htab);
204 objtab.htab = NULL;
205 objtab.hsiz = 100;
206 }
207 return;
208 }
209 for (ndx = modtab.hsiz*(modtab.htab != NULL); ndx--; )
210 if (modtab.htab[ndx] >= nobjects)
211 modtab.htab[ndx] = OVOID;
212
213 for (ndx = objtab.hsiz*(objtab.htab != NULL); ndx--; )
214 if (objtab.htab[ndx] >= nobjects)
215 objtab.htab[ndx] = OVOID;
216 }
217
218
219 static int
220 nexthsiz( /* return next hash table size */
221 int oldsiz
222 )
223 {
224 static int hsiztab[] = {
225 251, 509, 1021, 2039, 4093, 8191, 16381,
226 32749, 65521, 131071, 262139, 0
227 };
228 int *hsp;
229
230 for (hsp = hsiztab; *hsp; hsp++)
231 if (*hsp > oldsiz)
232 return(*hsp);
233 return(oldsiz*2 + 1); /* not always prime */
234 }
235
236
237 static int
238 otndx( /* get object table index for name */
239 char *name,
240 struct ohtab *tab
241 )
242 {
243 char *onm;
244 OBJECT *oldhtab;
245 int hval, i;
246 int ndx;
247
248 if (tab->htab == NULL) { /* new table */
249 tab->hsiz = nexthsiz(tab->hsiz);
250 tab->htab = (OBJECT *)malloc(tab->hsiz*sizeof(OBJECT));
251 if (tab->htab == NULL)
252 error(SYSTEM, "out of memory in otndx");
253 ndx = tab->hsiz;
254 while (ndx--) /* empty it */
255 tab->htab[ndx] = OVOID;
256 }
257 /* look up object */
258 hval = shash(name);
259 tryagain:
260 for (i = 0; i < tab->hsiz; i++) {
261 ndx = (hval + (unsigned long)i*i) % tab->hsiz;
262 if (tab->htab[ndx] == OVOID)
263 return(ndx);
264 onm = objptr(tab->htab[ndx])->oname;
265 if (onm != NULL && !strcmp(onm, name))
266 return(ndx);
267 }
268 /* table is full, reallocate */
269 oldhtab = tab->htab;
270 ndx = tab->hsiz;
271 tab->htab = NULL;
272 while (ndx--)
273 if (oldhtab[ndx] != OVOID) {
274 onm = objptr(oldhtab[ndx])->oname;
275 if (onm == NULL)
276 continue;
277 i = otndx(onm, tab);
278 tab->htab[i] = oldhtab[ndx];
279 }
280 free((void *)oldhtab);
281 goto tryagain; /* should happen only once! */
282 }