added stb, more binaryout changes"
[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 struct ir_set_t* trg_set;
71 enum ltype type;
72 };
73 union ir_setdata_t
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;
80 };
81 struct ir_class_t
82 { struct ir_class_t* nextchild, * nextsib;
83 struct ir_set_t* root_set;
84 uint8_t* name;
85 long filepos;
86 };
87 struct ir_set_t
88 { struct ir_set_t* nextchild, * nextsib;
89 uint32_t ref;
90 uint8_t* name;
91 struct ir_framebox_t* frameboxes;
92 struct ir_simplex_t* audio;
93 struct ir_link_t* links;
94 long filepos;
95 };
96 /* Functions */
97 static inline
98 struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*,uint8_t*);
99 static inline
100 union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int);
101 static inline
102 void ir_linkdata_resolve_set(union ir_setdata_t*);
103 static inline
104 int bytes_identical(const uint8_t*,const uint8_t*);
105 static inline
106 int classnames_identical(const uint8_t*,const uint8_t*);
107 static
108 uint8_t* name_alloc(const uint8_t*);
109 static
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)))
114 extern //apc.c
115 long sys_pagesize;
116 extern //apc.c
117 char* apc_package_name;
118 static
119 struct pagelist_t datapages, namepages, refhashpages;
120 static
121 struct ir_class_t root_class;
122
123 /* Init */
124 int ir_init
125 ( void )
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;
130 return 0;
131 }
132
133 /* Quit/Cleanup */
134 void ir_quit
135 ( void )
136 { pagenode_free(datapages.root);
137 pagenode_free(namepages.root);
138 pagenode_free(refhashpages.root);
139
140 }
141
142 /* Link */
143 int ir_linker
144 ( void )
145 {
146 return 0;
147 }
148
149 /* Condense */
150 int ir_condenser
151 ( void )
152 { return 0; }
153
154 /* Return the class's name string */
155 uint8_t* ir_class_name
156 ( struct ir_class_t* class )
157 { return class->name; }
158
159 /* Return a pointer to the root class */
160 struct ir_class_t* ir_class_root
161 ( void )
162 { return &root_class; }
163
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
167 */
168 struct ir_class_t* ir_class_addchild
169 ( struct ir_class_t* class,
170 const uint8_t* name
171 )
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;
178 }
179 iter = class->nextchild;
180 if (iter->name == NULL)
181 eprintf("Null name pointer in class %p\n", iter);
182 if (name == NULL)
183 eprintf("Null child added to class %s\n", iter->name);
184 check:
185 if (classnames_identical(iter->name, name))
186 return iter;
187 if (iter->nextsib != NULL)
188 { iter = iter->nextsib;
189 goto check;
190 }
191 iter->nextsib = struct_alloc(ir_class_t);
192 struct_clear(iter->nextsib);
193 iter->nextsib->name = classname_alloc(name);
194 return iter->nextsib;
195 }
196
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
200 */
201 struct ir_set_t* ir_class_addset
202 ( struct ir_class_t* class,
203 const uint8_t* name
204 )
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;
211 }
212 iter = class->root_set;
213 if (iter->name == NULL)
214 eprintf("Null name pointer in class %p\n", iter);
215 if (name == NULL)
216 eprintf("Null set added to class %U\n", iter->name);
217 check:
218 if (bytes_identical(iter->name, name))
219 return iter;
220 if (iter->nextsib != NULL)
221 { iter = iter->nextsib;
222 goto check;
223 }
224 iter->nextsib = struct_alloc(ir_set_t);
225 struct_clear(iter->nextsib);
226 iter->nextsib->name = name_alloc(name);
227 return iter->nextsib;
228 }
229
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; }
234
235 struct ir_set_t* ir_set_from_ref
236 ( uint32_t ref )
237 { uint16_t hash;
238 struct ir_set_t** iters;
239 struct pagenode_t* iterp;
240 iterp = refhashpages.root;
241 hash = REFHASH(ref);
242 do
243 iters = ((struct ir_set_t**) iterp->root) + hash;
244 while (*iters != NULL && (*iters)->ref != ref && (iterp = iterp->header.next) != NULL);
245 return *iters;
246 }
247
248
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
252 */
253 struct ir_set_t* ir_set_addchild
254 ( struct ir_set_t* set,
255 const uint8_t* name
256 )
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;
263 }
264 iter = set->nextchild;
265 if (name == NULL)
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);
269 check:
270 if (bytes_identical(iter->name, name))
271 return iter;
272 if (iter->nextsib != NULL)
273 { iter = iter->nextsib;
274 goto check;
275 }
276 iter->nextsib = struct_alloc(ir_set_t);
277 struct_clear(iter->nextsib);
278 iter->nextsib->name = name_alloc(name);
279 return iter->nextsib;
280 }
281
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.
287 */
288 static inline
289 struct ir_framebox_t* ir_set_add_framebox
290 ( struct ir_set_t* set,
291 uint8_t* name
292 )
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;
299 }
300 iter = set->frameboxes;
301 check:
302 if (bytes_identical(iter->header.data_name, name))
303 return iter;
304 if (iter->header.nextsib != NULL)
305 { iter = (struct ir_framebox_t*) iter->header.nextsib;
306 goto check;
307 }
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);
312 }
313
314 /* Match two null-terminated bytestrings
315 Return 1 if the two bytestrings are identical, else 0
316 */
317 static inline
318 int bytes_identical
319 ( const uint8_t* stra,
320 const uint8_t* strb
321 )
322 { int ca, cb;
323 do {
324 ca = *stra++;
325 cb = *strb++;
326 } while (ca && ca != '_' && ca == cb);
327 return (ca == cb);
328 }
329
330 static inline
331 int classnames_identical
332 ( const uint8_t* stra,
333 const uint8_t* strb
334 )
335 { int ca, cb;
336 do {
337 ca = *stra++;
338 cb = *strb++;
339 } while (ca && ca == cb);
340 return (ca == cb);
341 }
342
343 /* Return the name of the set */
344 uint8_t* ir_set_name
345 ( struct ir_set_t* set)
346 { return set->name; }
347
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; }
352
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; }
357
358 /* Get the file position of the class */
359 long ir_class_fpos
360 ( struct ir_class_t* class )
361 { return class->filepos; }
362
363 /* Set the file position of the class */
364 void ir_class_assign_fpos
365 ( struct ir_class_t* class,
366 long newpos
367 )
368 { class->filepos = newpos; }
369
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; }
374
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; }
379
380 /* Get the file position of the class */
381 long ir_set_fpos
382 ( struct ir_set_t* set )
383 { return set->filepos; }
384
385 /* Set the file position of the class */
386 void ir_set_assign_fpos
387 ( struct ir_set_t* set,
388 long newpos
389 )
390 { set->filepos = newpos; }
391
392 /* Assign Setdata to Set */
393 void ir_set_assign_data
394 ( struct ir_set_t* set,
395 union ir_setdata_t* setdata
396 )
397 { struct ir_framebox_t* framebox;
398 struct ir_simplex_t* simplex;
399 switch (setdata->header.type)
400 { case FSDAT:
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;
406 break;
407 case MSDAT:
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;
413 break;
414 case ADAT:
415 if (set->audio == NULL)
416 { set->audio = (struct ir_simplex_t*) setdata;
417 return;
418 }
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.
425 return;
426 }
427 else
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;
431 break;
432 case LDAT:
433 setdata->link.header.nextsib = (union ir_setdata_t*) set->links;
434 set->links = (struct ir_link_t*) setdata;
435 break;
436 default:
437 fprintf(stderr, "Unknown setdata type %x\n", setdata->header.type);
438 exit(-1);
439 }
440 }
441
442 void ir_set_assign_ref
443 ( struct ir_set_t* set,
444 uint32_t ref
445 )
446 { uint16_t hash, oldhash;
447 struct ir_set_t** iters;
448 struct pagenode_t* iterp;
449 uint32_t oldref;
450 oldref = set->ref;
451 oldhash = 0;
452 hash = REFHASH(ref);
453 iterp = refhashpages.root;
454 check_depth:
455 iters = ((struct ir_set_t**) iterp->root) + hash;
456 if (*iters == NULL || *iters == set)
457 *iters = set;
458 else
459 { if (iterp->header.next == NULL)
460 pagelist_alloc(refhashpages);
461 iterp = iterp->header.next;
462 goto check_depth;
463 }
464 if (oldref != 0)
465 { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref, ref, set->name);
466 if (oldhash != 0)
467 *iters = NULL;
468 else
469 { oldhash = hash;
470 hash = REFHASH(oldref);
471 goto check_depth;
472 }
473 }
474 set->ref = ref;
475 }
476
477 void ir_data_assign_path
478 ( union ir_setdata_t* setdata,
479 const uint8_t* path
480 )
481 { if (path == NULL)
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);
487 }
488
489 union ir_setdata_t* ir_framesheet
490 ( const uint8_t* name,
491 apc_facing d,
492 int width,
493 int height
494 )
495 { return ir_framedata(FSDAT, name, d, width, height); }
496
497 union ir_setdata_t* ir_mapsheet
498 ( const uint8_t* name,
499 apc_facing d,
500 int width,
501 int height
502 )
503 { return ir_framedata(MSDAT, name, d, width, height); }
504
505 static inline
506 union ir_setdata_t* ir_framedata
507 ( enum dtype type,
508 const uint8_t* name,
509 apc_facing d,
510 int width,
511 int height
512 )
513 { struct ir_framedata_t* framedata = struct_alloc(ir_framedata_t);
514 struct_clear(framedata);
515 if (name == NULL)
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;
523 }
524
525 union ir_setdata_t* ir_audio
526 ( const uint8_t* name )
527 { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t);
528 struct_clear(audio);
529 if (name == NULL)
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;
534 }
535
536
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;
541 if (class == NULL)
542 eprintf("Null class in classld\n");
543 classld = struct_alloc(ir_classld_t);
544 struct_clear(classld);
545 classld->root_class = class;
546 return classld;
547 }
548
549 struct ir_setld_t* ir_setld_from_ref
550 ( uint32_t ref )
551 { struct ir_setld_t* setld;
552 setld = struct_alloc(ir_setld_t);
553 struct_clear(setld);
554 setld->ref = ref;
555 return setld;
556 }
557
558 struct ir_setld_t* ir_setld_from_classld
559 ( struct ir_classld_t* classld,
560 const uint8_t* name
561 )
562 { struct ir_setld_t* setld;
563 setld = struct_alloc(ir_setld_t);
564 struct_clear(setld);
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;
570 return setld;
571 }
572
573 struct ir_setld_t* ir_setld_addchild
574 ( struct ir_setld_t* setld,
575 const uint8_t* name
576 )
577 { if (setld->namelist == NULL)
578 { setld->namelist = struct_alloc(ir_namelist_t);
579 struct_clear(setld->namelist);
580 setld->namelist_head = setld->namelist;
581 }
582 else
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;
586 }
587 setld->namelist_head->name = name_alloc(name);
588 return setld;
589 }
590
591 union ir_setdata_t* ir_link
592 ( enum ltype link_type,
593 struct ir_setld_t* setld,
594 const uint8_t* name
595 )
596 { struct ir_link_t* link;
597 link = struct_alloc(ir_link_t);
598 struct_clear(link);
599 link->header.type = LDAT;
600 link->type = link_type;
601 link->classld = setld->classld;
602 link->setld = setld;
603 if (link_type != OLINK && name != NULL)
604 link->header.data_name = name_alloc(name);
605 return (union ir_setdata_t*) link;
606 }
607
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; }
612
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; }
617
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; }
622
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); \
626 } while (0)
627
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;
633 }
634
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;
640 }
641
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;
649 }
650
651 /* Resolve and assign the link's target set */
652 static inline
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;
660 set = NULL;
661 class_iter = NULL;
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;
667 if (classld != NULL)
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)
676 break;
677 class_iter = class_iter->nextchild;
678 namelist_iter_last = namelist_iter;
679 namelist_iter = namelist_iter->nextsib;
680 }
681 else
682 class_iter = class_iter->nextsib;
683 }
684 if (class_iter == NULL)
685 { if (namelist_iter_last)
686 eprintf("No such subclass \"%s\" of class \"%s\"\n",
687 namelist_iter->name,
688 namelist_iter_last->name);
689 else
690 eprintf("No such class \"%s\"\n", namelist_iter->name);
691 }
692 set = class_iter->root_set;
693 }
694 else
695 set = ir_set_from_ref(setld->ref);
696 if (set == NULL)
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)
704 break;
705 set = set->nextchild;
706 namelist_iter_last = namelist_iter;
707 namelist_iter = namelist_iter->nextsib;
708 }
709 else
710 set = set->nextsib;
711 }
712 if (set == NULL)
713 { if (namelist_iter_last)
714 eprintf("No such subset \"%s\" of set \"%s\"\n",
715 namelist_iter->name,
716 namelist_iter_last->name);
717 else
718 eprintf("No such set \"%s\" in class \"%s\"\n",
719 namelist_iter->name,
720 class_iter->name);
721 }
722 }
723 linkdata->link.trg_set = set;
724 }
725
726 /* Assign a linkdatas trg_set */
727 void ir_linkdata_assign_set
728 ( struct ir_link_t* link, struct ir_set_t* set )
729 { link->trg_set = set; }
730
731 /* Assign a linkdatas type */
732 void ir_linkdata_assign_type
733 ( struct ir_link_t* link, ltype type; )
734 { link->type = type; }
735
736 /* Get a setdata's next sibling */
737 union ir_setdata_t* ir_setdata_nextsib
738 ( union ir_setdata_t* setdata )
739 { return setdata->header.nextsib; }
740
741 /* Get a setdata's name */
742 uint8_t* ir_setdata_name
743 ( union ir_setdata_t* setdata )
744 { return setdata->header.data_name; }
745
746 /* Get a setdata's filename */
747 uint8_t* ir_setdata_filename
748 ( union ir_setdata_t* setdata )
749 { return setdata->header.src_filename; }
750
751 /* Get a setdata's file position */
752 long ir_setdata_fpos
753 ( union ir_setdata_t* setdata )
754 { return setdata->header.filepos; }
755
756 /* Set a setdata's file position */
757 void ir_setdata_assign_fpos
758 ( union ir_setdata_t* setdata,
759 long newpos
760 )
761 { setdata->header.filepos = newpos; }
762
763 /* Assign a setdatas name */
764 void ir_setdata_assign_name
765 ( union ir_setdata_t* setdata, uint8_t* name )
766 { setdata->header.data_name = name;}
767
768 /* Return a framebox's specified framesheet */
769 union ir_setdata_t* ir_framebox_framesheet
770 ( union ir_setdata_t* fbox,
771 apc_facing facing
772 )
773 { if (fbox->header.type != FBDAT)
774 eprintf("Data %s is not a framebox\n", fbox->header.data_name);
775 return (union ir_setdata_t*) &fbox->framebox.framesheets[facing];
776 }
777
778 /* Return a framebox's specified mapsheet */
779 union ir_setdata_t* ir_framebox_mapsheet
780 ( union ir_setdata_t* fbox,
781 apc_facing facing
782 )
783 { if (fbox->header.type != FBDAT)
784 eprintf("Data %s is not a framebox\n", fbox->header.data_name);
785 return (union ir_setdata_t*) &fbox->framebox.mapsheets[facing];
786 }
787
788 /* Return a framedata's frame info */
789 struct ir_frameinfo_t* ir_framedata_frameinfo
790 ( union ir_setdata_t* framedata )
791 { if (framedata->header.type != MSDAT && framedata->header.type != FSDAT)
792 eprintf("Data %s is not a framedata\n", framedata->header.data_name);
793 return &framedata->mapsheet.frameinfo;
794 }
795
796
797 /** Allocators **/
798 static
799 uint8_t* name_alloc
800 ( const uint8_t* name_src )
801 { const uint8_t* iter;
802 uint8_t* name;
803 int head_mem;
804 copy:
805 name = (uint8_t*)namepages.head->header.head;
806 iter = name_src;
807 for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && *iter != '.' && head_mem; head_mem--)
808 *(namepages.head->header.head)++ = *iter++;
809 if (head_mem < 1) //not enough room
810 { pagelist_alloc(namepages);
811 goto copy;
812 }
813 *(namepages.head->header.head)++ = '\0';
814 return name;
815 }
816
817 static
818 uint8_t* classname_alloc
819 ( const uint8_t* name_src )
820 { const uint8_t* iter;
821 uint8_t* name;
822 int head_mem;
823 copy:
824 name = (uint8_t*)namepages.head->header.head;
825 iter = name_src;
826 for (head_mem = PL_HEADMEM(namepages); *iter && head_mem; head_mem--)
827 *(namepages.head->header.head)++ = *iter++;
828 if (head_mem < 1) //not enough room
829 { pagelist_alloc(namepages);
830 goto copy;
831 }
832 *(namepages.head->header.head)++ = '\0';
833 return name;
834 }
835
836 static void crawl_class(struct ir_class_t*);
837 static void crawl_set(struct ir_set_t*,int);
838
839 extern
840 int binout_init(ir_class);
841 void ir_test(void)
842 { uprintf("IR From Directory: %s\n",getcwd(NULL,255));
843 crawl_class(&root_class);
844 if (root_class.root_set != NULL)
845 crawl_set(root_class.root_set, 0);
846 uprintf("starting binaryout \n");
847 binout_init(&root_class);
848 }
849
850
851 static
852 void crawl_class
853 ( struct ir_class_t* class )
854 { struct ir_class_t* iter;
855 for (iter = class->nextchild; iter != NULL; iter = iter->nextsib)
856 { wprintf("Crawling class %U/\n", iter->name);
857 if(chdir((char*)iter->name))
858 eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255));
859 crawl_class(iter);
860 if (iter->root_set != NULL)
861 crawl_set(iter->root_set, 0);
862 uprintf("%U\\\n",iter->name);
863 if (chdir(".."))
864 eprintf("CHDIR ..\n");
865 wprintf("Finished crawling class %U/\n", iter->name);
866 }
867 }
868
869 #define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)
870 #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))
871 static
872 void crawl_set
873 ( struct ir_set_t* set,
874 int depth
875 )
876 { struct ir_set_t* iter;
877 int i;
878 i = depth * 12;
879 while (i--)
880 putchar('.');
881 i = depth;
882
883 for(iter = set; iter != NULL; iter = iter->nextchild)
884 { uprintf("[%10U]", iter->name);
885 push_setp(iter);
886 i++;
887 }
888
889 putchar('\n');
890 while (--i >= depth)
891 if (((iter = pop_setp())->nextsib) != NULL)
892 crawl_set(iter->nextsib,i);
893 }