2 \brief IR Memory Implementation
3 \details Intermediary memory management
6 ----------------------------------------------------------------------------*/
8 #include <stdlib.h> //exit, malloc
9 #include <stdio.h> //print
10 #include <stdarg.h> //va_args
11 #include <stdint.h> //uint64_t
12 #include <string.h> //memset, str*
15 #include <unistd.h> //u8_* functions
16 #include <unitypes.h> //uint8_t as a char
17 #include <unistr.h> //u32_cpy
18 #include <unistdio.h> //ulc_fprintf
20 #define eprintf_callback(...) exit(EXIT_FAILURE)
25 #define XXH_PRIVATE_API
26 #include "../xxHash/xxhash.h"
32 int ir_condenser(void);
34 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
37 { struct ir_namelist_t
* nextsib
;
41 { struct ir_class_t
* root_class
;
42 struct ir_namelist_t
* namelist
, * namelist_head
;
45 { struct ir_classld_t
* classld
;
47 struct ir_namelist_t
* namelist
, * namelist_head
;
49 struct ir_setdata_header_t
51 uint8_t* src_filename
, * data_name
;
52 union ir_setdata_t
* nextsib
;
56 { struct ir_setdata_header_t header
;
57 struct ir_frameinfo_t frameinfo
;
60 { struct ir_setdata_header_t header
;
61 struct ir_framedata_t framesheets
[FACING_MAX
];
62 struct ir_framedata_t mapsheets
[FACING_MAX
];
64 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
66 { struct ir_setdata_header_t header
;
67 struct ir_classld_t
* classld
;
68 struct ir_setld_t
* setld
;
69 struct ir_set_t
* trg_set
;
73 { struct ir_setdata_header_t header
;
74 struct ir_framebox_t framebox
;
75 struct ir_framedata_t framesheet
;
76 struct ir_framedata_t mapsheet
;
77 struct ir_simplex_t audio
;
78 struct ir_link_t link
;
81 { struct ir_class_t
* nextchild
, * nextsib
;
82 struct ir_set_t
* root_set
;
87 { struct ir_set_t
* nextchild
, * nextsib
;
90 struct ir_framebox_t
* frameboxes
;
91 struct ir_simplex_t
* audio
;
92 struct ir_link_t
* links
;
97 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*,uint8_t*);
99 union ir_setdata_t
* ir_framedata (enum dtype
,const uint8_t*,apc_facing
,int,int);
101 void ir_linkdata_resolve_set(union ir_setdata_t
*);
103 int bytes_identical(const uint8_t*,const uint8_t*);
105 int classnames_identical(const uint8_t*,const uint8_t*);
107 uint8_t* name_alloc(const uint8_t*);
109 uint8_t* classname_alloc(const uint8_t*);
110 #define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
111 #define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)
112 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
116 char* apc_package_name
;
118 struct pagelist_t datapages
, namepages
, refhashpages
;
120 struct ir_class_t root_class
;
125 { pagelist_init(datapages
, (size_t)SYS_PAGESIZE
);
126 pagelist_init(namepages
, (size_t)NAME_PAGESIZE
);
127 pagelist_init(refhashpages
, (size_t)SYS_PAGESIZE
);
128 root_class
.name
= (uint8_t*) apc_package_name
;
135 { pagenode_free(datapages
.root
);
136 pagenode_free(namepages
.root
);
137 pagenode_free(refhashpages
.root
);
153 /* Return the class's name string */
154 uint8_t* ir_class_name
155 ( struct ir_class_t
* class )
156 { return class->name
; }
158 /* Return a pointer to the root class */
159 struct ir_class_t
* ir_class_root
161 { return &root_class
; }
163 /* Add a subclass to a class
164 Attempts to create a new subclass in the provided class, returning
165 the class if it already exists
167 struct ir_class_t
* ir_class_addchild
168 ( struct ir_class_t
* class,
171 { struct ir_class_t
* iter
;
172 if (class->nextchild
== NULL
)
173 { class->nextchild
= struct_alloc(ir_class_t
);
174 struct_clear(class->nextchild
);
175 class->nextchild
->name
= classname_alloc(name
);
176 return class->nextchild
;
178 iter
= class->nextchild
;
179 if (iter
->name
== NULL
)
180 eprintf("Null name pointer in class %p\n", iter
);
182 eprintf("Null child added to class %s\n", iter
->name
);
184 if (classnames_identical(iter
->name
, name
))
186 if (iter
->nextsib
!= NULL
)
187 { iter
= iter
->nextsib
;
190 iter
->nextsib
= struct_alloc(ir_class_t
);
191 struct_clear(iter
->nextsib
);
192 iter
->nextsib
->name
= classname_alloc(name
);
193 return iter
->nextsib
;
196 /* Add a set to a class
197 Attempts to create a new root set in the specified class, returning
198 the set if it already exists
200 struct ir_set_t
* ir_class_addset
201 ( struct ir_class_t
* class,
204 { struct ir_set_t
* iter
;
205 if (class->root_set
== NULL
)
206 { class->root_set
= struct_alloc(ir_set_t
);
207 struct_clear(class->root_set
);
208 class->root_set
->name
= name_alloc(name
);
209 return class->root_set
;
211 iter
= class->root_set
;
212 if (iter
->name
== NULL
)
213 eprintf("Null name pointer in class %p\n", iter
);
215 eprintf("Null set added to class %U\n", iter
->name
);
217 if (bytes_identical(iter
->name
, name
))
219 if (iter
->nextsib
!= NULL
)
220 { iter
= iter
->nextsib
;
223 iter
->nextsib
= struct_alloc(ir_set_t
);
224 struct_clear(iter
->nextsib
);
225 iter
->nextsib
->name
= name_alloc(name
);
226 return iter
->nextsib
;
229 /* Get the root set of the class */
230 struct ir_set_t
* ir_class_rootset
231 ( struct ir_class_t
* class )
232 { return class->root_set
; }
234 struct ir_set_t
* ir_set_from_ref
237 struct ir_set_t
** iters
;
238 struct pagenode_t
* iterp
;
239 iterp
= refhashpages
.root
;
242 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
243 while (*iters
!= NULL
&& (*iters
)->ref
!= ref
&& (iterp
= iterp
->header
.next
) != NULL
);
248 /* Add a set to a set
249 Attempts to create a new subset of the specified set, returning the
250 child if it already exists
252 struct ir_set_t
* ir_set_addchild
253 ( struct ir_set_t
* set
,
256 { struct ir_set_t
* iter
;
257 if (set
->nextchild
== NULL
)
258 { set
->nextchild
= struct_alloc(ir_set_t
);
259 struct_clear(set
->nextchild
);
260 set
->nextchild
->name
= name_alloc(name
);
261 return set
->nextchild
;
263 iter
= set
->nextchild
;
265 eprintf("Null child added to set %s\n", iter
->name
);
266 if (iter
->name
== NULL
)
267 eprintf("Null name pointer in set %p\n", iter
);
269 if (bytes_identical(iter
->name
, name
))
271 if (iter
->nextsib
!= NULL
)
272 { iter
= iter
->nextsib
;
275 iter
->nextsib
= struct_alloc(ir_set_t
);
276 struct_clear(iter
->nextsib
);
277 iter
->nextsib
->name
= name_alloc(name
);
278 return iter
->nextsib
;
281 /* Add a framebox to a set
282 Attempts to create a new framebox of the specified set, returning
283 the framebox if it already exists
284 Name is not allocated, but assigned, unlike other "XXX_add" functions where
285 name is duplicated into IR's internal array.
288 struct ir_framebox_t
* ir_set_add_framebox
289 ( struct ir_set_t
* set
,
292 { struct ir_framebox_t
* iter
;
293 if (set
->frameboxes
== NULL
)
294 { set
->frameboxes
= struct_alloc(ir_framebox_t
);
295 struct_clear(set
->frameboxes
);
296 set
->frameboxes
->header
.data_name
= name
;
297 return set
->frameboxes
;
299 iter
= set
->frameboxes
;
301 if (bytes_identical(iter
->header
.data_name
, name
))
303 if (iter
->header
.nextsib
!= NULL
)
304 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
307 iter
->header
.nextsib
= (union ir_setdata_t
*) struct_alloc(ir_framebox_t
);
308 struct_clear(iter
->header
.nextsib
);
309 iter
->header
.nextsib
->header
.data_name
= name
;
310 return (struct ir_framebox_t
*) (iter
->header
.nextsib
);
313 /* Match two null-terminated bytestrings
314 Return 1 if the two bytestrings are identical, else 0
318 ( const uint8_t* stra
,
325 } while (ca
&& ca
!= '_' && ca
== cb
);
330 int classnames_identical
331 ( const uint8_t* stra
,
338 } while (ca
&& ca
== cb
);
342 /* Return the name of the set */
344 ( struct ir_set_t
* set
)
345 { return set
->name
; }
347 /* Return the next sib of the class */
348 struct ir_class_t
* ir_class_nextsib
349 ( struct ir_class_t
* class )
350 { return class->nextsib
; }
352 /* Return the next sib of the class */
353 struct ir_class_t
* ir_class_nextchild
354 ( struct ir_class_t
* class )
355 { return class->nextchild
; }
357 /* Get the file position of the class */
359 ( struct ir_class_t
* class )
360 { return class->filepos
; }
362 /* Set the file position of the class */
363 void ir_class_assign_fpos
364 ( struct ir_class_t
* class,
367 { class->filepos
= newpos
; }
369 /* Get the next sibling of the provided set */
370 struct ir_set_t
* ir_set_nextsib
371 ( struct ir_set_t
* set
)
372 { return set
->nextsib
; }
374 /* Get the next child of the provided set */
375 struct ir_set_t
* ir_set_nextchild
376 ( struct ir_set_t
* set
)
377 { return set
->nextchild
; }
379 /* Get the file position of the class */
381 ( struct ir_set_t
* set
)
382 { return set
->filepos
; }
384 /* Set the file position of the class */
385 void ir_set_assign_fpos
386 ( struct ir_set_t
* set
,
389 { set
->filepos
= newpos
; }
391 /* Assign Setdata to Set */
392 void ir_set_assign_data
393 ( struct ir_set_t
* set
,
394 union ir_setdata_t
* setdata
396 { struct ir_framebox_t
* framebox
;
397 struct ir_simplex_t
* simplex
;
398 switch (setdata
->header
.type
)
400 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
401 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
402 wprintf("Duplicate framesheet [%i] %s\n",
403 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
404 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
407 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
408 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
409 wprintf("Duplicate mapsheet [%i] %s\n",
410 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
411 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
414 if (set
->audio
== NULL
)
415 { set
->audio
= (struct ir_simplex_t
*) setdata
;
418 simplex
= set
->audio
;
419 while (simplex
->header
.nextsib
!= NULL
)
420 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
421 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
422 *simplex
= setdata
->audio
;
423 //setdata is now a pointer to redundant, unused memory.
427 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
428 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
429 set
->audio
= (struct ir_simplex_t
*) setdata
;
432 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
433 set
->links
= (struct ir_link_t
*) setdata
;
436 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
441 void ir_set_assign_ref
442 ( struct ir_set_t
* set
,
445 { uint16_t hash
, oldhash
;
446 struct ir_set_t
** iters
;
447 struct pagenode_t
* iterp
;
452 iterp
= refhashpages
.root
;
454 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
455 if (*iters
== NULL
|| *iters
== set
)
458 { if (iterp
->header
.next
== NULL
)
459 pagelist_alloc(refhashpages
);
460 iterp
= iterp
->header
.next
;
464 { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref
, ref
, set
->name
);
469 hash
= REFHASH(oldref
);
476 void ir_data_assign_path
477 ( union ir_setdata_t
* setdata
,
481 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
482 if (setdata
->header
.src_filename
!= NULL
)
483 wprintf("Path override: %s -> %s for setdata %s\n",
484 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
485 setdata
->header
.src_filename
= name_alloc(path
);
488 union ir_setdata_t
* ir_framesheet
489 ( const uint8_t* name
,
494 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
496 union ir_setdata_t
* ir_mapsheet
497 ( const uint8_t* name
,
502 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
505 union ir_setdata_t
* ir_framedata
512 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
513 struct_clear(framedata
);
515 eprintf("Null name in set allocation\n");
516 framedata
->header
.type
= type
;
517 framedata
->header
.data_name
= name_alloc(name
);
518 framedata
->frameinfo
.facing
= d
;
519 framedata
->frameinfo
.w
= width
;
520 framedata
->frameinfo
.h
= height
;
521 return (union ir_setdata_t
*) framedata
;
524 union ir_setdata_t
* ir_audio
525 ( const uint8_t* name
)
526 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
529 eprintf("Null audio\n");
530 audio
->header
.type
= ADAT
;
531 audio
->header
.data_name
= name_alloc(name
);
532 return (union ir_setdata_t
*) audio
;
536 /* Create classld that points to a class */
537 struct ir_classld_t
* ir_classld_from_class
538 ( struct ir_class_t
* class )
539 { struct ir_classld_t
* classld
;
541 eprintf("Null class in classld\n");
542 classld
= struct_alloc(ir_classld_t
);
543 struct_clear(classld
);
544 classld
->root_class
= class;
548 struct ir_setld_t
* ir_setld_from_ref
550 { struct ir_setld_t
* setld
;
551 setld
= struct_alloc(ir_setld_t
);
557 struct ir_setld_t
* ir_setld_from_classld
558 ( struct ir_classld_t
* classld
,
561 { struct ir_setld_t
* setld
;
562 setld
= struct_alloc(ir_setld_t
);
564 setld
->namelist
= struct_alloc(ir_namelist_t
);
565 struct_clear(setld
->namelist
);
566 setld
->namelist_head
= setld
->namelist
;
567 setld
->namelist_head
->name
= name_alloc(name
);
568 setld
->classld
= classld
;
572 struct ir_setld_t
* ir_setld_addchild
573 ( struct ir_setld_t
* setld
,
576 { if (setld
->namelist
== NULL
)
577 { setld
->namelist
= struct_alloc(ir_namelist_t
);
578 struct_clear(setld
->namelist
);
579 setld
->namelist_head
= setld
->namelist
;
582 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
583 struct_clear(setld
->namelist_head
->nextsib
);
584 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
586 setld
->namelist_head
->name
= name_alloc(name
);
590 union ir_setdata_t
* ir_link
591 ( enum ltype link_type
,
592 struct ir_setld_t
* setld
,
595 { struct ir_link_t
* link
;
596 link
= struct_alloc(ir_link_t
);
598 link
->header
.type
= LDAT
;
599 link
->type
= link_type
;
600 link
->classld
= setld
->classld
;
602 if (link_type
!= OLINK
&& name
!= NULL
)
603 link
->header
.data_name
= name_alloc(name
);
604 return (union ir_setdata_t
*) link
;
607 /* Return a set's root framebox */
608 union ir_setdata_t
* ir_set_framebox
609 ( struct ir_set_t
* set
)
610 { return (union ir_setdata_t
*) set
->frameboxes
; }
612 /* Return a set's root audio data */
613 union ir_setdata_t
* ir_set_audio
614 ( struct ir_set_t
* set
)
615 { return (union ir_setdata_t
*) set
->audio
; }
617 /* Return a set's root link data */
618 union ir_setdata_t
* ir_set_link
619 ( struct ir_set_t
* set
)
620 { return (union ir_setdata_t
*) set
->links
; }
622 #define assert_link(linkdata) do { \
623 if (linkdata->header.type != LDAT) \
624 eprintf("Data %s is not a link\n", linkdata->header.data_name); \
627 /* Return the link type */
628 enum ltype ir_linkdata_type
629 ( union ir_setdata_t
* linkdata
)
630 { assert_link(linkdata
);
631 return linkdata
->link
.type
;
634 /* Return the link type */
635 uint32_t ir_linkdata_ref
636 ( union ir_setdata_t
* linkdata
)
637 { assert_link(linkdata
);
638 return linkdata
->link
.setld
->ref
;
641 /* Return the current target set, resolving it first if not present */
642 struct ir_set_t
* ir_linkdata_set
643 ( union ir_setdata_t
* linkdata
)
644 { assert_link(linkdata
);
645 if (linkdata
->link
.trg_set
== NULL
)
646 ir_linkdata_resolve_set(linkdata
);
647 return linkdata
->link
.trg_set
;
650 /* Resolve and assign the link's target set */
652 void ir_linkdata_resolve_set
653 ( union ir_setdata_t
* linkdata
)
654 { struct ir_class_t
* class_iter
;
655 struct ir_namelist_t
* namelist_iter
,* namelist_iter_last
;
656 struct ir_setld_t
* setld
;
657 struct ir_classld_t
* classld
;
658 struct ir_set_t
* set
;
661 assert_link(linkdata
);
662 setld
= linkdata
->link
.setld
;
663 if (linkdata
->link
.setld
== NULL
)
664 eprintf("Link data is invalid\n");
665 classld
= linkdata
->link
.classld
;
667 { namelist_iter
= classld
->namelist
;
668 if (classld
->root_class
== NULL
)
669 eprintf("No root class for classld\n");
670 class_iter
= classld
->root_class
->nextchild
;
671 namelist_iter_last
= NULL
;
672 while (class_iter
!= NULL
)
673 { if (classnames_identical(class_iter
->name
, namelist_iter
->name
))
674 { if (namelist_iter
== classld
->namelist_head
)
676 class_iter
= class_iter
->nextchild
;
677 namelist_iter_last
= namelist_iter
;
678 namelist_iter
= namelist_iter
->nextsib
;
681 class_iter
= class_iter
->nextsib
;
683 if (class_iter
== NULL
)
684 { if (namelist_iter_last
)
685 eprintf("No such subclass \"%s\" of class \"%s\"\n",
687 namelist_iter_last
->name
);
689 eprintf("No such class \"%s\"\n", namelist_iter
->name
);
691 set
= class_iter
->root_set
;
694 set
= ir_set_from_ref(setld
->ref
);
696 eprintf("Initial set resolution failed\n");
697 namelist_iter
= setld
->namelist
;
698 namelist_iter_last
= NULL
;
699 if (setld
->namelist
!= NULL
)
700 { while (set
!= NULL
)
701 { if (bytes_identical(set
->name
, namelist_iter
->name
))
702 { if (namelist_iter
== setld
->namelist_head
)
704 set
= set
->nextchild
;
705 namelist_iter_last
= namelist_iter
;
706 namelist_iter
= namelist_iter
->nextsib
;
712 { if (namelist_iter_last
)
713 eprintf("No such subset \"%s\" of set \"%s\"\n",
715 namelist_iter_last
->name
);
717 eprintf("No such set \"%s\" in class \"%s\"\n",
722 linkdata
->link
.trg_set
= set
;
725 /* Get a setdata's next sibling */
726 union ir_setdata_t
* ir_setdata_nextsib
727 ( union ir_setdata_t
* setdata
)
728 { return setdata
->header
.nextsib
; }
730 /* Get a setdata's name */
731 uint8_t* ir_setdata_name
732 ( union ir_setdata_t
* setdata
)
733 { return setdata
->header
.data_name
; }
735 /* Get a setdata's filename */
736 uint8_t* ir_setdata_filename
737 ( union ir_setdata_t
* setdata
)
738 { return setdata
->header
.src_filename
; }
740 /* Get a setdata's file position */
742 ( union ir_setdata_t
* setdata
)
743 { return setdata
->header
.filepos
; }
745 /* Set a setdata's file position */
746 void ir_setdata_assign_fpos
747 ( union ir_setdata_t
* setdata
,
750 { setdata
->header
.filepos
= newpos
; }
752 /* Return a framebox's specified framesheet */
753 union ir_setdata_t
* ir_framebox_framesheet
754 ( union ir_setdata_t
* fbox
,
757 { if (fbox
->header
.type
!= FBDAT
)
758 eprintf("Data %s is not a framebox\n", fbox
->header
.data_name
);
759 return (union ir_setdata_t
*) &fbox
->framebox
.framesheets
[facing
];
762 /* Return a framebox's specified mapsheet */
763 union ir_setdata_t
* ir_framebox_mapsheet
764 ( union ir_setdata_t
* fbox
,
767 { if (fbox
->header
.type
!= FBDAT
)
768 eprintf("Data %s is not a framebox\n", fbox
->header
.data_name
);
769 return (union ir_setdata_t
*) &fbox
->framebox
.mapsheets
[facing
];
772 /* Return a framedata's frame info */
773 struct ir_frameinfo_t
* ir_framedata_frameinfo
774 ( union ir_setdata_t
* framedata
)
775 { if (framedata
->header
.type
!= MSDAT
&& framedata
->header
.type
!= FSDAT
)
776 eprintf("Data %s is not a framedata\n", framedata
->header
.data_name
);
777 return &framedata
->mapsheet
.frameinfo
;
784 ( const uint8_t* name_src
)
785 { const uint8_t* iter
;
789 name
= (uint8_t*)namepages
.head
->header
.head
;
791 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && *iter
!= '.' && head_mem
; head_mem
--)
792 *(namepages
.head
->header
.head
)++ = *iter
++;
793 if (head_mem
< 1) //not enough room
794 { pagelist_alloc(namepages
);
797 *(namepages
.head
->header
.head
)++ = '\0';
802 uint8_t* classname_alloc
803 ( const uint8_t* name_src
)
804 { const uint8_t* iter
;
808 name
= (uint8_t*)namepages
.head
->header
.head
;
810 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
811 *(namepages
.head
->header
.head
)++ = *iter
++;
812 if (head_mem
< 1) //not enough room
813 { pagelist_alloc(namepages
);
816 *(namepages
.head
->header
.head
)++ = '\0';
820 static void crawl_class(struct ir_class_t
*);
821 static void crawl_set(struct ir_set_t
*,int);
824 int binout_init(ir_class
);
826 { uprintf("IR From Directory: %s\n",getcwd(NULL
,255));
827 crawl_class(&root_class
);
828 if (root_class
.root_set
!= NULL
)
829 crawl_set(root_class
.root_set
, 0);
830 uprintf("starting binaryout \n");
831 binout_init(&root_class
);
837 ( struct ir_class_t
* class )
838 { struct ir_class_t
* iter
;
839 for (iter
= class->nextchild
; iter
!= NULL
; iter
= iter
->nextsib
)
840 { wprintf("Crawling class %U/\n", iter
->name
);
841 if(chdir((char*)iter
->name
))
842 eprintf("CHDIR %U from %s\n",iter
->name
,getcwd(NULL
,255));
844 if (iter
->root_set
!= NULL
)
845 crawl_set(iter
->root_set
, 0);
846 uprintf("%U\\\n",iter
->name
);
848 eprintf("CHDIR ..\n");
849 wprintf("Finished crawling class %U/\n", iter
->name
);
853 #define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)
854 #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))
857 ( struct ir_set_t
* set
,
860 { struct ir_set_t
* iter
;
867 for(iter
= set
; iter
!= NULL
; iter
= iter
->nextchild
)
868 { uprintf("[%10U]", iter
->name
);
875 if (((iter
= pop_setp())->nextsib
) != NULL
)
876 crawl_set(iter
->nextsib
,i
);