X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fir.c;h=857f73fb017bb3509fcafe40386cd20392677e5b;hp=0f8a46160f641c39ee696874e8fc041ba80fb23a;hb=HEAD;hpb=6035780f8e8c7ba47ae517ad6cf7e47515e847fd diff --git a/src/ir.c b/src/ir.c index 0f8a461..857f73f 100644 --- a/src/ir.c +++ b/src/ir.c @@ -10,31 +10,32 @@ #include //va_args #include //uint64_t #include //memset, str* +#include /* Unicode */ #include //u8_* functions #include //uint8_t as a char #include //u32_cpy +#include //ulc_fprintf /* Local */ +#define eprintf_callback(...) exit(EXIT_FAILURE) +#include "print.h" #include "apc.h" #include "ir.h" +#include "pagenode.h" +#define XXH_PRIVATE_API +#include "../xxHash/xxhash.h" /* Public */ int ir_init(void); void ir_quit(void); +void ir_test(void); int ir_linker(void); int ir_condenser(void); -/* Memory allocation structures */ -struct pagenode_t; -struct pagenode_header_t { - struct pagenode_t* next; - char* head; -}; -struct pagenode_t { - struct pagenode_header_t header; - char root[]; -}; -struct pagelist_t { - struct pagenode_t* root, * head; - size_t pagesize; +/* Set data mem */ +enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT }; +struct ir_facinglist_t; +struct ir_facinglist_t +{ struct ir_facinglist_t* nextsib; + apc_facing facing; }; struct ir_namelist_t; struct ir_namelist_t @@ -47,20 +48,20 @@ struct ir_classld_t }; struct ir_setld_t { struct ir_classld_t* classld; - long long ref; + uint32_t ref; struct ir_namelist_t* namelist, * namelist_head; }; -/* Set data mem */ struct ir_setdata_header_t { enum dtype type; uint8_t* src_filename, * data_name; union ir_setdata_t* nextsib; + long filepos; }; -struct ir_frameinfo_t -{ int facing, w, h; }; struct ir_framedata_t { struct ir_setdata_header_t header; - struct ir_frameinfo_t frameinfo; + apc_facing facing; + int w, h; + struct ir_facinglist_t* mirrorlist,* nextmirror; }; struct ir_framebox_t { struct ir_setdata_header_t header; @@ -70,8 +71,9 @@ struct ir_framebox_t struct ir_simplex_t { struct ir_setdata_header_t header; }; struct ir_link_t { struct ir_setdata_header_t header; - struct ir_classld_t* classld; struct ir_setld_t* setld; + struct ir_set_t* trg_set; + uint8_t* dlink; enum ltype type; }; union ir_setdata_t @@ -86,120 +88,80 @@ struct ir_class_t { struct ir_class_t* nextchild, * nextsib; struct ir_set_t* root_set; uint8_t* name; + long filepos; }; struct ir_set_t { struct ir_set_t* nextchild, * nextsib; - struct ir_class_t* class; - long long ref; + uint32_t ref; uint8_t* name; struct ir_framebox_t* frameboxes; struct ir_simplex_t* audio; struct ir_link_t* links; + long filepos; }; /* Functions */ static inline -int init_pagelist(struct pagelist_t*,size_t); +struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*,uint8_t*); static inline -struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*, uint8_t*); -static -void ir_free_pagenodes(struct pagenode_t*); +union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,facinglist,int,int); static inline -int bytes_identical(uint8_t*,uint8_t*); +void ir_linkdata_resolve_set(union ir_setdata_t*); +static inline +int bytes_identical(const uint8_t*,const uint8_t*); +static inline +int classnames_identical(const uint8_t*,const uint8_t*); static -void* stack_alloc(size_t); +uint8_t* name_alloc(const uint8_t*); static -uint8_t* name_alloc(uint8_t*); -static inline -union ir_setdata_t* ir_framedata (enum dtype,uint8_t*,apc_facing,int,int); -/* Function-Like Macros */ -#define do_warn() do { \ - } while (0) -#define wprint(str) do { \ - fprintf(stderr, str); \ - do_warn(); \ - } while (0) -#define wprintf(fmt,...) do { \ - fprintf(stderr, fmt, __VA_ARGS__); \ - do_warn(); \ - } while (0) -#define do_error() do { \ - exit(-1); \ - } while (0) -#define eprint(str) do { \ - fprintf(stderr, str); \ - do_error(); \ - } while (0) -#define eprintf(fmt,...) do { \ - fprintf(stderr, fmt, __VA_ARGS__); \ - do_error(); \ - } while (0) -#define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T))) -#define DATA_PAGESIZE (sys_pagesize) -#define NAME_PAGESIZE (APC_NAME_MAX * 1024) -#define PL_HEADERSIZE (sizeof(struct pagenode_header_t)) -#define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root) -#define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL)) -/* Memory */ +uint8_t* classname_alloc(const uint8_t*); +#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S)))) +#define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF) +#define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T))) extern //apc.c -long sys_pagesize; +long sys_pagesize; +extern //apc.c +char* apc_package_name; static -struct pagelist_t datapages, namepages; +struct pagelist_t datapages, namepages, refhashpages; static -struct ir_class_t root_class = { .name = (uint8_t*)"." }; +struct ir_class_t root_class; /* Init */ int ir_init ( void ) -{ if (init_pagelist(&datapages, (size_t)DATA_PAGESIZE)) - eprint("Memory allocation error\n"); - if (init_pagelist(&namepages, (size_t)NAME_PAGESIZE)) - eprint("Memory allocation error\n"); - return 0; -} - -static inline -int init_pagelist -( struct pagelist_t* pl, - size_t size -) -{ pl->pagesize = size; - pl->root = (struct pagenode_t*) calloc(size,1); - if (pl->root == NULL) - return -1; - pl->root->header.head = pl->root->root; - pl->head = pl->root; +{ pagelist_init(datapages, (size_t)SYS_PAGESIZE); + pagelist_init(namepages, (size_t)NAME_PAGESIZE); + pagelist_init(refhashpages, (size_t)SYS_PAGESIZE); + root_class.name = (uint8_t*) apc_package_name; return 0; } -/* Quit/Cleanup - Recursively clean pagenode linked list -*/ +/* Quit/Cleanup */ void ir_quit ( void ) -{ ir_free_pagenodes(datapages.root); - ir_free_pagenodes(namepages.root); -} +{ pagenode_free(datapages.root); + pagenode_free(namepages.root); + pagenode_free(refhashpages.root); -static -void ir_free_pagenodes -( struct pagenode_t* pagenode ) -{ if (pagenode->header.next != NULL) - ir_free_pagenodes(pagenode->header.next); - free(pagenode); } -/* Link -*/ +/* Link */ int ir_linker ( void ) -{ return 0; } +{ + return 0; +} -/* Condense -*/ +/* Condense */ int ir_condenser ( void ) { return 0; } +/* Return the class's name string */ +uint8_t* ir_class_name +( struct ir_class_t* class ) +{ return class->name; } + /* Return a pointer to the root class */ struct ir_class_t* ir_class_root ( void ) @@ -211,23 +173,31 @@ struct ir_class_t* ir_class_root */ struct ir_class_t* ir_class_addchild ( struct ir_class_t* class, - uint8_t* name + const uint8_t* name ) { struct ir_class_t* iter; if (class->nextchild == NULL) - return class->nextchild = struct_alloc(ir_class_t); + { class->nextchild = struct_alloc(ir_class_t); + struct_clear(class->nextchild); + class->nextchild->name = classname_alloc(name); + return class->nextchild; + } iter = class->nextchild; + if (iter->name == NULL) + eprintf("Null name pointer in class %p\n", iter); + if (name == NULL) + eprintf("Null child added to class %s\n", iter->name); check: - if (bytes_identical(iter->name, name)) + if (classnames_identical(iter->name, name)) return iter; if (iter->nextsib != NULL) { iter = iter->nextsib; goto check; } - iter = struct_alloc(ir_class_t); - iter->nextsib = class->nextchild; - iter->name = name_alloc(name); - return class->nextchild = iter; + iter->nextsib = struct_alloc(ir_class_t); + struct_clear(iter->nextsib); + iter->nextsib->name = classname_alloc(name); + return iter->nextsib; } /* Add a set to a class @@ -236,12 +206,20 @@ struct ir_class_t* ir_class_addchild */ struct ir_set_t* ir_class_addset ( struct ir_class_t* class, - uint8_t* name + const uint8_t* name ) { struct ir_set_t* iter; if (class->root_set == NULL) - return class->root_set = struct_alloc(ir_set_t); + { class->root_set = struct_alloc(ir_set_t); + struct_clear(class->root_set); + class->root_set->name = name_alloc(name); + return class->root_set; + } iter = class->root_set; + if (iter->name == NULL) + eprintf("Null name pointer in class %p\n", iter); + if (name == NULL) + eprintf("Null set added to class %U\n", iter->name); check: if (bytes_identical(iter->name, name)) return iter; @@ -249,24 +227,51 @@ struct ir_set_t* ir_class_addset { iter = iter->nextsib; goto check; } - iter = struct_alloc(ir_set_t); - iter->nextsib = class->root_set; - iter->name = name_alloc(name); - return class->root_set = iter; + iter->nextsib = struct_alloc(ir_set_t); + struct_clear(iter->nextsib); + iter->nextsib->name = name_alloc(name); + return iter->nextsib; } +/* Get the root set of the class */ +struct ir_set_t* ir_class_rootset +( struct ir_class_t* class ) +{ return class->root_set; } + +struct ir_set_t* ir_set_from_ref +( uint32_t ref ) +{ uint16_t hash; + struct ir_set_t** iters; + struct pagenode_t* iterp; + iterp = refhashpages.root; + hash = REFHASH(ref); + do + iters = ((struct ir_set_t**) iterp->root) + hash; + while (*iters != NULL && (*iters)->ref != ref && (iterp = iterp->header.next) != NULL); + return *iters; +} + + /* Add a set to a set Attempts to create a new subset of the specified set, returning the child if it already exists */ struct ir_set_t* ir_set_addchild ( struct ir_set_t* set, - uint8_t* name + const uint8_t* name ) { struct ir_set_t* iter; if (set->nextchild == NULL) - return set->nextchild = struct_alloc(ir_set_t); + { set->nextchild = struct_alloc(ir_set_t); + struct_clear(set->nextchild); + set->nextchild->name = name_alloc(name); + return set->nextchild; + } iter = set->nextchild; + if (name == NULL) + eprintf("Null child added to set %s\n", iter->name); + if (iter->name == NULL) + eprintf("Null name pointer in set %p\n", iter); check: if (bytes_identical(iter->name, name)) return iter; @@ -274,15 +279,17 @@ struct ir_set_t* ir_set_addchild { iter = iter->nextsib; goto check; } - iter = struct_alloc(ir_set_t); - iter->nextsib = set->nextchild; - iter->name = name_alloc(name); - return set->nextchild = iter; + iter->nextsib = struct_alloc(ir_set_t); + struct_clear(iter->nextsib); + iter->nextsib->name = name_alloc(name); + return iter->nextsib; } /* Add a framebox to a set Attempts to create a new framebox of the specified set, returning the framebox if it already exists + Name is not allocated, but assigned, unlike other "XXX_add" functions where + name is duplicated into IR's internal array. */ static inline struct ir_framebox_t* ir_set_add_framebox @@ -291,7 +298,11 @@ struct ir_framebox_t* ir_set_add_framebox ) { struct ir_framebox_t* iter; if (set->frameboxes == NULL) - return set->frameboxes = struct_alloc(ir_framebox_t); + { set->frameboxes = struct_alloc(ir_framebox_t); + struct_clear(set->frameboxes); + set->frameboxes->header.data_name = name; + return set->frameboxes; + } iter = set->frameboxes; check: if (bytes_identical(iter->header.data_name, name)) @@ -300,10 +311,10 @@ struct ir_framebox_t* ir_set_add_framebox { iter = (struct ir_framebox_t*) iter->header.nextsib; goto check; } - iter = struct_alloc(ir_framebox_t); - iter->header.nextsib = (union ir_setdata_t*) set->frameboxes; - iter->header.data_name = name_alloc(name); - return set->frameboxes = iter; + iter->header.nextsib = (union ir_setdata_t*) struct_alloc(ir_framebox_t); + struct_clear(iter->header.nextsib); + iter->header.nextsib->header.data_name = name; + return (struct ir_framebox_t*) (iter->header.nextsib); } /* Match two null-terminated bytestrings @@ -311,8 +322,21 @@ struct ir_framebox_t* ir_set_add_framebox */ static inline int bytes_identical -( uint8_t* stra, - uint8_t* strb +( const uint8_t* stra, + const uint8_t* strb +) +{ int ca, cb; + do { + ca = *stra++; + cb = *strb++; + } while (ca && ca != '_' && ca == cb); + return (ca == cb); +} + +static inline +int classnames_identical +( const uint8_t* stra, + const uint8_t* strb ) { int ca, cb; do { @@ -322,9 +346,56 @@ int bytes_identical return (ca == cb); } -/* Assign Setdata to Set +/* Return the name of the set */ +uint8_t* ir_set_name +( struct ir_set_t* set) +{ return set->name; } + +/* Return the next sib of the class */ +struct ir_class_t* ir_class_nextsib +( struct ir_class_t* class ) +{ return class->nextsib; } + +/* Return the next sib of the class */ +struct ir_class_t* ir_class_nextchild +( struct ir_class_t* class ) +{ return class->nextchild; } + +/* Get the file position of the class */ +long ir_class_fpos +( struct ir_class_t* class ) +{ return class->filepos; } + +/* Set the file position of the class */ +void ir_class_assign_fpos +( struct ir_class_t* class, + long newpos +) +{ class->filepos = newpos; } + +/* Get the next sibling of the provided set */ +struct ir_set_t* ir_set_nextsib +( struct ir_set_t* set ) +{ return set->nextsib; } + +/* Get the next child of the provided set */ +struct ir_set_t* ir_set_nextchild +( struct ir_set_t* set ) +{ return set->nextchild; } + +/* Get the file position of the class */ +long ir_set_fpos +( struct ir_set_t* set ) +{ return set->filepos; } + +/* Set the file position of the class */ +void ir_set_assign_fpos +( struct ir_set_t* set, + long newpos +) +{ set->filepos = newpos; } - */ +/* Assign Setdata to Set */ void ir_set_assign_data ( struct ir_set_t* set, union ir_setdata_t* setdata @@ -334,17 +405,17 @@ void ir_set_assign_data switch (setdata->header.type) { case FSDAT: framebox = ir_set_add_framebox(set, setdata->header.data_name); - if (framebox->framesheets[setdata->framesheet.frameinfo.facing].header.data_name != NULL) + if (framebox->framesheets[setdata->framesheet.facing].header.data_name != NULL) wprintf("Duplicate framesheet [%i] %s\n", - setdata->framesheet.frameinfo.facing, setdata->header.data_name); - framebox->framesheets[setdata->framesheet.frameinfo.facing] = setdata->framesheet; + setdata->framesheet.facing, setdata->header.data_name); + framebox->framesheets[setdata->framesheet.facing] = setdata->framesheet; break; case MSDAT: framebox = ir_set_add_framebox(set, setdata->header.data_name); - if (framebox->mapsheets[setdata->mapsheet.frameinfo.facing].header.data_name != NULL) + if (framebox->mapsheets[setdata->mapsheet.facing].header.data_name != NULL) wprintf("Duplicate mapsheet [%i] %s\n", - setdata->mapsheet.frameinfo.facing, setdata->header.data_name); - framebox->mapsheets[setdata->mapsheet.frameinfo.facing] = setdata->mapsheet; + setdata->mapsheet.facing, setdata->header.data_name); + framebox->mapsheets[setdata->mapsheet.facing] = setdata->mapsheet; break; case ADAT: if (set->audio == NULL) @@ -376,61 +447,101 @@ void ir_set_assign_data void ir_set_assign_ref ( struct ir_set_t* set, - long long ref + uint32_t ref ) -{ if (set->ref != 0) - wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n", - (long unsigned) set->ref, (long unsigned) ref, set->name); +{ uint16_t hash, oldhash; + struct ir_set_t** iters; + struct pagenode_t* iterp; + uint32_t oldref; + oldref = set->ref; + oldhash = 0; + hash = REFHASH(ref); + iterp = refhashpages.root; + check_depth: + iters = ((struct ir_set_t**) iterp->root) + hash; + if (*iters == NULL || *iters == set) + *iters = set; + else + { if (iterp->header.next == NULL) + pagelist_alloc(refhashpages); + iterp = iterp->header.next; + goto check_depth; + } + if (oldref != 0) + { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref, ref, set->name); + if (oldhash != 0) + *iters = NULL; + else + { oldhash = hash; + hash = REFHASH(oldref); + goto check_depth; + } + } set->ref = ref; - //TODO: reflist_add(set); } void ir_data_assign_path ( union ir_setdata_t* setdata, - uint8_t* path + const uint8_t* path ) -{ if (setdata->header.src_filename != NULL) +{ if (path == NULL) + eprintf("Null path in data %s\n", setdata->header.data_name); + if (setdata->header.src_filename != NULL) wprintf("Path override: %s -> %s for setdata %s\n", setdata->header.src_filename, path, setdata->header.data_name); setdata->header.src_filename = name_alloc(path); } union ir_setdata_t* ir_framesheet -( uint8_t* name, - apc_facing d, - int width, - int height +( const uint8_t* name, + struct ir_facinglist_t* facinglist, + int width, + int height ) -{ return ir_framedata(FSDAT, name, d, width, height); } +{ return ir_framedata(FSDAT, name, facinglist, width, height); } union ir_setdata_t* ir_mapsheet -( uint8_t* name, - apc_facing d, - int width, - int height +( const uint8_t* name, + struct ir_facinglist_t* facinglist, + int width, + int height ) -{ return ir_framedata(MSDAT, name, d, width, height); } +{ return ir_framedata(MSDAT, name, facinglist, width, height); } static inline union ir_setdata_t* ir_framedata -( enum dtype type, - uint8_t* name, - apc_facing d, - int width, - int height +( enum dtype type, + const uint8_t* name, + struct ir_facinglist_t* facinglist, + int width, + int height ) { struct ir_framedata_t* framedata = struct_alloc(ir_framedata_t); + struct_clear(framedata); + if (name == NULL) + eprintf("Null name in set allocation\n"); framedata->header.type = type; framedata->header.data_name = name_alloc(name); - framedata->frameinfo.facing = d; - framedata->frameinfo.w = width; - framedata->frameinfo.h = height; + if (facinglist != NULL) + { framedata->facing = facinglist->facing; + framedata->mirrorlist = facinglist->nextsib; + } + else + { framedata->facing = SFACE; + framedata->mirrorlist = NULL; + } + framedata->nextmirror = framedata->mirrorlist; + framedata->w = width; + framedata->h = height; return (union ir_setdata_t*) framedata; } union ir_setdata_t* ir_audio -( uint8_t* name ) +( const uint8_t* name ) { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t); + struct_clear(audio); + if (name == NULL) + eprintf("Null audio\n"); audio->header.type = ADAT; audio->header.data_name = name_alloc(name); return (union ir_setdata_t*) audio; @@ -441,26 +552,32 @@ union ir_setdata_t* ir_audio struct ir_classld_t* ir_classld_from_class ( struct ir_class_t* class ) { struct ir_classld_t* classld; + if (class == NULL) + eprintf("Null class in classld\n"); classld = struct_alloc(ir_classld_t); + struct_clear(classld); classld->root_class = class; return classld; } struct ir_setld_t* ir_setld_from_ref -( long long ref ) +( uint32_t ref ) { struct ir_setld_t* setld; setld = struct_alloc(ir_setld_t); + struct_clear(setld); setld->ref = ref; return setld; } struct ir_setld_t* ir_setld_from_classld ( struct ir_classld_t* classld, - uint8_t* name + const uint8_t* name ) { struct ir_setld_t* setld; setld = struct_alloc(ir_setld_t); + struct_clear(setld); setld->namelist = struct_alloc(ir_namelist_t); + struct_clear(setld->namelist); setld->namelist_head = setld->namelist; setld->namelist_head->name = name_alloc(name); setld->classld = classld; @@ -469,14 +586,16 @@ struct ir_setld_t* ir_setld_from_classld struct ir_setld_t* ir_setld_addchild ( struct ir_setld_t* setld, - uint8_t* name + const uint8_t* name ) { if (setld->namelist == NULL) { setld->namelist = struct_alloc(ir_namelist_t); + struct_clear(setld->namelist); setld->namelist_head = setld->namelist; } else { setld->namelist_head->nextsib = struct_alloc(ir_namelist_t); + struct_clear(setld->namelist_head->nextsib); setld->namelist_head = setld->namelist_head->nextsib; } setld->namelist_head->name = name_alloc(name); @@ -486,54 +605,432 @@ struct ir_setld_t* ir_setld_addchild union ir_setdata_t* ir_link ( enum ltype link_type, struct ir_setld_t* setld, - uint8_t* name + const uint8_t* name ) { struct ir_link_t* link; link = struct_alloc(ir_link_t); + struct_clear(link); link->header.type = LDAT; - link->type = link_type; - link->classld = setld->classld; + link->type = link_type; link->setld = setld; if (link_type != OLINK && name != NULL) link->header.data_name = name_alloc(name); return (union ir_setdata_t*) link; } +/* Return a set's root framebox */ +union ir_setdata_t* ir_set_framebox +( struct ir_set_t* set ) +{ return (union ir_setdata_t*) set->frameboxes; } -static -void* stack_alloc -( size_t bytes ) -{ if (!bytes) //valid behavior to attain current head - return datapages.head->header.head; - if (PL_HEADMEM(datapages) < bytes) - { datapages.head->header.next = (struct pagenode_t*) calloc(datapages.pagesize,1); - if (datapages.head->header.next == NULL) - eprint("Memory allocation error \n"); - datapages.head = datapages.head->header.next; - datapages.head->header.head = datapages.head->root; +/* Return a set's root audio data */ +union ir_setdata_t* ir_set_audio +( struct ir_set_t* set ) +{ return (union ir_setdata_t*) set->audio; } + +/* Return a set's root link data */ +union ir_setdata_t* ir_set_link +( struct ir_set_t* set ) +{ return (union ir_setdata_t*) set->links; } + +#define assert_link(linkdata) if (DEBUG) { \ + if (linkdata->header.type != LDAT) \ + eprintf("Data %s is not a link\n", linkdata->header.data_name); \ + } + +/* Return the link type */ +enum ltype ir_linkdata_type +( union ir_setdata_t* linkdata ) +{ assert_link(linkdata); + return linkdata->link.type; +} + +/* Return the link type */ +uint32_t ir_linkdata_ref +( union ir_setdata_t* linkdata ) +{ assert_link(linkdata); + return linkdata->link.setld->ref; +} + +/* Return the current target set, resolving it first if not present */ +struct ir_set_t* ir_linkdata_set +( union ir_setdata_t* linkdata ) +{ assert_link(linkdata); + if (linkdata->link.trg_set == NULL) + ir_linkdata_resolve_set(linkdata); + return linkdata->link.trg_set; +} + +/* Resolve and assign the link's target set */ +static inline +void ir_linkdata_resolve_set +( union ir_setdata_t* linkdata ) +{ struct ir_class_t* class_iter; + struct ir_namelist_t* namelist_iter,* namelist_iter_last; + struct ir_setld_t* setld; + struct ir_classld_t* classld; + struct ir_set_t* set; + set = NULL; + class_iter = NULL; + assert_link(linkdata); + setld = linkdata->link.setld; + if (linkdata->link.setld == NULL) + eprintf("Link data is invalid\n"); + classld = setld->classld; + if (classld != NULL) + { namelist_iter = classld->namelist; + if (classld->root_class == NULL) + eprintf("No root class for classld\n"); + class_iter = classld->root_class->nextchild; + namelist_iter_last = NULL; + while (class_iter != NULL) + { if (classnames_identical(class_iter->name, namelist_iter->name)) + { if (namelist_iter == classld->namelist_head) + break; + class_iter = class_iter->nextchild; + namelist_iter_last = namelist_iter; + namelist_iter = namelist_iter->nextsib; + } + else + class_iter = class_iter->nextsib; + } + if (class_iter == NULL) + { if (namelist_iter_last) + eprintf("No such subclass \"%s\" of class \"%s\"\n", + namelist_iter->name, + namelist_iter_last->name); + else + { wprintf("No such class \"%s\"\n", namelist_iter->name); + return; + } + } + set = class_iter->root_set; + } + else + set = ir_set_from_ref(setld->ref); + if (set == NULL) + eprintf("Initial set resolution failed\n"); + namelist_iter = setld->namelist; + namelist_iter_last = NULL; + if (setld->namelist != NULL) + { while (set != NULL) + { if (bytes_identical(set->name, namelist_iter->name)) + { if (namelist_iter == setld->namelist_head) + break; + set = set->nextchild; + namelist_iter_last = namelist_iter; + namelist_iter = namelist_iter->nextsib; + } + else + set = set->nextsib; + } + if (set == NULL) + { if (namelist_iter_last) + eprintf("No such subset \"%s\" of set \"%s\"\n", + namelist_iter->name, + namelist_iter_last->name); + else + eprintf("No such set \"%s\" in class \"%s\"\n", + namelist_iter->name, + class_iter->name); + } + } + linkdata->link.trg_set = set; +} + +/* Assign a linkdatas trg_set */ +void ir_linkdata_assign_set +( union ir_setdata_t* link, struct ir_set_t* set ) +{ assert_link(link); + link->link.trg_set = set; +} + +/* Assign a linkdatas type */ +void ir_linkdata_assign_type +( union ir_setdata_t* link, enum ltype type ) +{ assert_link(link); + link->link.type = type; +} + +/* Get, or generate, the fully qualified name of the link's target set */ +uint8_t* +ir_linkdata_dlink_name +( union ir_setdata_t* link ) +{ struct ir_namelist_t* namelist_iter; + struct ir_setld_t* setld; + struct ir_classld_t* classld; + uint8_t* bytep; + size_t bytes; + char setpass; + uint8_t delimiter; + static const uint8_t dlink_prefix[] = { '/', '.', '.', '/' }; +# define dlink_prefix_len 4 + assert_link(link); + if (link->link.dlink != NULL) + return link->link.dlink; + bytes = 0; + setld = link->link.setld; + if (setld == NULL) + eprintf("No setld in dlink\n"); + classld = setld->classld; + if (classld == NULL) + eprintf("No classld in dlink\n"); + if (classld->root_class != NULL) + eprintf("Cannot dlink local class \"%s\"\n", classld->root_class->name); + namelist_iter = classld->namelist; + setpass = 0; + count_bytes_in_namelist: + while (namelist_iter != NULL) + { bytep = namelist_iter->name; + while (*bytep++); + bytes += (bytep - namelist_iter->name); + namelist_iter = namelist_iter->nextsib; } - datapages.head->header.head += bytes; - return (void*) datapages.head->header.head - bytes; + if (setpass == 0) + { setpass = 1; + namelist_iter = setld->namelist; + goto count_bytes_in_namelist; + } + bytes += dlink_prefix_len; + link->link.dlink = stack_alloc(&namepages, bytes); + for (bytes = 0; bytes < dlink_prefix_len; bytes++) + link->link.dlink[bytes] = dlink_prefix[bytes]; + namelist_iter = classld->namelist; + setpass = 0; + delimiter = APC_CLASS_DELIMITER; + copy_bytes_in_namelist: + while (namelist_iter != NULL) + { bytep = namelist_iter->name; + while (*bytep) + link->link.dlink[bytes++] = *bytep++; + link->link.dlink[bytes++] = delimiter; + namelist_iter = namelist_iter->nextsib; + } + if (setpass == 0) + { setpass = 1; + namelist_iter = setld->namelist; + delimiter = APC_SET_DELIMITER; + link->link.dlink[bytes - 1] = delimiter; //overwrite last delimiter + goto copy_bytes_in_namelist; + } + link->link.dlink[bytes] = '\0'; //tailing '\0' null termination + return link->link.dlink; +} + +/* Get a setdata's next sibling */ +union ir_setdata_t* ir_setdata_nextsib +( union ir_setdata_t* setdata ) +{ return setdata->header.nextsib; } + +/* Get a setdata's name */ +uint8_t* ir_setdata_name +( union ir_setdata_t* setdata ) +{ return setdata->header.data_name; } + +/* Get a setdata's filename */ +uint8_t* ir_setdata_filename +( union ir_setdata_t* setdata ) +{ return setdata->header.src_filename; } + +/* Get a setdata's file position */ +long ir_setdata_fpos +( union ir_setdata_t* setdata ) +{ return setdata->header.filepos; } + +/* Set a setdata's file position */ +void ir_setdata_assign_fpos +( union ir_setdata_t* setdata, + long newpos +) +{ setdata->header.filepos = newpos; } + +/* Assign a setdatas name */ +void ir_setdata_assign_name +( union ir_setdata_t* setdata, uint8_t* name ) +{ setdata->header.data_name = name;} + +/* Create a new facinglist from an apc_facing */ +struct ir_facinglist_t* ir_facinglist +( apc_facing facing ) +{ struct ir_facinglist_t* list = struct_alloc(ir_facinglist_t); + list->facing = facing; + return list; +} + +/* Add a child to the facing list */ +struct ir_facinglist_t* ir_facinglist_push +( struct ir_facinglist_t* list, + apc_facing facing +) +{ struct ir_facinglist_t* iter = list; + if (iter != NULL) + { while (iter->nextsib != NULL) + iter = iter->nextsib; + iter->nextsib = struct_alloc(ir_facinglist_t); + iter->nextsib->facing = facing; + } + return list; +} + +#define assert_framebox(fbox) if (DEBUG) { \ + if (fbox->header.type != FBDAT) \ + eprintf("Data %s is not a framebox\n", fbox->header.data_name); \ + } + +/* Return a framebox's specified framesheet */ +union ir_setdata_t* ir_framebox_framesheet +( union ir_setdata_t* fbox, + apc_facing facing +) +{ assert_framebox(fbox); + return (union ir_setdata_t*) &fbox->framebox.framesheets[facing]; +} + +/* Return a framebox's specified mapsheet */ +union ir_setdata_t* ir_framebox_mapsheet +( union ir_setdata_t* fbox, + apc_facing facing +) +{ assert_framebox(fbox); + return (union ir_setdata_t*) &fbox->framebox.mapsheets[facing]; } +#define assert_framedata(fdat) if (DEBUG) { \ + if (fdat->header.type != MSDAT && fdat->header.type != FSDAT) \ + eprintf("Data %s is not a framedata\n", fdat->header.data_name); \ + } + +/* Return a framedata's frame info */ +int ir_framedata_width +( union ir_setdata_t* framedata ) +{ assert_framedata(framedata); + return framedata->mapsheet.w; +} + +/* Return a framedata's frame info */ +int ir_framedata_height +( union ir_setdata_t* framedata ) +{ assert_framedata(framedata); + return framedata->mapsheet.h; +} + +/* Return the next facing in the framedata's facing list, and reset the + 'nextmirror' head to mirrorlist, so that 'ir_framedata_nextmirror' will now + refer to the second facing in the framedata */ +apc_facing ir_framedata_firstfacing +( union ir_setdata_t* framedata ) +{ assert_framedata(framedata); + framedata->mapsheet.nextmirror = framedata->mapsheet.mirrorlist; + return framedata->mapsheet.facing; +} + +/* Return the next facing for this framedata, incrementing the 'nextmirror' + head. Returns FACING_MAX when there are no more facings to return. */ +apc_facing ir_framedata_nextfacing +( union ir_setdata_t* framedata ) +{ apc_facing facing; + assert_framedata(framedata); + if (framedata->mapsheet.nextmirror == NULL) + return FACING_MAX; + facing = framedata->mapsheet.nextmirror->facing; + framedata->mapsheet.nextmirror = framedata->mapsheet.nextmirror->nextsib; + return facing; +} + +/** Allocators **/ static uint8_t* name_alloc -( uint8_t* name_src ) -{ uint8_t* iter, * name; - int head_mem; +( const uint8_t* name_src ) +{ const uint8_t* iter; + uint8_t* name; + int head_mem; + copy: + name = (uint8_t*)namepages.head->header.head; + iter = name_src; + for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && *iter != '.' && head_mem; head_mem--) + *(namepages.head->header.head)++ = *iter++; + if (head_mem < 1) //not enough room + { pagelist_alloc(namepages); + goto copy; + } + *(namepages.head->header.head)++ = '\0'; + return name; +} + +static +uint8_t* classname_alloc +( const uint8_t* name_src ) +{ const uint8_t* iter; + uint8_t* name; + int head_mem; copy: name = (uint8_t*)namepages.head->header.head; iter = name_src; for (head_mem = PL_HEADMEM(namepages); *iter && head_mem; head_mem--) *(namepages.head->header.head)++ = *iter++; - if (head_mem == 0) //not enough room - { namepages.head->header.next = (struct pagenode_t*) calloc(namepages.pagesize,1); - if (namepages.head->header.next == NULL) - eprint("Memory allocation error\n"); - namepages.head = namepages.head->header.next; - namepages.head->header.head = namepages.head->root; + if (head_mem < 1) //not enough room + { pagelist_alloc(namepages); goto copy; } *(namepages.head->header.head)++ = '\0'; return name; } + +static void crawl_class(struct ir_class_t*); +static void crawl_set(struct ir_set_t*,int); + +extern +int binout_init(ir_class); +void ir_test(void) +{ uprintf("IR From Directory: %s\n",getcwd(NULL,255)); + crawl_class(&root_class); + if (root_class.root_set != NULL) + crawl_set(root_class.root_set, 0); + uprintf("starting binaryout \n"); + binout_init(&root_class); +} + + +static +void crawl_class +( struct ir_class_t* class ) +{ struct ir_class_t* iter; + for (iter = class->nextchild; iter != NULL; iter = iter->nextsib) + { wprintf("Crawling class %U/\n", iter->name); + if(chdir((char*)iter->name)) + eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255)); + crawl_class(iter); + if (iter->root_set != NULL) + crawl_set(iter->root_set, 0); + uprintf("%U\\\n",iter->name); + if (chdir("..")) + eprintf("CHDIR ..\n"); + wprintf("Finished crawling class %U/\n", iter->name); + } +} + +#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp) +#define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*))) +static +void crawl_set +( struct ir_set_t* set, + int depth +) +{ struct ir_set_t* iter; + int i; + i = depth * 12; + while (i--) + putchar('.'); + i = depth; + + for(iter = set; iter != NULL; iter = iter->nextchild) + { uprintf("[%10U]", iter->name); + push_setp(iter); + i++; + } + + putchar('\n'); + while (--i >= depth) + if (((iter = pop_setp())->nextsib) != NULL) + crawl_set(iter->nextsib,i); +}