1 /*
2  * object.c
3  *
4  * Object manipulation routines.
5  *
6  */
7 
8 #include "ztypes.h"
9 
10 #define PARENT 0
11 #define NEXT 1
12 #define CHILD 2
13 
14 #ifdef __STDC__
15 static zword_t read_object (zword_t objp, int field);
16 static void write_object (zword_t objp, int field, zword_t value);
17 #else
18 static zword_t read_object ();
19 static void write_object ();
20 #endif
21 
22 /*
23  * get_object_address
24  *
25  * Calculate the address of an object in the data area.
26  *
27  */
28 
29 #ifdef __STDC__
get_object_address(zword_t obj)30 zword_t get_object_address (zword_t obj)
31 #else
32 zword_t get_object_address (obj)
33 zword_t obj;
34 #endif
35 {
36     int offset;
37 
38     /* Address calculation is object table base + size of default properties area +
39        object number-1 * object size */
40 
41     if (h_type < V4)
42         offset = h_objects_offset + ((P3_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O3_SIZE);
43     else
44         offset = h_objects_offset + ((P4_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O4_SIZE);
45 
46     return ((zword_t) offset);
47 
48 }/* get_object_address */
49 
50 /*
51  * insert_object
52  *
53  * Insert object 1 as the child of object 2 after first removing it from its
54  * previous parent. The object is inserted at the front of the child object
55  * chain.
56  *
57  */
58 
59 #ifdef __STDC__
insert_object(zword_t obj1,zword_t obj2)60 void insert_object (zword_t obj1, zword_t obj2)
61 #else
62 void insert_object (obj1, obj2)
63 zword_t obj1;
64 zword_t obj2;
65 #endif
66 {
67     zword_t obj1p, obj2p, child2;
68 
69 #ifdef STRICTZ
70     if (obj1 == 0) {
71         report_strictz_error(STRZERR_MOVE_OBJECT,
72             "@move_object called moving object 0");
73         return;
74     }
75     if (obj2 == 0) {
76         report_strictz_error(STRZERR_MOVE_OBJECT_2,
77             "@move_object called moving into object 0");
78         return;
79     }
80 #endif
81 
82     /* Get addresses of both objects */
83 
84     obj1p = get_object_address (obj1);
85     obj2p = get_object_address (obj2);
86 
87     /* Remove object 1 from current parent */
88 
89     remove_object (obj1);
90 
91     /* Make object 2 object 1's parent */
92 
93     write_object (obj1p, PARENT, obj2);
94 
95     /* Get current first child of object 2 */
96 
97     child2 = read_object (obj2p, CHILD);
98 
99     /* Make object 1 first child of object 2 */
100 
101     write_object (obj2p, CHILD, obj1);
102 
103     /* If object 2 had children then link them into the next child field of object 1 */
104 
105     if (child2)
106         write_object (obj1p, NEXT, child2);
107 
108 }/* insert_object */
109 
110 /*
111  * remove_object
112  *
113  * Remove an object by unlinking from the its parent object and from its
114  * siblings.
115  *
116  */
117 
118 #ifdef __STDC__
remove_object(zword_t obj)119 void remove_object (zword_t obj)
120 #else
121 void remove_object (obj)
122 zword_t obj;
123 #endif
124 {
125     zword_t objp, parentp, childp, parent, child;
126 
127 #ifdef STRICTZ
128     if (obj == 0) {
129         report_strictz_error(STRZERR_REMOVE_OBJECT,
130             "@remove_object called with object 0");
131         return;
132     }
133 #endif
134 
135     /* Get address of object to be removed */
136 
137     objp = get_object_address (obj);
138 
139     /* Get parent of object, and return if no parent */
140 
141     if ((parent = read_object (objp, PARENT)) == 0)
142         return;
143 
144     /* Get address of parent object */
145 
146     parentp = get_object_address (parent);
147 
148     /* Find first child of parent */
149 
150     child = read_object (parentp, CHILD);
151 
152     /* If object is first child then just make the parent child pointer
153        equal to the next child */
154 
155     if (child == obj)
156         write_object (parentp, CHILD, read_object (objp, NEXT));
157     else {
158 
159         /* Walk down the child chain looking for this object */
160 
161         do {
162             childp = get_object_address (child);
163             child = read_object (childp, NEXT);
164         } while (child != obj);
165 
166         /* Set the next pointer thre previous child to the next pointer
167            of the current object child pointer */
168 
169         write_object (childp, NEXT, read_object (objp, NEXT));
170     }
171 
172     /* Set the parent and next child pointers to NULL */
173 
174     write_object (objp, PARENT, 0);
175     write_object (objp, NEXT, 0);
176 
177 }/* remove_object */
178 
179 /*
180  * load_parent_object
181  *
182  * Load the parent object pointer of an object
183  *
184  */
185 
186 #ifdef __STDC__
load_parent_object(zword_t obj)187 void load_parent_object (zword_t obj)
188 #else
189 void load_parent_object (obj)
190 zword_t obj;
191 #endif
192 {
193 
194 #ifdef STRICTZ
195     if (obj == 0) {
196         report_strictz_error(STRZERR_GET_PARENT,
197             "@get_parent called with object 0");
198         store_operand(0);
199         return;
200     }
201 #endif
202 
203     store_operand (read_object (get_object_address (obj), PARENT));
204 
205 }/* load_parent_object */
206 
207 /*
208  * load_child_object
209  *
210  * Load the child object pointer of an object and jump if the child pointer is
211  * not NULL.
212  *
213  */
214 
215 #ifdef __STDC__
load_child_object(zword_t obj)216 void load_child_object (zword_t obj)
217 #else
218 void load_child_object (obj)
219 zword_t obj;
220 #endif
221 {
222     zword_t child;
223 
224 #ifdef STRICTZ
225     if (obj == 0) {
226         report_strictz_error(STRZERR_GET_CHILD,
227             "@get_child called with object 0");
228         store_operand(0);
229         conditional_jump(FALSE);
230         return;
231     }
232 #endif
233 
234     child = read_object (get_object_address (obj), CHILD);
235 
236     store_operand (child);
237 
238     conditional_jump (child != 0);
239 
240 }/* load_child_object */
241 
242 /*
243  * load_next_object
244  *
245  * Load the next child object pointer of an object and jump if the next child
246  * pointer is not NULL.
247  *
248  */
249 
250 #ifdef __STDC__
load_next_object(zword_t obj)251 void load_next_object (zword_t obj)
252 #else
253 void load_next_object (obj)
254 zword_t obj;
255 #endif
256 {
257     zword_t next;
258 
259 #ifdef STRICTZ
260     if (obj == 0) {
261         report_strictz_error(STRZERR_GET_SIBLING,
262             "@get_sibling called with object 0");
263         store_operand(0);
264         conditional_jump(FALSE);
265         return;
266     }
267 #endif
268 
269     next = read_object (get_object_address (obj), NEXT);
270 
271     store_operand (next);
272 
273     conditional_jump (next != 0);
274 
275 }/* load_next_object */
276 
277 /*
278  * compare_parent_object
279  *
280  * Jump if object 2 is the parent of object 1
281  *
282  */
283 
284 #ifdef __STDC__
compare_parent_object(zword_t obj1,zword_t obj2)285 void compare_parent_object (zword_t obj1, zword_t obj2)
286 #else
287 void compare_parent_object (obj1, obj2)
288 zword_t obj1;
289 zword_t obj2;
290 #endif
291 {
292 
293 #ifdef STRICTZ
294     if (obj1 == 0) {
295         report_strictz_error(STRZERR_JIN,
296             "@jin called with object 0");
297         conditional_jump(0 == obj2);
298         return;
299     }
300 #endif
301 
302     conditional_jump (read_object (get_object_address (obj1), PARENT) == obj2);
303 
304 }/* compare_parent_object */
305 
306 /*
307  * test_attr
308  *
309  * Test if an attribute bit is set.
310  *
311  */
312 
313 #ifdef __STDC__
test_attr(zword_t obj,zword_t bit)314 void test_attr (zword_t obj, zword_t bit)
315 #else
316 void test_attr (obj, bit)
317 zword_t obj;
318 zword_t bit;
319 #endif
320 {
321     zword_t objp;
322     zbyte_t value;
323 
324     assert (O3_ATTRIBUTES == O4_ATTRIBUTES);
325 
326 #ifdef STRICTZ
327     if (obj == 0) {
328         report_strictz_error(STRZERR_TEST_ATTR,
329             "@test_attr called with object 0");
330         conditional_jump(FALSE);
331         return;
332     }
333 #endif
334 
335     /* Get attribute address */
336 
337     objp = get_object_address (obj) + (bit >> 3);
338 
339     /* Load attribute byte */
340 
341     value = get_byte (objp);
342 
343     /* Test attribute */
344 
345     conditional_jump ((value >> (7 - (bit & 7))) & 1);
346 
347 }/* test_attr */
348 
349 /*
350  * set_attr
351  *
352  * Set an attribute bit.
353  *
354  */
355 
356 #ifdef __STDC__
set_attr(zword_t obj,zword_t bit)357 void set_attr (zword_t obj, zword_t bit)
358 #else
359 void set_attr (obj, bit)
360 zword_t obj;
361 zword_t bit;
362 #endif
363 {
364     zword_t objp;
365     zbyte_t value;
366 
367     assert (O3_ATTRIBUTES == O4_ATTRIBUTES);
368 
369 #ifdef STRICTZ
370     if (obj == 0) {
371         report_strictz_error(STRZERR_SET_ATTR,
372             "@set_attr called with object 0");
373         return;
374     }
375 #endif
376 
377     /* Get attribute address */
378 
379     objp = get_object_address (obj) + (bit >> 3);
380 
381     /* Load attribute byte */
382 
383     value = get_byte (objp);
384 
385     /* Set attribute bit */
386 
387     value |= (zbyte_t) (1 << (7 - (bit & 7)));
388 
389     /* Store attribute byte */
390 
391     set_byte (objp, value);
392 
393 }/* set_attr */
394 
395 /*
396  * clear_attr
397  *
398  * Clear an attribute bit
399  *
400  */
401 
402 #ifdef __STDC__
clear_attr(zword_t obj,zword_t bit)403 void clear_attr (zword_t obj, zword_t bit)
404 #else
405 void clear_attr (obj, bit)
406 zword_t obj;
407 zword_t bit;
408 #endif
409 {
410     zword_t objp;
411     zbyte_t value;
412 
413     assert (O3_ATTRIBUTES == O4_ATTRIBUTES);
414 
415 #ifdef STRICTZ
416     if (obj == 0) {
417         report_strictz_error(STRZERR_CLEAR_ATTR,
418             "@clear_attr called with object 0");
419         return;
420     }
421 #endif
422 
423     /* Get attribute address */
424 
425     objp = get_object_address (obj) + (bit >> 3);
426 
427     /* Load attribute byte */
428 
429     value = get_byte (objp);
430 
431     /* Clear attribute bit */
432 
433     value &= (zbyte_t) ~(1 << (7 - (bit & 7)));
434 
435     /* Store attribute byte */
436 
437     set_byte (objp, value);
438 
439 }/* clear_attr */
440 
441 #ifdef __STDC__
read_object(zword_t objp,int field)442 static zword_t read_object (zword_t objp, int field)
443 #else
444 static zword_t read_object (objp, field)
445 zword_t objp;
446 int field;
447 #endif
448 {
449     zword_t value;
450 
451     if (h_type < V4) {
452         if (field == PARENT)
453             value = (zword_t) get_byte (PARENT3 (objp));
454         else if (field == NEXT)
455             value = (zword_t) get_byte (NEXT3 (objp));
456         else
457             value = (zword_t) get_byte (CHILD3 (objp));
458     } else {
459         if (field == PARENT)
460             value = get_word (PARENT4 (objp));
461         else if (field == NEXT)
462             value = get_word (NEXT4 (objp));
463         else
464             value = get_word (CHILD4 (objp));
465     }
466 
467     return (value);
468 
469 }/* read_object */
470 
471 #ifdef __STDC__
write_object(zword_t objp,int field,zword_t value)472 static void write_object (zword_t objp, int field, zword_t value)
473 #else
474 static void write_object (objp, field, value)
475 zword_t objp;
476 int field;
477 zword_t value;
478 #endif
479 {
480 
481     if (h_type < V4) {
482         if (field == PARENT)
483             set_byte (PARENT3 (objp), value);
484         else if (field == NEXT)
485             set_byte (NEXT3 (objp), value);
486         else
487             set_byte (CHILD3 (objp), value);
488     } else {
489         if (field == PARENT)
490             set_word (PARENT4 (objp), value);
491         else if (field == NEXT)
492             set_word (NEXT4 (objp), value);
493         else
494             set_word (CHILD4 (objp), value);
495     }
496 
497 }/* write_object */
498