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
};
35 struct ir_facinglist_t
;
36 struct ir_facinglist_t
37 { struct ir_facinglist_t
* nextsib
;
42 { struct ir_namelist_t
* nextsib
;
46 { struct ir_class_t
* root_class
;
47 struct ir_namelist_t
* namelist
, * namelist_head
;
50 { struct ir_classld_t
* classld
;
52 struct ir_namelist_t
* namelist
, * namelist_head
;
54 struct ir_setdata_header_t
56 uint8_t* src_filename
, * data_name
;
57 union ir_setdata_t
* nextsib
;
61 { struct ir_setdata_header_t header
;
64 struct ir_facinglist_t
* mirrorlist
,* nextmirror
;
67 { struct ir_setdata_header_t header
;
68 struct ir_framedata_t framesheets
[FACING_MAX
];
69 struct ir_framedata_t mapsheets
[FACING_MAX
];
71 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
73 { struct ir_setdata_header_t header
;
74 struct ir_setld_t
* setld
;
75 struct ir_set_t
* trg_set
;
80 { struct ir_setdata_header_t header
;
81 struct ir_framebox_t framebox
;
82 struct ir_framedata_t framesheet
;
83 struct ir_framedata_t mapsheet
;
84 struct ir_simplex_t audio
;
85 struct ir_link_t link
;
88 { struct ir_class_t
* nextchild
, * nextsib
;
89 struct ir_set_t
* root_set
;
94 { struct ir_set_t
* nextchild
, * nextsib
;
97 struct ir_framebox_t
* frameboxes
;
98 struct ir_simplex_t
* audio
;
99 struct ir_link_t
* links
;
104 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*,uint8_t*);
106 union ir_setdata_t
* ir_framedata (enum dtype
,const uint8_t*,facinglist
,int,int);
108 void ir_linkdata_resolve_set(union ir_setdata_t
*);
110 int bytes_identical(const uint8_t*,const uint8_t*);
112 int classnames_identical(const uint8_t*,const uint8_t*);
114 uint8_t* name_alloc(const uint8_t*);
116 uint8_t* classname_alloc(const uint8_t*);
117 #define struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
118 #define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)
119 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
123 char* apc_package_name
;
125 struct pagelist_t datapages
, namepages
, refhashpages
;
127 struct ir_class_t root_class
;
132 { pagelist_init(datapages
, (size_t)SYS_PAGESIZE
);
133 pagelist_init(namepages
, (size_t)NAME_PAGESIZE
);
134 pagelist_init(refhashpages
, (size_t)SYS_PAGESIZE
);
135 root_class
.name
= (uint8_t*) apc_package_name
;
142 { pagenode_free(datapages
.root
);
143 pagenode_free(namepages
.root
);
144 pagenode_free(refhashpages
.root
);
160 /* Return the class's name string */
161 uint8_t* ir_class_name
162 ( struct ir_class_t
* class )
163 { return class->name
; }
165 /* Return a pointer to the root class */
166 struct ir_class_t
* ir_class_root
168 { return &root_class
; }
170 /* Add a subclass to a class
171 Attempts to create a new subclass in the provided class, returning
172 the class if it already exists
174 struct ir_class_t
* ir_class_addchild
175 ( struct ir_class_t
* class,
178 { struct ir_class_t
* iter
;
179 if (class->nextchild
== NULL
)
180 { class->nextchild
= struct_alloc(ir_class_t
);
181 struct_clear(class->nextchild
);
182 class->nextchild
->name
= classname_alloc(name
);
183 return class->nextchild
;
185 iter
= class->nextchild
;
186 if (iter
->name
== NULL
)
187 eprintf("Null name pointer in class %p\n", iter
);
189 eprintf("Null child added to class %s\n", iter
->name
);
191 if (classnames_identical(iter
->name
, name
))
193 if (iter
->nextsib
!= NULL
)
194 { iter
= iter
->nextsib
;
197 iter
->nextsib
= struct_alloc(ir_class_t
);
198 struct_clear(iter
->nextsib
);
199 iter
->nextsib
->name
= classname_alloc(name
);
200 return iter
->nextsib
;
203 /* Add a set to a class
204 Attempts to create a new root set in the specified class, returning
205 the set if it already exists
207 struct ir_set_t
* ir_class_addset
208 ( struct ir_class_t
* class,
211 { struct ir_set_t
* iter
;
212 if (class->root_set
== NULL
)
213 { class->root_set
= struct_alloc(ir_set_t
);
214 struct_clear(class->root_set
);
215 class->root_set
->name
= name_alloc(name
);
216 return class->root_set
;
218 iter
= class->root_set
;
219 if (iter
->name
== NULL
)
220 eprintf("Null name pointer in class %p\n", iter
);
222 eprintf("Null set added to class %U\n", iter
->name
);
224 if (bytes_identical(iter
->name
, name
))
226 if (iter
->nextsib
!= NULL
)
227 { iter
= iter
->nextsib
;
230 iter
->nextsib
= struct_alloc(ir_set_t
);
231 struct_clear(iter
->nextsib
);
232 iter
->nextsib
->name
= name_alloc(name
);
233 return iter
->nextsib
;
236 /* Get the root set of the class */
237 struct ir_set_t
* ir_class_rootset
238 ( struct ir_class_t
* class )
239 { return class->root_set
; }
241 struct ir_set_t
* ir_set_from_ref
244 struct ir_set_t
** iters
;
245 struct pagenode_t
* iterp
;
246 iterp
= refhashpages
.root
;
249 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
250 while (*iters
!= NULL
&& (*iters
)->ref
!= ref
&& (iterp
= iterp
->header
.next
) != NULL
);
255 /* Add a set to a set
256 Attempts to create a new subset of the specified set, returning the
257 child if it already exists
259 struct ir_set_t
* ir_set_addchild
260 ( struct ir_set_t
* set
,
263 { struct ir_set_t
* iter
;
264 if (set
->nextchild
== NULL
)
265 { set
->nextchild
= struct_alloc(ir_set_t
);
266 struct_clear(set
->nextchild
);
267 set
->nextchild
->name
= name_alloc(name
);
268 return set
->nextchild
;
270 iter
= set
->nextchild
;
272 eprintf("Null child added to set %s\n", iter
->name
);
273 if (iter
->name
== NULL
)
274 eprintf("Null name pointer in set %p\n", iter
);
276 if (bytes_identical(iter
->name
, name
))
278 if (iter
->nextsib
!= NULL
)
279 { iter
= iter
->nextsib
;
282 iter
->nextsib
= struct_alloc(ir_set_t
);
283 struct_clear(iter
->nextsib
);
284 iter
->nextsib
->name
= name_alloc(name
);
285 return iter
->nextsib
;
288 /* Add a framebox to a set
289 Attempts to create a new framebox of the specified set, returning
290 the framebox if it already exists
291 Name is not allocated, but assigned, unlike other "XXX_add" functions where
292 name is duplicated into IR's internal array.
295 struct ir_framebox_t
* ir_set_add_framebox
296 ( struct ir_set_t
* set
,
299 { struct ir_framebox_t
* iter
;
300 if (set
->frameboxes
== NULL
)
301 { set
->frameboxes
= struct_alloc(ir_framebox_t
);
302 struct_clear(set
->frameboxes
);
303 set
->frameboxes
->header
.data_name
= name
;
304 return set
->frameboxes
;
306 iter
= set
->frameboxes
;
308 if (bytes_identical(iter
->header
.data_name
, name
))
310 if (iter
->header
.nextsib
!= NULL
)
311 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
314 iter
->header
.nextsib
= (union ir_setdata_t
*) struct_alloc(ir_framebox_t
);
315 struct_clear(iter
->header
.nextsib
);
316 iter
->header
.nextsib
->header
.data_name
= name
;
317 return (struct ir_framebox_t
*) (iter
->header
.nextsib
);
320 /* Match two null-terminated bytestrings
321 Return 1 if the two bytestrings are identical, else 0
325 ( const uint8_t* stra
,
332 } while (ca
&& ca
!= '_' && ca
== cb
);
337 int classnames_identical
338 ( const uint8_t* stra
,
345 } while (ca
&& ca
== cb
);
349 /* Return the name of the set */
351 ( struct ir_set_t
* set
)
352 { return set
->name
; }
354 /* Return the next sib of the class */
355 struct ir_class_t
* ir_class_nextsib
356 ( struct ir_class_t
* class )
357 { return class->nextsib
; }
359 /* Return the next sib of the class */
360 struct ir_class_t
* ir_class_nextchild
361 ( struct ir_class_t
* class )
362 { return class->nextchild
; }
364 /* Get the file position of the class */
366 ( struct ir_class_t
* class )
367 { return class->filepos
; }
369 /* Set the file position of the class */
370 void ir_class_assign_fpos
371 ( struct ir_class_t
* class,
374 { class->filepos
= newpos
; }
376 /* Get the next sibling of the provided set */
377 struct ir_set_t
* ir_set_nextsib
378 ( struct ir_set_t
* set
)
379 { return set
->nextsib
; }
381 /* Get the next child of the provided set */
382 struct ir_set_t
* ir_set_nextchild
383 ( struct ir_set_t
* set
)
384 { return set
->nextchild
; }
386 /* Get the file position of the class */
388 ( struct ir_set_t
* set
)
389 { return set
->filepos
; }
391 /* Set the file position of the class */
392 void ir_set_assign_fpos
393 ( struct ir_set_t
* set
,
396 { set
->filepos
= newpos
; }
398 /* Assign Setdata to Set */
399 void ir_set_assign_data
400 ( struct ir_set_t
* set
,
401 union ir_setdata_t
* setdata
403 { struct ir_framebox_t
* framebox
;
404 struct ir_simplex_t
* simplex
;
405 switch (setdata
->header
.type
)
407 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
408 if (framebox
->framesheets
[setdata
->framesheet
.facing
].header
.data_name
!= NULL
)
409 wprintf("Duplicate framesheet [%i] %s\n",
410 setdata
->framesheet
.facing
, setdata
->header
.data_name
);
411 framebox
->framesheets
[setdata
->framesheet
.facing
] = setdata
->framesheet
;
414 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
415 if (framebox
->mapsheets
[setdata
->mapsheet
.facing
].header
.data_name
!= NULL
)
416 wprintf("Duplicate mapsheet [%i] %s\n",
417 setdata
->mapsheet
.facing
, setdata
->header
.data_name
);
418 framebox
->mapsheets
[setdata
->mapsheet
.facing
] = setdata
->mapsheet
;
421 if (set
->audio
== NULL
)
422 { set
->audio
= (struct ir_simplex_t
*) setdata
;
425 simplex
= set
->audio
;
426 while (simplex
->header
.nextsib
!= NULL
)
427 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
428 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
429 *simplex
= setdata
->audio
;
430 //setdata is now a pointer to redundant, unused memory.
434 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
435 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
436 set
->audio
= (struct ir_simplex_t
*) setdata
;
439 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
440 set
->links
= (struct ir_link_t
*) setdata
;
443 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
448 void ir_set_assign_ref
449 ( struct ir_set_t
* set
,
452 { uint16_t hash
, oldhash
;
453 struct ir_set_t
** iters
;
454 struct pagenode_t
* iterp
;
459 iterp
= refhashpages
.root
;
461 iters
= ((struct ir_set_t
**) iterp
->root
) + hash
;
462 if (*iters
== NULL
|| *iters
== set
)
465 { if (iterp
->header
.next
== NULL
)
466 pagelist_alloc(refhashpages
);
467 iterp
= iterp
->header
.next
;
471 { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref
, ref
, set
->name
);
476 hash
= REFHASH(oldref
);
483 void ir_data_assign_path
484 ( union ir_setdata_t
* setdata
,
488 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
489 if (setdata
->header
.src_filename
!= NULL
)
490 wprintf("Path override: %s -> %s for setdata %s\n",
491 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
492 setdata
->header
.src_filename
= name_alloc(path
);
495 union ir_setdata_t
* ir_framesheet
496 ( const uint8_t* name
,
497 struct ir_facinglist_t
* facinglist
,
501 { return ir_framedata(FSDAT
, name
, facinglist
, width
, height
); }
503 union ir_setdata_t
* ir_mapsheet
504 ( const uint8_t* name
,
505 struct ir_facinglist_t
* facinglist
,
509 { return ir_framedata(MSDAT
, name
, facinglist
, width
, height
); }
512 union ir_setdata_t
* ir_framedata
515 struct ir_facinglist_t
* facinglist
,
519 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
520 struct_clear(framedata
);
522 eprintf("Null name in set allocation\n");
523 framedata
->header
.type
= type
;
524 framedata
->header
.data_name
= name_alloc(name
);
525 if (facinglist
!= NULL
)
526 { framedata
->facing
= facinglist
->facing
;
527 framedata
->mirrorlist
= facinglist
->nextsib
;
530 { framedata
->facing
= SFACE
;
531 framedata
->mirrorlist
= NULL
;
533 framedata
->nextmirror
= framedata
->mirrorlist
;
534 framedata
->w
= width
;
535 framedata
->h
= height
;
536 return (union ir_setdata_t
*) framedata
;
539 union ir_setdata_t
* ir_audio
540 ( const uint8_t* name
)
541 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
544 eprintf("Null audio\n");
545 audio
->header
.type
= ADAT
;
546 audio
->header
.data_name
= name_alloc(name
);
547 return (union ir_setdata_t
*) audio
;
551 /* Create classld that points to a class */
552 struct ir_classld_t
* ir_classld_from_class
553 ( struct ir_class_t
* class )
554 { struct ir_classld_t
* classld
;
556 eprintf("Null class in classld\n");
557 classld
= struct_alloc(ir_classld_t
);
558 struct_clear(classld
);
559 classld
->root_class
= class;
563 struct ir_setld_t
* ir_setld_from_ref
565 { struct ir_setld_t
* setld
;
566 setld
= struct_alloc(ir_setld_t
);
572 struct ir_setld_t
* ir_setld_from_classld
573 ( struct ir_classld_t
* classld
,
576 { struct ir_setld_t
* setld
;
577 setld
= struct_alloc(ir_setld_t
);
579 setld
->namelist
= struct_alloc(ir_namelist_t
);
580 struct_clear(setld
->namelist
);
581 setld
->namelist_head
= setld
->namelist
;
582 setld
->namelist_head
->name
= name_alloc(name
);
583 setld
->classld
= classld
;
587 struct ir_setld_t
* ir_setld_addchild
588 ( struct ir_setld_t
* setld
,
591 { if (setld
->namelist
== NULL
)
592 { setld
->namelist
= struct_alloc(ir_namelist_t
);
593 struct_clear(setld
->namelist
);
594 setld
->namelist_head
= setld
->namelist
;
597 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
598 struct_clear(setld
->namelist_head
->nextsib
);
599 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
601 setld
->namelist_head
->name
= name_alloc(name
);
605 union ir_setdata_t
* ir_link
606 ( enum ltype link_type
,
607 struct ir_setld_t
* setld
,
610 { struct ir_link_t
* link
;
611 link
= struct_alloc(ir_link_t
);
613 link
->header
.type
= LDAT
;
614 link
->type
= link_type
;
616 if (link_type
!= OLINK
&& name
!= NULL
)
617 link
->header
.data_name
= name_alloc(name
);
618 return (union ir_setdata_t
*) link
;
621 /* Return a set's root framebox */
622 union ir_setdata_t
* ir_set_framebox
623 ( struct ir_set_t
* set
)
624 { return (union ir_setdata_t
*) set
->frameboxes
; }
626 /* Return a set's root audio data */
627 union ir_setdata_t
* ir_set_audio
628 ( struct ir_set_t
* set
)
629 { return (union ir_setdata_t
*) set
->audio
; }
631 /* Return a set's root link data */
632 union ir_setdata_t
* ir_set_link
633 ( struct ir_set_t
* set
)
634 { return (union ir_setdata_t
*) set
->links
; }
636 #define assert_link(linkdata) if (DEBUG) { \
637 if (linkdata->header.type != LDAT) \
638 eprintf("Data %s is not a link\n", linkdata->header.data_name); \
641 /* Return the link type */
642 enum ltype ir_linkdata_type
643 ( union ir_setdata_t
* linkdata
)
644 { assert_link(linkdata
);
645 return linkdata
->link
.type
;
648 /* Return the link type */
649 uint32_t ir_linkdata_ref
650 ( union ir_setdata_t
* linkdata
)
651 { assert_link(linkdata
);
652 return linkdata
->link
.setld
->ref
;
655 /* Return the current target set, resolving it first if not present */
656 struct ir_set_t
* ir_linkdata_set
657 ( union ir_setdata_t
* linkdata
)
658 { assert_link(linkdata
);
659 if (linkdata
->link
.trg_set
== NULL
)
660 ir_linkdata_resolve_set(linkdata
);
661 return linkdata
->link
.trg_set
;
664 /* Resolve and assign the link's target set */
666 void ir_linkdata_resolve_set
667 ( union ir_setdata_t
* linkdata
)
668 { struct ir_class_t
* class_iter
;
669 struct ir_namelist_t
* namelist_iter
,* namelist_iter_last
;
670 struct ir_setld_t
* setld
;
671 struct ir_classld_t
* classld
;
672 struct ir_set_t
* set
;
675 assert_link(linkdata
);
676 setld
= linkdata
->link
.setld
;
677 if (linkdata
->link
.setld
== NULL
)
678 eprintf("Link data is invalid\n");
679 classld
= setld
->classld
;
681 { namelist_iter
= classld
->namelist
;
682 if (classld
->root_class
== NULL
)
683 eprintf("No root class for classld\n");
684 class_iter
= classld
->root_class
->nextchild
;
685 namelist_iter_last
= NULL
;
686 while (class_iter
!= NULL
)
687 { if (classnames_identical(class_iter
->name
, namelist_iter
->name
))
688 { if (namelist_iter
== classld
->namelist_head
)
690 class_iter
= class_iter
->nextchild
;
691 namelist_iter_last
= namelist_iter
;
692 namelist_iter
= namelist_iter
->nextsib
;
695 class_iter
= class_iter
->nextsib
;
697 if (class_iter
== NULL
)
698 { if (namelist_iter_last
)
699 eprintf("No such subclass \"%s\" of class \"%s\"\n",
701 namelist_iter_last
->name
);
703 { wprintf("No such class \"%s\"\n", namelist_iter
->name
);
707 set
= class_iter
->root_set
;
710 set
= ir_set_from_ref(setld
->ref
);
712 eprintf("Initial set resolution failed\n");
713 namelist_iter
= setld
->namelist
;
714 namelist_iter_last
= NULL
;
715 if (setld
->namelist
!= NULL
)
716 { while (set
!= NULL
)
717 { if (bytes_identical(set
->name
, namelist_iter
->name
))
718 { if (namelist_iter
== setld
->namelist_head
)
720 set
= set
->nextchild
;
721 namelist_iter_last
= namelist_iter
;
722 namelist_iter
= namelist_iter
->nextsib
;
728 { if (namelist_iter_last
)
729 eprintf("No such subset \"%s\" of set \"%s\"\n",
731 namelist_iter_last
->name
);
733 eprintf("No such set \"%s\" in class \"%s\"\n",
738 linkdata
->link
.trg_set
= set
;
741 /* Assign a linkdatas trg_set */
742 void ir_linkdata_assign_set
743 ( union ir_setdata_t
* link
, struct ir_set_t
* set
)
745 link
->link
.trg_set
= set
;
748 /* Assign a linkdatas type */
749 void ir_linkdata_assign_type
750 ( union ir_setdata_t
* link
, enum ltype type
)
752 link
->link
.type
= type
;
755 /* Get, or generate, the fully qualified name of the link's target set */
757 ir_linkdata_dlink_name
758 ( union ir_setdata_t
* link
)
759 { struct ir_namelist_t
* namelist_iter
;
760 struct ir_setld_t
* setld
;
761 struct ir_classld_t
* classld
;
766 static const uint8_t dlink_prefix
[] = { '/', '.', '.', '/' };
767 # define dlink_prefix_len 4
769 if (link
->link
.dlink
!= NULL
)
770 return link
->link
.dlink
;
772 setld
= link
->link
.setld
;
774 eprintf("No setld in dlink\n");
775 classld
= setld
->classld
;
777 eprintf("No classld in dlink\n");
778 if (classld
->root_class
!= NULL
)
779 eprintf("Cannot dlink local class \"%s\"\n", classld
->root_class
->name
);
780 namelist_iter
= classld
->namelist
;
782 count_bytes_in_namelist
:
783 while (namelist_iter
!= NULL
)
784 { bytep
= namelist_iter
->name
;
786 bytes
+= (bytep
- namelist_iter
->name
);
787 namelist_iter
= namelist_iter
->nextsib
;
791 namelist_iter
= setld
->namelist
;
792 goto count_bytes_in_namelist
;
794 bytes
+= dlink_prefix_len
;
795 link
->link
.dlink
= stack_alloc(&namepages
, bytes
);
796 for (bytes
= 0; bytes
< dlink_prefix_len
; bytes
++)
797 link
->link
.dlink
[bytes
] = dlink_prefix
[bytes
];
798 namelist_iter
= classld
->namelist
;
800 delimiter
= APC_CLASS_DELIMITER
;
801 copy_bytes_in_namelist
:
802 while (namelist_iter
!= NULL
)
803 { bytep
= namelist_iter
->name
;
805 link
->link
.dlink
[bytes
++] = *bytep
++;
806 link
->link
.dlink
[bytes
++] = delimiter
;
807 namelist_iter
= namelist_iter
->nextsib
;
811 namelist_iter
= setld
->namelist
;
812 delimiter
= APC_SET_DELIMITER
;
813 link
->link
.dlink
[bytes
- 1] = delimiter
; //overwrite last delimiter
814 goto copy_bytes_in_namelist
;
816 link
->link
.dlink
[bytes
] = '\0'; //tailing '\0' null termination
817 return link
->link
.dlink
;
820 /* Get a setdata's next sibling */
821 union ir_setdata_t
* ir_setdata_nextsib
822 ( union ir_setdata_t
* setdata
)
823 { return setdata
->header
.nextsib
; }
825 /* Get a setdata's name */
826 uint8_t* ir_setdata_name
827 ( union ir_setdata_t
* setdata
)
828 { return setdata
->header
.data_name
; }
830 /* Get a setdata's filename */
831 uint8_t* ir_setdata_filename
832 ( union ir_setdata_t
* setdata
)
833 { return setdata
->header
.src_filename
; }
835 /* Get a setdata's file position */
837 ( union ir_setdata_t
* setdata
)
838 { return setdata
->header
.filepos
; }
840 /* Set a setdata's file position */
841 void ir_setdata_assign_fpos
842 ( union ir_setdata_t
* setdata
,
845 { setdata
->header
.filepos
= newpos
; }
847 /* Assign a setdatas name */
848 void ir_setdata_assign_name
849 ( union ir_setdata_t
* setdata
, uint8_t* name
)
850 { setdata
->header
.data_name
= name
;}
852 /* Create a new facinglist from an apc_facing */
853 struct ir_facinglist_t
* ir_facinglist
854 ( apc_facing facing
)
855 { struct ir_facinglist_t
* list
= struct_alloc(ir_facinglist_t
);
856 list
->facing
= facing
;
860 /* Add a child to the facing list */
861 struct ir_facinglist_t
* ir_facinglist_push
862 ( struct ir_facinglist_t
* list
,
865 { struct ir_facinglist_t
* iter
= list
;
867 { while (iter
->nextsib
!= NULL
)
868 iter
= iter
->nextsib
;
869 iter
->nextsib
= struct_alloc(ir_facinglist_t
);
870 iter
->nextsib
->facing
= facing
;
875 #define assert_framebox(fbox) if (DEBUG) { \
876 if (fbox->header.type != FBDAT) \
877 eprintf("Data %s is not a framebox\n", fbox->header.data_name); \
880 /* Return a framebox's specified framesheet */
881 union ir_setdata_t
* ir_framebox_framesheet
882 ( union ir_setdata_t
* fbox
,
885 { assert_framebox(fbox
);
886 return (union ir_setdata_t
*) &fbox
->framebox
.framesheets
[facing
];
889 /* Return a framebox's specified mapsheet */
890 union ir_setdata_t
* ir_framebox_mapsheet
891 ( union ir_setdata_t
* fbox
,
894 { assert_framebox(fbox
);
895 return (union ir_setdata_t
*) &fbox
->framebox
.mapsheets
[facing
];
898 #define assert_framedata(fdat) if (DEBUG) { \
899 if (fdat->header.type != MSDAT && fdat->header.type != FSDAT) \
900 eprintf("Data %s is not a framedata\n", fdat->header.data_name); \
903 /* Return a framedata's frame info */
904 int ir_framedata_width
905 ( union ir_setdata_t
* framedata
)
906 { assert_framedata(framedata
);
907 return framedata
->mapsheet
.w
;
910 /* Return a framedata's frame info */
911 int ir_framedata_height
912 ( union ir_setdata_t
* framedata
)
913 { assert_framedata(framedata
);
914 return framedata
->mapsheet
.h
;
917 /* Return the next facing in the framedata's facing list, and reset the
918 'nextmirror' head to mirrorlist, so that 'ir_framedata_nextmirror' will now
919 refer to the second facing in the framedata */
920 apc_facing ir_framedata_firstfacing
921 ( union ir_setdata_t
* framedata
)
922 { assert_framedata(framedata
);
923 framedata
->mapsheet
.nextmirror
= framedata
->mapsheet
.mirrorlist
;
924 return framedata
->mapsheet
.facing
;
927 /* Return the next facing for this framedata, incrementing the 'nextmirror'
928 head. Returns FACING_MAX when there are no more facings to return. */
929 apc_facing ir_framedata_nextfacing
930 ( union ir_setdata_t
* framedata
)
932 assert_framedata(framedata
);
933 if (framedata
->mapsheet
.nextmirror
== NULL
)
935 facing
= framedata
->mapsheet
.nextmirror
->facing
;
936 framedata
->mapsheet
.nextmirror
= framedata
->mapsheet
.nextmirror
->nextsib
;
943 ( const uint8_t* name_src
)
944 { const uint8_t* iter
;
948 name
= (uint8_t*)namepages
.head
->header
.head
;
950 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && *iter
!= '.' && head_mem
; head_mem
--)
951 *(namepages
.head
->header
.head
)++ = *iter
++;
952 if (head_mem
< 1) //not enough room
953 { pagelist_alloc(namepages
);
956 *(namepages
.head
->header
.head
)++ = '\0';
961 uint8_t* classname_alloc
962 ( const uint8_t* name_src
)
963 { const uint8_t* iter
;
967 name
= (uint8_t*)namepages
.head
->header
.head
;
969 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
970 *(namepages
.head
->header
.head
)++ = *iter
++;
971 if (head_mem
< 1) //not enough room
972 { pagelist_alloc(namepages
);
975 *(namepages
.head
->header
.head
)++ = '\0';
979 static void crawl_class(struct ir_class_t
*);
980 static void crawl_set(struct ir_set_t
*,int);
983 int binout_init(ir_class
);
985 { uprintf("IR From Directory: %s\n",getcwd(NULL
,255));
986 crawl_class(&root_class
);
987 if (root_class
.root_set
!= NULL
)
988 crawl_set(root_class
.root_set
, 0);
989 uprintf("starting binaryout \n");
990 binout_init(&root_class
);
996 ( struct ir_class_t
* class )
997 { struct ir_class_t
* iter
;
998 for (iter
= class->nextchild
; iter
!= NULL
; iter
= iter
->nextsib
)
999 { wprintf("Crawling class %U/\n", iter
->name
);
1000 if(chdir((char*)iter
->name
))
1001 eprintf("CHDIR %U from %s\n",iter
->name
,getcwd(NULL
,255));
1003 if (iter
->root_set
!= NULL
)
1004 crawl_set(iter
->root_set
, 0);
1005 uprintf("%U\\\n",iter
->name
);
1007 eprintf("CHDIR ..\n");
1008 wprintf("Finished crawling class %U/\n", iter
->name
);
1012 #define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)
1013 #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))
1016 ( struct ir_set_t
* set
,
1019 { struct ir_set_t
* iter
;
1026 for(iter
= set
; iter
!= NULL
; iter
= iter
->nextchild
)
1027 { uprintf("[%10U]", iter
->name
);
1033 while (--i
>= depth
)
1034 if (((iter
= pop_setp())->nextsib
) != NULL
)
1035 crawl_set(iter
->nextsib
,i
);