ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/modobject.c
Revision: 2.18
Committed: Sat Oct 17 16:39:23 2020 UTC (3 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.17: +23 -11 lines
Log Message:
fix: freeing *some* objects now preserves valid modifier lookups

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.18 static const char RCSid[] = "$Id: modobject.c,v 2.17 2013/12/09 18:17:13 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * Routines for tracking object modifiers
6 greg 2.7 *
7     * External symbols declared in object.h
8     */
9    
10 greg 2.8 #include "copyright.h"
11 greg 1.1
12     #include "standard.h"
13    
14     #include "object.h"
15    
16 greg 1.2 #include "otypes.h"
17    
18 greg 1.1
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 schorsch 2.10 static int otndx(char *, struct ohtab *);
25 greg 1.3
26 greg 1.1
27 greg 2.9 OBJECT
28 greg 2.13 objndx( /* get object number from pointer */
29     OBJREC *op
30     )
31 greg 1.1 {
32 greg 2.13 int i, j;
33 greg 1.1
34 gwlarson 2.6 for (i = nobjects>>OBJBLKSHFT; i >= 0; i--) {
35 greg 2.3 j = op - objblock[i];
36 greg 2.12 if ((j >= 0) & (j < OBJBLKSIZ))
37 gwlarson 2.6 return((i<<OBJBLKSHFT) + j);
38 greg 2.3 }
39     return(OVOID);
40 greg 1.1 }
41    
42    
43 greg 2.9 OBJECT
44 greg 2.13 lastmod( /* find modifier definition before obj */
45     OBJECT obj,
46     char *mname
47     )
48 greg 2.3 {
49 greg 2.13 OBJREC *op;
50     int i;
51 greg 2.3
52 greg 2.4 i = modifier(mname); /* try hash table first */
53 greg 2.12 if ((obj == OVOID) | (i < obj))
54 greg 2.4 return(i);
55     for (i = obj; i-- > 0; ) { /* need to search */
56 greg 2.3 op = objptr(i);
57 greg 2.13 if (ismodifier(op->otype) && op->oname[0] == mname[0] &&
58     !strcmp(op->oname, mname))
59 greg 2.3 return(i);
60     }
61     return(OVOID);
62     }
63    
64    
65 greg 2.9 OBJECT
66 greg 2.13 modifier( /* get a modifier number from its name */
67     char *mname
68     )
69 greg 1.1 {
70 greg 2.13 int ndx;
71 greg 1.1
72     ndx = otndx(mname, &modtab);
73     return(modtab.htab[ndx]);
74     }
75    
76    
77 greg 2.3 #ifdef GETOBJ
78 greg 2.9 OBJECT
79 greg 2.13 object( /* get an object number from its name */
80     char *oname
81     )
82 greg 2.3 {
83 greg 2.13 int ndx;
84 greg 2.3
85     ndx = otndx(oname, &objtab);
86     return(objtab.htab[ndx]);
87     }
88     #endif
89    
90    
91 greg 2.15 int
92 greg 2.14 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 greg 2.17 int i, n;
111 greg 2.14
112 greg 2.15 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 greg 2.14 #ifdef IARGS
126 greg 2.15 if (op1->oargs.niargs != op2->oargs.niargs)
127 greg 2.14 return(0);
128 greg 2.15 for (i = op1->oargs.niargs; i-- > 0; )
129     if (op1->oargs.iarg[i] != op2->oargs.iarg[i])
130     return(0);
131 greg 2.14 #endif
132 greg 2.15 for (i = op1->oargs.nfargs; i-- > 0; )
133     if (!eqreal(op1->oargs.farg[i], op2->oargs.farg[i]))
134     return(0);
135 greg 2.17 n = 0;
136 greg 2.16 switch (op1->otype) { /* special cases (KEEP CONSISTENT!) */
137     case MOD_ALIAS:
138     case MAT_ILLUM:
139     case MAT_MIRROR:
140 greg 2.17 n = (op1->oargs.nsargs > 0);
141 greg 2.16 break;
142     case MIX_FUNC:
143     case MIX_DATA:
144     case MIX_TEXT:
145     case MIX_PICT:
146 greg 2.17 n = 2*(op1->oargs.nsargs >= 2);
147 greg 2.16 break;
148     case MAT_CLIP:
149 greg 2.17 n = op1->oargs.nsargs;
150 greg 2.16 break;
151     }
152 greg 2.17 /* 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 greg 2.16 return(0);
160 greg 2.15 obj1 = op1->omod;
161     obj2 = op2->omod;
162     }
163 greg 2.14 return(1);
164     }
165    
166    
167 greg 2.7 void
168 greg 2.13 insertobject( /* insert new object into our list */
169     OBJECT obj
170     )
171 greg 1.1 {
172 greg 2.13 int i;
173 greg 1.1
174     if (ismodifier(objptr(obj)->otype)) {
175     i = otndx(objptr(obj)->oname, &modtab);
176 greg 2.14 if (eqobjects(obj, modtab.htab[i]))
177 greg 2.16 return; /* don't index if same as earlier def. */
178 greg 1.1 modtab.htab[i] = obj;
179     }
180 greg 2.3 #ifdef GETOBJ
181     else {
182     i = otndx(objptr(obj)->oname, &objtab);
183     objtab.htab[i] = obj;
184     }
185     #endif
186 greg 1.1 for (i = 0; addobjnotify[i] != NULL; i++)
187     (*addobjnotify[i])(obj);
188     }
189    
190    
191 greg 2.7 void
192 greg 2.18 truncobjndx(void) /* remove bogus table entries past end */
193 greg 2.7 {
194 greg 2.18 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 greg 2.7 }
209 greg 2.18 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 greg 2.7 }
217    
218    
219 greg 1.1 static int
220 greg 2.13 nexthsiz( /* return next hash table size */
221     int oldsiz
222     )
223 greg 1.1 {
224     static int hsiztab[] = {
225     251, 509, 1021, 2039, 4093, 8191, 16381, 0
226     };
227 greg 2.13 int *hsp;
228 greg 1.1
229     for (hsp = hsiztab; *hsp; hsp++)
230     if (*hsp > oldsiz)
231     return(*hsp);
232     return(oldsiz*2 + 1); /* not always prime */
233     }
234    
235    
236     static int
237 greg 2.13 otndx( /* get object table index for name */
238     char *name,
239     struct ohtab *tab
240     )
241 greg 1.1 {
242     OBJECT *oldhtab;
243     int hval, i;
244 greg 2.13 int ndx;
245 greg 1.1
246     if (tab->htab == NULL) { /* new table */
247     tab->hsiz = nexthsiz(tab->hsiz);
248     tab->htab = (OBJECT *)malloc(tab->hsiz*sizeof(OBJECT));
249     if (tab->htab == NULL)
250     error(SYSTEM, "out of memory in otndx");
251     ndx = tab->hsiz;
252     while (ndx--) /* empty it */
253     tab->htab[ndx] = OVOID;
254     }
255     /* look up object */
256     hval = shash(name);
257     tryagain:
258     for (i = 0; i < tab->hsiz; i++) {
259 greg 2.11 ndx = (hval + (unsigned long)i*i) % tab->hsiz;
260 greg 1.1 if (tab->htab[ndx] == OVOID ||
261     !strcmp(objptr(tab->htab[ndx])->oname, name))
262     return(ndx);
263     }
264     /* table is full, reallocate */
265     oldhtab = tab->htab;
266     ndx = tab->hsiz;
267     tab->htab = NULL;
268     while (ndx--)
269     if (oldhtab[ndx] != OVOID) {
270     i = otndx(objptr(oldhtab[ndx])->oname, tab);
271     tab->htab[i] = oldhtab[ndx];
272     }
273 greg 2.7 free((void *)oldhtab);
274 greg 1.1 goto tryagain; /* should happen only once! */
275     }