fixes
[henge/apc.git] / src / ir.c
1 /*!@file
2 \brief IR Memory Implementation
3 \details Intermediary memory management
4 \author Jordan Lavatai
5 \date Aug 2016
6 ----------------------------------------------------------------------------*/
7 /* Standard */
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*
13 #include <errno.h>
14 /* Unicode */
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
19 /* Local */
20 #include "print.h"
21 #include "apc.h"
22 #include "ir.h"
23 #include "pagenode.h"
24 #undef do_error
25 #define do_error(...) exit(-1)
26 #define XXH_PRIVATE_API
27 #include "../xxHash/xxhash.h"
28 /* Public */
29 int ir_init(void);
30 void ir_quit(void);
31 void ir_test(void);
32 int ir_linker(void);
33 int ir_condenser(void);
34 /* Set data mem */
35 enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT };
36 struct ir_namelist_t;
37 struct ir_namelist_t
38 { struct ir_namelist_t* nextsib;
39 uint8_t* name;
40 };
41 struct ir_classld_t
42 { struct ir_class_t* root_class;
43 struct ir_namelist_t* namelist, * namelist_head;
44 };
45 struct ir_setld_t
46 { struct ir_classld_t* classld;
47 uint32_t ref;
48 struct ir_namelist_t* namelist, * namelist_head;
49 };
50 struct ir_setdata_header_t
51 { enum dtype type;
52 uint8_t* src_filename, * data_name;
53 union ir_setdata_t* nextsib;
54 long filepos;
55 };
56 struct ir_framedata_t
57 { struct ir_setdata_header_t header;
58 struct ir_frameinfo_t frameinfo;
59 };
60 struct ir_framebox_t
61 { struct ir_setdata_header_t header;
62 struct ir_framedata_t framesheets[FACING_MAX];
63 struct ir_framedata_t mapsheets[FACING_MAX];
64 };
65 struct ir_simplex_t { struct ir_setdata_header_t header; };
66 struct ir_link_t
67 { struct ir_setdata_header_t header;
68 struct ir_classld_t* classld;
69 struct ir_setld_t* setld;
70 enum ltype type;
71 };
72 union ir_setdata_t
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;
79 };
80 struct ir_class_t
81 { struct ir_class_t* nextchild, * nextsib;
82 struct ir_set_t* root_set;
83 uint8_t* name;
84 long filepos;
85 };
86 struct ir_set_t
87 { struct ir_set_t* nextchild, * nextsib;
88 uint32_t ref;
89 uint8_t* name;
90 struct ir_framebox_t* frameboxes;
91 struct ir_simplex_t* audio;
92 struct ir_link_t* links;
93 long filepos;
94 };
95 /* Functions */
96 static inline
97 struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*,uint8_t*);
98 static inline
99 union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int);
100 static inline
101 int bytes_identical(const uint8_t*,const uint8_t*);
102 static inline
103 int classnames_identical(const uint8_t*,const uint8_t*);
104 static
105 uint8_t* name_alloc(const uint8_t*);
106 static
107 uint8_t* classname_alloc(const uint8_t*);
108 #define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
109 #define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)
110 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
111 extern //apc.c
112 long sys_pagesize;
113 static
114 struct pagelist_t datapages, namepages, refhashpages;
115 static
116 struct ir_class_t root_class = { .name = (uint8_t*)"." };
117
118 /* Init */
119 int ir_init
120 ( void )
121 { pagelist_init(datapages, (size_t)SYS_PAGESIZE);
122 pagelist_init(namepages, (size_t)NAME_PAGESIZE);
123 pagelist_init(refhashpages, (size_t)SYS_PAGESIZE);
124
125 return 0;
126 }
127
128 /* Quit/Cleanup */
129 void ir_quit
130 ( void )
131 { pagenode_free(datapages.root);
132 pagenode_free(namepages.root);
133 pagenode_free(refhashpages.root);
134
135 }
136
137 /* Link */
138 int ir_linker
139 ( void )
140 {
141 return 0;
142 }
143
144 /* Condense */
145 int ir_condenser
146 ( void )
147 { return 0; }
148
149 /* Return the class's name string */
150 uint8_t* ir_class_name
151 ( struct ir_class_t* class )
152 { return class->name; }
153
154 /* Return a pointer to the root class */
155 struct ir_class_t* ir_class_root
156 ( void )
157 { return &root_class; }
158
159 /* Add a subclass to a class
160 Attempts to create a new subclass in the provided class, returning
161 the class if it already exists
162 */
163 struct ir_class_t* ir_class_addchild
164 ( struct ir_class_t* class,
165 const uint8_t* name
166 )
167 { struct ir_class_t* iter;
168 if (class->nextchild == NULL)
169 { class->nextchild = struct_alloc(ir_class_t);
170 struct_clear(class->nextchild);
171 class->nextchild->name = classname_alloc(name);
172 return class->nextchild;
173 }
174 iter = class->nextchild;
175 if (iter->name == NULL)
176 eprintf("Null name pointer in class %p\n", iter);
177 if (name == NULL)
178 eprintf("Null child added to class %s\n", iter->name);
179 check:
180 if (classnames_identical(iter->name, name))
181 return iter;
182 if (iter->nextsib != NULL)
183 { iter = iter->nextsib;
184 goto check;
185 }
186 iter->nextsib = struct_alloc(ir_class_t);
187 struct_clear(iter->nextsib);
188 iter->nextsib->name = classname_alloc(name);
189 return iter->nextsib;
190 }
191
192 /* Add a set to a class
193 Attempts to create a new root set in the specified class, returning
194 the set if it already exists
195 */
196 struct ir_set_t* ir_class_addset
197 ( struct ir_class_t* class,
198 const uint8_t* name
199 )
200 { struct ir_set_t* iter;
201 if (class->root_set == NULL)
202 { class->root_set = struct_alloc(ir_set_t);
203 struct_clear(class->root_set);
204 class->root_set->name = name_alloc(name);
205 return class->root_set;
206 }
207 iter = class->root_set;
208 if (iter->name == NULL)
209 eprintf("Null name pointer in class %p\n", iter);
210 if (name == NULL)
211 eprintf("Null set added to class %U\n", iter->name);
212 check:
213 if (bytes_identical(iter->name, name))
214 return iter;
215 if (iter->nextsib != NULL)
216 { iter = iter->nextsib;
217 goto check;
218 }
219 iter->nextsib = struct_alloc(ir_set_t);
220 struct_clear(iter->nextsib);
221 iter->nextsib->name = name_alloc(name);
222 return iter->nextsib;
223 }
224
225 /* Get the root set of the class */
226 struct ir_set_t* ir_class_rootset
227 ( struct ir_class_t* class )
228 { return class->root_set; }
229
230 struct ir_set_t* ir_set_from_ref
231 ( uint32_t ref )
232 { uint16_t hash;
233 struct ir_set_t** iters;
234 struct pagenode_t* iterp;
235 iterp = refhashpages.root;
236 hash = REFHASH(ref);
237 do
238 iters = ((struct ir_set_t**) iterp->root) + hash;
239 while (*iters != NULL && (*iters)->ref != ref && (iterp = iterp->header.next) != NULL);
240 return *iters;
241 }
242
243
244 /* Add a set to a set
245 Attempts to create a new subset of the specified set, returning the
246 child if it already exists
247 */
248 struct ir_set_t* ir_set_addchild
249 ( struct ir_set_t* set,
250 const uint8_t* name
251 )
252 { struct ir_set_t* iter;
253 if (set->nextchild == NULL)
254 { set->nextchild = struct_alloc(ir_set_t);
255 struct_clear(set->nextchild);
256 set->nextchild->name = name_alloc(name);
257 return set->nextchild;
258 }
259 iter = set->nextchild;
260 if (name == NULL)
261 eprintf("Null child added to set %s\n", iter->name);
262 if (iter->name == NULL)
263 eprintf("Null name pointer in set %p\n", iter);
264 check:
265 if (bytes_identical(iter->name, name))
266 return iter;
267 if (iter->nextsib != NULL)
268 { iter = iter->nextsib;
269 goto check;
270 }
271 iter->nextsib = struct_alloc(ir_set_t);
272 struct_clear(iter->nextsib);
273 iter->nextsib->name = name_alloc(name);
274 return iter->nextsib;
275 }
276
277 /* Add a framebox to a set
278 Attempts to create a new framebox of the specified set, returning
279 the framebox if it already exists
280 Name is not allocated, but assigned, unlike other "XXX_add" functions where
281 name is duplicated into IR's internal array.
282 */
283 static inline
284 struct ir_framebox_t* ir_set_add_framebox
285 ( struct ir_set_t* set,
286 uint8_t* name
287 )
288 { struct ir_framebox_t* iter;
289 if (set->frameboxes == NULL)
290 { set->frameboxes = struct_alloc(ir_framebox_t);
291 struct_clear(set->frameboxes);
292 set->frameboxes->header.data_name = name;
293 return set->frameboxes;
294 }
295 iter = set->frameboxes;
296 check:
297 if (bytes_identical(iter->header.data_name, name))
298 return iter;
299 if (iter->header.nextsib != NULL)
300 { iter = (struct ir_framebox_t*) iter->header.nextsib;
301 goto check;
302 }
303 iter->header.nextsib = (union ir_setdata_t*) struct_alloc(ir_framebox_t);
304 struct_clear(iter->header.nextsib);
305 iter->header.nextsib->header.data_name = name;
306 return (struct ir_framebox_t*) (iter->header.nextsib);
307 }
308
309 /* Match two null-terminated bytestrings
310 Return 1 if the two bytestrings are identical, else 0
311 */
312 static inline
313 int bytes_identical
314 ( const uint8_t* stra,
315 const uint8_t* strb
316 )
317 { int ca, cb;
318 do {
319 ca = *stra++;
320 cb = *strb++;
321 } while (ca && ca != '_' && ca == cb);
322 return (ca == cb);
323 }
324
325 static inline
326 int classnames_identical
327 ( const uint8_t* stra,
328 const uint8_t* strb
329 )
330 { int ca, cb;
331 do {
332 ca = *stra++;
333 cb = *strb++;
334 } while (ca && ca == cb);
335 return (ca == cb);
336 }
337
338 /* Return the name of the set */
339 uint8_t* ir_set_name
340 ( struct ir_set_t* set)
341 { return set->name; }
342
343 /* Return the next sib of the class */
344 struct ir_class_t* ir_class_nextsib
345 ( struct ir_class_t* class )
346 { return class->nextsib; }
347
348 /* Return the next sib of the class */
349 struct ir_class_t* ir_class_nextchild
350 ( struct ir_class_t* class )
351 { return class->nextchild; }
352
353 /* Get the file position of the class */
354 long ir_class_fpos
355 ( struct ir_class_t* class )
356 { return class->filepos; }
357
358 /* Set the file position of the class */
359 void ir_class_assign_fpos
360 ( struct ir_class_t* class,
361 long newpos
362 )
363 { class->filepos = newpos; }
364
365 /* Get the next sibling of the provided set */
366 struct ir_set_t* ir_set_nextsib
367 ( struct ir_set_t* set )
368 { return set->nextsib; }
369
370 /* Get the next child of the provided set */
371 struct ir_set_t* ir_set_nextchild
372 ( struct ir_set_t* set )
373 { return set->nextchild; }
374
375 /* Get the file position of the class */
376 long ir_set_fpos
377 ( struct ir_set_t* set )
378 { return set->filepos; }
379
380 /* Set the file position of the class */
381 void ir_set_assign_fpos
382 ( struct ir_set_t* set,
383 long newpos
384 )
385 { set->filepos = newpos; }
386
387 /* Assign Setdata to Set */
388 void ir_set_assign_data
389 ( struct ir_set_t* set,
390 union ir_setdata_t* setdata
391 )
392 { struct ir_framebox_t* framebox;
393 struct ir_simplex_t* simplex;
394 switch (setdata->header.type)
395 { case FSDAT:
396 framebox = ir_set_add_framebox(set, setdata->header.data_name);
397 if (framebox->framesheets[setdata->framesheet.frameinfo.facing].header.data_name != NULL)
398 wprintf("Duplicate framesheet [%i] %s\n",
399 setdata->framesheet.frameinfo.facing, setdata->header.data_name);
400 framebox->framesheets[setdata->framesheet.frameinfo.facing] = setdata->framesheet;
401 break;
402 case MSDAT:
403 framebox = ir_set_add_framebox(set, setdata->header.data_name);
404 if (framebox->mapsheets[setdata->mapsheet.frameinfo.facing].header.data_name != NULL)
405 wprintf("Duplicate mapsheet [%i] %s\n",
406 setdata->mapsheet.frameinfo.facing, setdata->header.data_name);
407 framebox->mapsheets[setdata->mapsheet.frameinfo.facing] = setdata->mapsheet;
408 break;
409 case ADAT:
410 if (set->audio == NULL)
411 { set->audio = (struct ir_simplex_t*) setdata;
412 return;
413 }
414 simplex = set->audio;
415 while (simplex->header.nextsib != NULL)
416 if (bytes_identical(simplex->header.data_name, setdata->header.data_name))
417 { wprintf("Duplicate audio %s\n", setdata->header.data_name);
418 *simplex = setdata->audio;
419 //setdata is now a pointer to redundant, unused memory.
420 return;
421 }
422 else
423 simplex = (struct ir_simplex_t*) simplex->header.nextsib;
424 setdata->audio.header.nextsib = (union ir_setdata_t*) set->audio;
425 set->audio = (struct ir_simplex_t*) setdata;
426 break;
427 case LDAT:
428 setdata->link.header.nextsib = (union ir_setdata_t*) set->links;
429 set->links = (struct ir_link_t*) setdata;
430 break;
431 default:
432 fprintf(stderr, "Unknown setdata type %x\n", setdata->header.type);
433 exit(-1);
434 }
435 }
436
437 void ir_set_assign_ref
438 ( struct ir_set_t* set,
439 uint32_t ref
440 )
441 { uint16_t hash, oldhash;
442 struct ir_set_t** iters;
443 struct pagenode_t* iterp;
444 uint32_t oldref;
445 oldref = set->ref;
446 oldhash = 0;
447 hash = REFHASH(ref);
448 iterp = refhashpages.root;
449 check_depth:
450 iters = ((struct ir_set_t**) iterp->root) + hash;
451 if (*iters == NULL || *iters == set)
452 *iters = set;
453 else
454 { if (iterp->header.next == NULL)
455 pagelist_alloc(refhashpages);
456 iterp = iterp->header.next;
457 goto check_depth;
458 }
459 if (oldref != 0)
460 { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref, ref, set->name);
461 if (oldhash != 0)
462 *iters = NULL;
463 else
464 { oldhash = hash;
465 hash = REFHASH(oldref);
466 goto check_depth;
467 }
468 }
469 set->ref = ref;
470 }
471
472 void ir_data_assign_path
473 ( union ir_setdata_t* setdata,
474 const uint8_t* path
475 )
476 { if (path == NULL)
477 eprintf("Null path in data %s\n", setdata->header.data_name);
478 if (setdata->header.src_filename != NULL)
479 wprintf("Path override: %s -> %s for setdata %s\n",
480 setdata->header.src_filename, path, setdata->header.data_name);
481 setdata->header.src_filename = name_alloc(path);
482 }
483
484 union ir_setdata_t* ir_framesheet
485 ( const uint8_t* name,
486 apc_facing d,
487 int width,
488 int height
489 )
490 { return ir_framedata(FSDAT, name, d, width, height); }
491
492 union ir_setdata_t* ir_mapsheet
493 ( const uint8_t* name,
494 apc_facing d,
495 int width,
496 int height
497 )
498 { return ir_framedata(MSDAT, name, d, width, height); }
499
500 static inline
501 union ir_setdata_t* ir_framedata
502 ( enum dtype type,
503 const uint8_t* name,
504 apc_facing d,
505 int width,
506 int height
507 )
508 { struct ir_framedata_t* framedata = struct_alloc(ir_framedata_t);
509 struct_clear(framedata);
510 if (name == NULL)
511 eprintf("Null name in set allocation\n");
512 framedata->header.type = type;
513 framedata->header.data_name = name_alloc(name);
514 framedata->frameinfo.facing = d;
515 framedata->frameinfo.w = width;
516 framedata->frameinfo.h = height;
517 return (union ir_setdata_t*) framedata;
518 }
519
520 union ir_setdata_t* ir_audio
521 ( const uint8_t* name )
522 { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t);
523 struct_clear(audio);
524 if (name == NULL)
525 eprintf("Null audio\n");
526 audio->header.type = ADAT;
527 audio->header.data_name = name_alloc(name);
528 return (union ir_setdata_t*) audio;
529 }
530
531
532 /* Create classld that points to a class */
533 struct ir_classld_t* ir_classld_from_class
534 ( struct ir_class_t* class )
535 { struct ir_classld_t* classld;
536 if (class == NULL)
537 eprintf("Null class in classld\n");
538 classld = struct_alloc(ir_classld_t);
539 struct_clear(classld);
540 classld->root_class = class;
541 return classld;
542 }
543
544 struct ir_setld_t* ir_setld_from_ref
545 ( uint32_t ref )
546 { struct ir_setld_t* setld;
547 setld = struct_alloc(ir_setld_t);
548 struct_clear(setld);
549 setld->ref = ref;
550 return setld;
551 }
552
553 struct ir_setld_t* ir_setld_from_classld
554 ( struct ir_classld_t* classld,
555 const uint8_t* name
556 )
557 { struct ir_setld_t* setld;
558 setld = struct_alloc(ir_setld_t);
559 struct_clear(setld);
560 setld->namelist = struct_alloc(ir_namelist_t);
561 struct_clear(setld->namelist);
562 setld->namelist_head = setld->namelist;
563 setld->namelist_head->name = name_alloc(name);
564 setld->classld = classld;
565 return setld;
566 }
567
568 struct ir_setld_t* ir_setld_addchild
569 ( struct ir_setld_t* setld,
570 const uint8_t* name
571 )
572 { if (setld->namelist == NULL)
573 { setld->namelist = struct_alloc(ir_namelist_t);
574 struct_clear(setld->namelist);
575 setld->namelist_head = setld->namelist;
576 }
577 else
578 { setld->namelist_head->nextsib = struct_alloc(ir_namelist_t);
579 struct_clear(setld->namelist_head->nextsib);
580 setld->namelist_head = setld->namelist_head->nextsib;
581 }
582 setld->namelist_head->name = name_alloc(name);
583 return setld;
584 }
585
586 union ir_setdata_t* ir_link
587 ( enum ltype link_type,
588 struct ir_setld_t* setld,
589 const uint8_t* name
590 )
591 { struct ir_link_t* link;
592 link = struct_alloc(ir_link_t);
593 struct_clear(link);
594 link->header.type = LDAT;
595 link->type = link_type;
596 link->classld = setld->classld;
597 link->setld = setld;
598 if (link_type != OLINK && name != NULL)
599 link->header.data_name = name_alloc(name);
600 return (union ir_setdata_t*) link;
601 }
602
603 /* Return a set's root framebox */
604 union ir_setdata_t* ir_set_framebox
605 ( struct ir_set_t* set )
606 { return (union ir_setdata_t*) set->frameboxes; }
607
608 /* Return a set's root audio data */
609 union ir_setdata_t* ir_set_audio
610 ( struct ir_set_t* set )
611 { return (union ir_setdata_t*) set->audio; }
612
613 /* Return a set's root link data */
614 union ir_setdata_t* ir_set_link
615 ( struct ir_set_t* set )
616 { return (union ir_setdata_t*) set->links; }
617
618 /* Return the link type */
619 enum ltype ir_linkdata_type
620 ( union ir_setdata_t* linkdata )
621 { if (linkdata->header.type != LDAT)
622 eprintf("Data %s is not a link\n", linkdata->header.data_name);
623 return linkdata->link.type;
624 }
625
626 /* Return the link type */
627 uint32_t ir_linkdata_ref
628 ( union ir_setdata_t* linkdata )
629 { if (linkdata->header.type != LDAT)
630 eprintf("Data %s is not a link\n", linkdata->header.data_name);
631 return linkdata->link.setld->ref;
632 }
633
634 /* Get a setdata's next sibling */
635 union ir_setdata_t* ir_setdata_nextsib
636 ( union ir_setdata_t* setdata )
637 { return setdata->header.nextsib; }
638
639 /* Get a setdata's name */
640 uint8_t* ir_setdata_name
641 ( union ir_setdata_t* setdata )
642 { return setdata->header.data_name; }
643
644 /* Get a setdata's filename */
645 uint8_t* ir_setdata_filename
646 ( union ir_setdata_t* setdata )
647 { return setdata->header.src_filename; }
648
649 /* Get a setdata's file position */
650 long ir_setdata_fpos
651 ( union ir_setdata_t* setdata )
652 { return setdata->header.filepos; }
653
654 /* Set a setdata's file position */
655 void ir_setdata_assign_fpos
656 ( union ir_setdata_t* setdata,
657 long newpos
658 )
659 { setdata->header.filepos = newpos; }
660
661 /* Return a framebox's specified framesheet */
662 union ir_setdata_t* ir_framebox_framesheet
663 ( union ir_setdata_t* fbox,
664 apc_facing facing
665 )
666 { if (fbox->header.type != FBDAT)
667 eprintf("Data %s is not a framebox\n", fbox->header.data_name);
668 return (union ir_setdata_t*) &fbox->framebox.framesheets[facing];
669 }
670
671 /* Return a framebox's specified mapsheet */
672 union ir_setdata_t* ir_framebox_mapsheet
673 ( union ir_setdata_t* fbox,
674 apc_facing facing
675 )
676 { if (fbox->header.type != FBDAT)
677 eprintf("Data %s is not a framebox\n", fbox->header.data_name);
678 return (union ir_setdata_t*) &fbox->framebox.mapsheets[facing];
679 }
680
681 /* Return a framedata's frame info */
682 struct ir_frameinfo_t* ir_framedata_mapsheet
683 ( union ir_setdata_t* framedata )
684 { if (framedata->header.type != MSDAT && framedata->header.type != FSDAT)
685 eprintf("Data %s is not a framedata\n", framedata->header.data_name);
686 return &framedata->mapsheet.frameinfo;
687 }
688
689 /** Allocators **/
690 static
691 uint8_t* name_alloc
692 ( const uint8_t* name_src )
693 { const uint8_t* iter;
694 uint8_t* name;
695 int head_mem;
696 copy:
697 name = (uint8_t*)namepages.head->header.head;
698 iter = name_src;
699 for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && *iter != '.' && head_mem; head_mem--)
700 *(namepages.head->header.head)++ = *iter++;
701 if (head_mem < 1) //not enough room
702 { pagelist_alloc(namepages);
703 goto copy;
704 }
705 *(namepages.head->header.head)++ = '\0';
706 return name;
707 }
708
709 static
710 uint8_t* classname_alloc
711 ( const uint8_t* name_src )
712 { const uint8_t* iter;
713 uint8_t* name;
714 int head_mem;
715 copy:
716 name = (uint8_t*)namepages.head->header.head;
717 iter = name_src;
718 for (head_mem = PL_HEADMEM(namepages); *iter && head_mem; head_mem--)
719 *(namepages.head->header.head)++ = *iter++;
720 if (head_mem < 1) //not enough room
721 { pagelist_alloc(namepages);
722 goto copy;
723 }
724 *(namepages.head->header.head)++ = '\0';
725 return name;
726 }
727
728 static void crawl_class(struct ir_class_t*);
729 static void crawl_set(struct ir_set_t*,int);
730
731 extern
732 int binout_init(ir_class);
733 void ir_test(void)
734 { uprintf("IR From Directory: %s\n",getcwd(NULL,255));
735 crawl_class(&root_class);
736 if (root_class.root_set != NULL)
737 crawl_set(root_class.root_set, 0);
738 uprintf("starting binaryout \n");
739 binout_init(&root_class);
740 }
741
742
743 static
744 void crawl_class
745 ( struct ir_class_t* class )
746 { struct ir_class_t* iter;
747 for (iter = class->nextchild; iter != NULL; iter = iter->nextsib)
748 { wprintf("Crawling class %U/\n", iter->name);
749 if(chdir((char*)iter->name))
750 eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255));
751 crawl_class(iter);
752 if (iter->root_set != NULL)
753 crawl_set(iter->root_set, 0);
754 uprintf("%U\\\n",iter->name);
755 if (chdir(".."))
756 eprintf("CHDIR ..\n");
757 wprintf("Finished crawling class %U/\n", iter->name);
758 }
759 }
760
761 #define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)
762 #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))
763 static
764 void crawl_set
765 ( struct ir_set_t* set,
766 int depth
767 )
768 { struct ir_set_t* iter;
769 int i;
770 i = depth * 12;
771 while (i--)
772 putchar('.');
773 i = depth;
774
775 for(iter = set; iter != NULL; iter = iter->nextchild)
776 { uprintf("[%10U]", iter->name);
777 push_setp(iter);
778 i++;
779 }
780
781 putchar('\n');
782 while (--i >= depth)
783 if (((iter = pop_setp())->nextsib) != NULL)
784 crawl_set(iter->nextsib,i);
785 }