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
25 #define do_error(...) exit(-1)
26 #define XXH_PRIVATE_API
27 #include "../xxHash/xxhash.h"
33 int ir_condenser(void);
35 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
38 { struct ir_namelist_t
* nextsib
;
42 { struct ir_class_t
* root_class
;
43 struct ir_namelist_t
* namelist
, * namelist_head
;
46 { struct ir_classld_t
* classld
;
48 struct ir_namelist_t
* namelist
, * namelist_head
;
50 struct ir_setdata_header_t
52 uint8_t* src_filename
, * data_name
;
53 union ir_setdata_t
* nextsib
;
57 { struct ir_setdata_header_t header
;
58 struct ir_frameinfo_t frameinfo
;
61 { struct ir_setdata_header_t header
;
62 struct ir_framedata_t framesheets
[FACING_MAX
];
63 struct ir_framedata_t mapsheets
[FACING_MAX
];
65 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
67 { struct ir_setdata_header_t header
;
68 struct ir_classld_t
* classld
;
69 struct ir_setld_t
* setld
;
70 struct ir_set_t
* trg_set
;
74 { struct ir_setdata_header_t header
;
75 struct ir_framebox_t framebox
;
76 struct ir_framedata_t framesheet
;
77 struct ir_framedata_t mapsheet
;
78 struct ir_simplex_t audio
;
79 struct ir_link_t link
;
82 { struct ir_class_t
* nextchild
, * nextsib
;
83 struct ir_set_t
* root_set
;
88 { struct ir_set_t
* nextchild
, * nextsib
;
91 struct ir_framebox_t
* frameboxes
;
92 struct ir_simplex_t
* audio
;
93 struct ir_link_t
* links
;
98 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*,uint8_t*);
100 union ir_setdata_t
* ir_framedata (enum dtype
,const uint8_t*,apc_facing
,int,int);
102 void ir_linkdata_resolve_set(union ir_setdata_t
*);
104 int bytes_identical(const uint8_t*,const uint8_t*);
106 int classnames_identical(const uint8_t*,const uint8_t*);
108 uint8_t* name_alloc(const uint8_t*);
110 uint8_t* classname_alloc(const uint8_t*);
111 #define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
112 #define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)
113 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
117 char* apc_package_name
;
119 struct pagelist_t datapages
, namepages
, refhashpages
;
121 struct ir_class_t root_class
;
126 { pagelist_init(datapages
, (size_t)SYS_PAGESIZE
);
127 pagelist_init(namepages
, (size_t)NAME_PAGESIZE
);
128 pagelist_init(refhashpages
, (size_t)SYS_PAGESIZE
);
129 root_class
.name
= (uint8_t*) apc_package_name
;
136 { pagenode_free(datapages
.root
);
137 pagenode_free(namepages
.root
);
138 pagenode_free(refhashpages
.root
);
154 /* Return the class's name string */
155 uint8_t* ir_class_name
156 ( struct ir_class_t
* class )
157 { return class->name
; }
159 /* Return a pointer to the root class */
160 struct ir_class_t
* ir_class_root
162 { return &root_class
; }
164 /* Add a subclass to a class
165 Attempts to create a new subclass in the provided class, returning
166 the class if it already exists
168 struct ir_class_t
* ir_class_addchild
169 ( struct ir_class_t
* class,
172 { struct ir_class_t
* iter
;
173 if (class->nextchild
== NULL
)
174 { class->nextchild
= struct_alloc(ir_class_t
);
175 struct_clear(class->nextchild
);
176 class->nextchild
->name
= classname_alloc(name
);
177 return class->nextchild
;
179 iter
= class->nextchild
;
180 if (iter
->name
== NULL
)
181 eprintf("Null name pointer in class %p\n", iter
);
183 eprintf("Null child added to class %s\n", iter
->name
);
185 if (classnames_identical(iter
->name
, name
))
187 if (iter
->nextsib
!= NULL
)
188 { iter
= iter
->nextsib
;
191 iter
->nextsib
= struct_alloc(ir_class_t
);
192 struct_clear(iter
->nextsib
);
193 iter
->nextsib
->name
= classname_alloc(name
);
194 return iter
->nextsib
;
197 /* Add a set to a class
198 Attempts to create a new root set in the specified class, returning
199 the set if it already exists
201 struct ir_set_t
* ir_class_addset
202 ( struct ir_class_t
* class,
205 { struct ir_set_t
* iter
;
206 if (class->root_set
== NULL
)
207 { class->root_set
= struct_alloc(ir_set_t
);
208 struct_clear(class->root_set
);
209 class->root_set
->name
= name_alloc(name
);
210 return class->root_set
;
212 iter
= class->root_set
;
213 if (iter
->name
== NULL
)
214 eprintf("Null name pointer in class %p\n", iter
);
216 eprintf("Null set added to class %U\n", iter
->name
);
218 if (bytes_identical(iter
->name
, name
))
220 if (iter
->nextsib
!= NULL
)
221 { iter
= iter
->nextsib
;
224 iter
->nextsib
= struct_alloc(ir_set_t
);
225 struct_clear(iter
->nextsib
);
226 iter
->nextsib
->name
= name_alloc(name
);
227 return iter
->nextsib
;
230 /* Get the root set of the class */
231 struct ir_set_t
* ir_class_rootset
232 ( struct ir_class_t
* class )
233 { return class->root_set
; }
235 struct ir_set_t
* ir_set_from_ref
238 struct ir_set_t
** iters
;
239 struct pagenode_t
* iterp
;
240 iterp
= refhashpages
.root
;
243 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
244 while (*iters
!= NULL
&& (*iters
)->ref
!= ref
&& (iterp
= iterp
->header
.next
) != NULL
);
249 /* Add a set to a set
250 Attempts to create a new subset of the specified set, returning the
251 child if it already exists
253 struct ir_set_t
* ir_set_addchild
254 ( struct ir_set_t
* set
,
257 { struct ir_set_t
* iter
;
258 if (set
->nextchild
== NULL
)
259 { set
->nextchild
= struct_alloc(ir_set_t
);
260 struct_clear(set
->nextchild
);
261 set
->nextchild
->name
= name_alloc(name
);
262 return set
->nextchild
;
264 iter
= set
->nextchild
;
266 eprintf("Null child added to set %s\n", iter
->name
);
267 if (iter
->name
== NULL
)
268 eprintf("Null name pointer in set %p\n", iter
);
270 if (bytes_identical(iter
->name
, name
))
272 if (iter
->nextsib
!= NULL
)
273 { iter
= iter
->nextsib
;
276 iter
->nextsib
= struct_alloc(ir_set_t
);
277 struct_clear(iter
->nextsib
);
278 iter
->nextsib
->name
= name_alloc(name
);
279 return iter
->nextsib
;
282 /* Add a framebox to a set
283 Attempts to create a new framebox of the specified set, returning
284 the framebox if it already exists
285 Name is not allocated, but assigned, unlike other "XXX_add" functions where
286 name is duplicated into IR's internal array.
289 struct ir_framebox_t
* ir_set_add_framebox
290 ( struct ir_set_t
* set
,
293 { struct ir_framebox_t
* iter
;
294 if (set
->frameboxes
== NULL
)
295 { set
->frameboxes
= struct_alloc(ir_framebox_t
);
296 struct_clear(set
->frameboxes
);
297 set
->frameboxes
->header
.data_name
= name
;
298 return set
->frameboxes
;
300 iter
= set
->frameboxes
;
302 if (bytes_identical(iter
->header
.data_name
, name
))
304 if (iter
->header
.nextsib
!= NULL
)
305 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
308 iter
->header
.nextsib
= (union ir_setdata_t
*) struct_alloc(ir_framebox_t
);
309 struct_clear(iter
->header
.nextsib
);
310 iter
->header
.nextsib
->header
.data_name
= name
;
311 return (struct ir_framebox_t
*) (iter
->header
.nextsib
);
314 /* Match two null-terminated bytestrings
315 Return 1 if the two bytestrings are identical, else 0
319 ( const uint8_t* stra
,
326 } while (ca
&& ca
!= '_' && ca
== cb
);
331 int classnames_identical
332 ( const uint8_t* stra
,
339 } while (ca
&& ca
== cb
);
343 /* Return the name of the set */
345 ( struct ir_set_t
* set
)
346 { return set
->name
; }
348 /* Return the next sib of the class */
349 struct ir_class_t
* ir_class_nextsib
350 ( struct ir_class_t
* class )
351 { return class->nextsib
; }
353 /* Return the next sib of the class */
354 struct ir_class_t
* ir_class_nextchild
355 ( struct ir_class_t
* class )
356 { return class->nextchild
; }
358 /* Get the file position of the class */
360 ( struct ir_class_t
* class )
361 { return class->filepos
; }
363 /* Set the file position of the class */
364 void ir_class_assign_fpos
365 ( struct ir_class_t
* class,
368 { class->filepos
= newpos
; }
370 /* Get the next sibling of the provided set */
371 struct ir_set_t
* ir_set_nextsib
372 ( struct ir_set_t
* set
)
373 { return set
->nextsib
; }
375 /* Get the next child of the provided set */
376 struct ir_set_t
* ir_set_nextchild
377 ( struct ir_set_t
* set
)
378 { return set
->nextchild
; }
380 /* Get the file position of the class */
382 ( struct ir_set_t
* set
)
383 { return set
->filepos
; }
385 /* Set the file position of the class */
386 void ir_set_assign_fpos
387 ( struct ir_set_t
* set
,
390 { set
->filepos
= newpos
; }
392 /* Assign Setdata to Set */
393 void ir_set_assign_data
394 ( struct ir_set_t
* set
,
395 union ir_setdata_t
* setdata
397 { struct ir_framebox_t
* framebox
;
398 struct ir_simplex_t
* simplex
;
399 switch (setdata
->header
.type
)
401 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
402 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
403 wprintf("Duplicate framesheet [%i] %s\n",
404 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
405 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
408 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
409 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
410 wprintf("Duplicate mapsheet [%i] %s\n",
411 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
412 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
415 if (set
->audio
== NULL
)
416 { set
->audio
= (struct ir_simplex_t
*) setdata
;
419 simplex
= set
->audio
;
420 while (simplex
->header
.nextsib
!= NULL
)
421 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
422 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
423 *simplex
= setdata
->audio
;
424 //setdata is now a pointer to redundant, unused memory.
428 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
429 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
430 set
->audio
= (struct ir_simplex_t
*) setdata
;
433 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
434 set
->links
= (struct ir_link_t
*) setdata
;
437 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
442 void ir_set_assign_ref
443 ( struct ir_set_t
* set
,
446 { uint16_t hash
, oldhash
;
447 struct ir_set_t
** iters
;
448 struct pagenode_t
* iterp
;
453 iterp
= refhashpages
.root
;
455 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
456 if (*iters
== NULL
|| *iters
== set
)
459 { if (iterp
->header
.next
== NULL
)
460 pagelist_alloc(refhashpages
);
461 iterp
= iterp
->header
.next
;
465 { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref
, ref
, set
->name
);
470 hash
= REFHASH(oldref
);
477 void ir_data_assign_path
478 ( union ir_setdata_t
* setdata
,
482 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
483 if (setdata
->header
.src_filename
!= NULL
)
484 wprintf("Path override: %s -> %s for setdata %s\n",
485 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
486 setdata
->header
.src_filename
= name_alloc(path
);
489 union ir_setdata_t
* ir_framesheet
490 ( const uint8_t* name
,
495 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
497 union ir_setdata_t
* ir_mapsheet
498 ( const uint8_t* name
,
503 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
506 union ir_setdata_t
* ir_framedata
513 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
514 struct_clear(framedata
);
516 eprintf("Null name in set allocation\n");
517 framedata
->header
.type
= type
;
518 framedata
->header
.data_name
= name_alloc(name
);
519 framedata
->frameinfo
.facing
= d
;
520 framedata
->frameinfo
.w
= width
;
521 framedata
->frameinfo
.h
= height
;
522 return (union ir_setdata_t
*) framedata
;
525 union ir_setdata_t
* ir_audio
526 ( const uint8_t* name
)
527 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
530 eprintf("Null audio\n");
531 audio
->header
.type
= ADAT
;
532 audio
->header
.data_name
= name_alloc(name
);
533 return (union ir_setdata_t
*) audio
;
537 /* Create classld that points to a class */
538 struct ir_classld_t
* ir_classld_from_class
539 ( struct ir_class_t
* class )
540 { struct ir_classld_t
* classld
;
542 eprintf("Null class in classld\n");
543 classld
= struct_alloc(ir_classld_t
);
544 struct_clear(classld
);
545 classld
->root_class
= class;
549 struct ir_setld_t
* ir_setld_from_ref
551 { struct ir_setld_t
* setld
;
552 setld
= struct_alloc(ir_setld_t
);
558 struct ir_setld_t
* ir_setld_from_classld
559 ( struct ir_classld_t
* classld
,
562 { struct ir_setld_t
* setld
;
563 setld
= struct_alloc(ir_setld_t
);
565 setld
->namelist
= struct_alloc(ir_namelist_t
);
566 struct_clear(setld
->namelist
);
567 setld
->namelist_head
= setld
->namelist
;
568 setld
->namelist_head
->name
= name_alloc(name
);
569 setld
->classld
= classld
;
573 struct ir_setld_t
* ir_setld_addchild
574 ( struct ir_setld_t
* setld
,
577 { if (setld
->namelist
== NULL
)
578 { setld
->namelist
= struct_alloc(ir_namelist_t
);
579 struct_clear(setld
->namelist
);
580 setld
->namelist_head
= setld
->namelist
;
583 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
584 struct_clear(setld
->namelist_head
->nextsib
);
585 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
587 setld
->namelist_head
->name
= name_alloc(name
);
591 union ir_setdata_t
* ir_link
592 ( enum ltype link_type
,
593 struct ir_setld_t
* setld
,
596 { struct ir_link_t
* link
;
597 link
= struct_alloc(ir_link_t
);
599 link
->header
.type
= LDAT
;
600 link
->type
= link_type
;
601 link
->classld
= setld
->classld
;
603 if (link_type
!= OLINK
&& name
!= NULL
)
604 link
->header
.data_name
= name_alloc(name
);
605 return (union ir_setdata_t
*) link
;
608 /* Return a set's root framebox */
609 union ir_setdata_t
* ir_set_framebox
610 ( struct ir_set_t
* set
)
611 { return (union ir_setdata_t
*) set
->frameboxes
; }
613 /* Return a set's root audio data */
614 union ir_setdata_t
* ir_set_audio
615 ( struct ir_set_t
* set
)
616 { return (union ir_setdata_t
*) set
->audio
; }
618 /* Return a set's root link data */
619 union ir_setdata_t
* ir_set_link
620 ( struct ir_set_t
* set
)
621 { return (union ir_setdata_t
*) set
->links
; }
623 #define assert_link(linkdata) do { \
624 if (linkdata->header.type != LDAT) \
625 eprintf("Data %s is not a link\n", linkdata->header.data_name); \
628 /* Return the link type */
629 enum ltype ir_linkdata_type
630 ( union ir_setdata_t
* linkdata
)
631 { assert_link(linkdata
);
632 return linkdata
->link
.type
;
635 /* Return the link type */
636 uint32_t ir_linkdata_ref
637 ( union ir_setdata_t
* linkdata
)
638 { assert_link(linkdata
);
639 return linkdata
->link
.setld
->ref
;
642 /* Return the current target set, resolving it first if not present */
643 struct ir_set_t
* ir_linkdata_set
644 ( union ir_setdata_t
* linkdata
)
645 { assert_link(linkdata
);
646 if (linkdata
->link
.trg_set
== NULL
)
647 ir_linkdata_resolve_set(linkdata
);
648 return linkdata
->link
.trg_set
;
651 /* Resolve and assign the link's target set */
653 void ir_linkdata_resolve_set
654 ( union ir_setdata_t
* linkdata
)
655 { struct ir_class_t
* class_iter
;
656 struct ir_namelist_t
* namelist_iter
,* namelist_iter_last
;
657 struct ir_setld_t
* setld
;
658 struct ir_classld_t
* classld
;
659 struct ir_set_t
* set
;
662 assert_link(linkdata
);
663 setld
= linkdata
->link
.setld
;
664 if (linkdata
->link
.setld
== NULL
)
665 eprintf("Link data is invalid\n");
666 classld
= linkdata
->link
.classld
;
668 { namelist_iter
= classld
->namelist
;
669 if (classld
->root_class
== NULL
)
670 eprintf("No root class for classld\n");
671 class_iter
= classld
->root_class
->nextchild
;
672 namelist_iter_last
= NULL
;
673 while (class_iter
!= NULL
)
674 { if (classnames_identical(class_iter
->name
, namelist_iter
->name
))
675 { if (namelist_iter
== classld
->namelist_head
)
677 class_iter
= class_iter
->nextchild
;
678 namelist_iter_last
= namelist_iter
;
679 namelist_iter
= namelist_iter
->nextsib
;
682 class_iter
= class_iter
->nextsib
;
684 if (class_iter
== NULL
)
685 { if (namelist_iter_last
)
686 eprintf("No such subclass \"%s\" of class \"%s\"\n",
688 namelist_iter_last
->name
);
690 eprintf("No such class \"%s\"\n", namelist_iter
->name
);
692 set
= class_iter
->root_set
;
695 set
= ir_set_from_ref(setld
->ref
);
697 eprintf("Initial set resolution failed\n");
698 namelist_iter
= setld
->namelist
;
699 namelist_iter_last
= NULL
;
700 if (setld
->namelist
!= NULL
)
701 { while (set
!= NULL
)
702 { if (bytes_identical(set
->name
, namelist_iter
->name
))
703 { if (namelist_iter
== setld
->namelist_head
)
705 set
= set
->nextchild
;
706 namelist_iter_last
= namelist_iter
;
707 namelist_iter
= namelist_iter
->nextsib
;
713 { if (namelist_iter_last
)
714 eprintf("No such subset \"%s\" of set \"%s\"\n",
716 namelist_iter_last
->name
);
718 eprintf("No such set \"%s\" in class \"%s\"\n",
723 linkdata
->link
.trg_set
= set
;
726 /* Get a setdata's next sibling */
727 union ir_setdata_t
* ir_setdata_nextsib
728 ( union ir_setdata_t
* setdata
)
729 { return setdata
->header
.nextsib
; }
731 /* Get a setdata's name */
732 uint8_t* ir_setdata_name
733 ( union ir_setdata_t
* setdata
)
734 { return setdata
->header
.data_name
; }
736 /* Get a setdata's filename */
737 uint8_t* ir_setdata_filename
738 ( union ir_setdata_t
* setdata
)
739 { return setdata
->header
.src_filename
; }
741 /* Get a setdata's file position */
743 ( union ir_setdata_t
* setdata
)
744 { return setdata
->header
.filepos
; }
746 /* Set a setdata's file position */
747 void ir_setdata_assign_fpos
748 ( union ir_setdata_t
* setdata
,
751 { setdata
->header
.filepos
= newpos
; }
753 /* Return a framebox's specified framesheet */
754 union ir_setdata_t
* ir_framebox_framesheet
755 ( union ir_setdata_t
* fbox
,
758 { if (fbox
->header
.type
!= FBDAT
)
759 eprintf("Data %s is not a framebox\n", fbox
->header
.data_name
);
760 return (union ir_setdata_t
*) &fbox
->framebox
.framesheets
[facing
];
763 /* Return a framebox's specified mapsheet */
764 union ir_setdata_t
* ir_framebox_mapsheet
765 ( union ir_setdata_t
* fbox
,
768 { if (fbox
->header
.type
!= FBDAT
)
769 eprintf("Data %s is not a framebox\n", fbox
->header
.data_name
);
770 return (union ir_setdata_t
*) &fbox
->framebox
.mapsheets
[facing
];
773 /* Return a framedata's frame info */
774 struct ir_frameinfo_t
* ir_framedata_frameinfo
775 ( union ir_setdata_t
* framedata
)
776 { if (framedata
->header
.type
!= MSDAT
&& framedata
->header
.type
!= FSDAT
)
777 eprintf("Data %s is not a framedata\n", framedata
->header
.data_name
);
778 return &framedata
->mapsheet
.frameinfo
;
785 ( const uint8_t* name_src
)
786 { const uint8_t* iter
;
790 name
= (uint8_t*)namepages
.head
->header
.head
;
792 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && *iter
!= '.' && head_mem
; head_mem
--)
793 *(namepages
.head
->header
.head
)++ = *iter
++;
794 if (head_mem
< 1) //not enough room
795 { pagelist_alloc(namepages
);
798 *(namepages
.head
->header
.head
)++ = '\0';
803 uint8_t* classname_alloc
804 ( const uint8_t* name_src
)
805 { const uint8_t* iter
;
809 name
= (uint8_t*)namepages
.head
->header
.head
;
811 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
812 *(namepages
.head
->header
.head
)++ = *iter
++;
813 if (head_mem
< 1) //not enough room
814 { pagelist_alloc(namepages
);
817 *(namepages
.head
->header
.head
)++ = '\0';
821 static void crawl_class(struct ir_class_t
*);
822 static void crawl_set(struct ir_set_t
*,int);
825 int binout_init(ir_class
);
827 { uprintf("IR From Directory: %s\n",getcwd(NULL
,255));
828 crawl_class(&root_class
);
829 if (root_class
.root_set
!= NULL
)
830 crawl_set(root_class
.root_set
, 0);
831 uprintf("starting binaryout \n");
832 binout_init(&root_class
);
838 ( struct ir_class_t
* class )
839 { struct ir_class_t
* iter
;
840 for (iter
= class->nextchild
; iter
!= NULL
; iter
= iter
->nextsib
)
841 { wprintf("Crawling class %U/\n", iter
->name
);
842 if(chdir((char*)iter
->name
))
843 eprintf("CHDIR %U from %s\n",iter
->name
,getcwd(NULL
,255));
845 if (iter
->root_set
!= NULL
)
846 crawl_set(iter
->root_set
, 0);
847 uprintf("%U\\\n",iter
->name
);
849 eprintf("CHDIR ..\n");
850 wprintf("Finished crawling class %U/\n", iter
->name
);
854 #define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)
855 #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))
858 ( struct ir_set_t
* set
,
861 { struct ir_set_t
* iter
;
868 for(iter
= set
; iter
!= NULL
; iter
= iter
->nextchild
)
869 { uprintf("[%10U]", iter
->name
);
876 if (((iter
= pop_setp())->nextsib
) != NULL
)
877 crawl_set(iter
->nextsib
,i
);