X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fir.c;h=cb5fafd56f715d52a9341736007685863b24daca;hp=ebb2545398acb124a698d4355496cd0e2800c71f;hb=892bb35058d0fd8b92f8f3fa0fbdee4f00aa57f0;hpb=25a23e5134b1d9649f0279a4028b887c9deb9987 diff --git a/src/ir.c b/src/ir.c index ebb2545..cb5fafd 100644 --- a/src/ir.c +++ b/src/ir.c @@ -14,16 +14,22 @@ #include //u8_* functions #include //uint8_t as a char #include //u32_cpy +#include //ulc_fprintf /* Local */ +#include "print.h" #include "apc.h" #include "ir.h" +#undef do_error +#define do_error(...) exit(-1) +#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 */ -enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT }; struct pagenode_t; struct pagenode_header_t { struct pagenode_t* next; @@ -37,6 +43,13 @@ struct pagelist_t { struct pagenode_t* root, * head; size_t pagesize; }; +#define SYS_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)) +/* Set data mem */ +enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT }; struct ir_namelist_t; struct ir_namelist_t { struct ir_namelist_t* nextsib; @@ -51,7 +64,6 @@ struct ir_setld_t long long 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; @@ -90,8 +102,7 @@ struct ir_class_t }; 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; @@ -99,104 +110,86 @@ struct ir_set_t }; /* 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*,const uint8_t*); -static -void ir_free_pagenodes(struct pagenode_t*); +union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int); static inline -int bytes_identical(const uint8_t*,const uint8_t*); +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); +#define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T))) +#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S)))) static -void* stack_alloc(size_t); +uint8_t* name_alloc(const uint8_t*); static -uint8_t* name_alloc(const uint8_t*); +uint8_t* classname_alloc(const uint8_t*); static inline -union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int); -/* Function-Like Macros */ -#define do_warn() do { \ +void* pagelist_pop(struct pagelist_t*,size_t); +#define $($)#$ +#define pagelist_alloc(pagelist) do { \ + pagelist.head->header.next = (struct pagenode_t*) malloc(pagelist.pagesize); \ + if (pagelist.head->header.next == NULL) \ + eprintf("Memory allocation error\n"); \ + struct_clear(pagelist.head->header.next); \ + pagelist.head = pagelist.head->header.next; \ + pagelist.head->header.head = pagelist.head->root; \ } while (0) -#define wprint(str) do { \ - fprintf(stderr, str); \ - do_warn(); \ +#define pagelist_init(pagelist,size) do { \ + pagelist.pagesize = size; \ + pagelist.root = (struct pagenode_t*) malloc(size); \ + if (pagelist.root == NULL) \ + eprintf("Memory allocation error\n"); \ + struct_clear(pagelist.root); \ + pagelist.head = pagelist.root; \ + pagelist.head->header.head = pagelist.head->root; \ } 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 */ +static +void pagenode_free(struct pagenode_t*); +#define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF) + extern //apc.c -long sys_pagesize; +long sys_pagesize; static -struct pagelist_t datapages, namepages; +struct pagelist_t datapages, namepages, refhashpages; static struct ir_class_t root_class = { .name = (uint8_t*)"." }; /* 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); 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); } +/* Recursively clean pagenode linked list, freeing last first */ static -void ir_free_pagenodes +void pagenode_free ( struct pagenode_t* pagenode ) { if (pagenode->header.next != NULL) - ir_free_pagenodes(pagenode->header.next); + pagenode_free(pagenode->header.next); free(pagenode); } -/* Link -*/ +/* Link */ int ir_linker ( void ) -{ return 0; } +{ + return 0; +} -/* Condense -*/ +/* Condense */ int ir_condenser ( void ) { return 0; } @@ -220,26 +213,28 @@ struct ir_class_t* ir_class_addchild const uint8_t* name ) { struct ir_class_t* iter; - printf("Class %s, addchild %s\n", class->name, name); if (class->nextchild == NULL) - goto alloc; + { 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; } - alloc: - 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 @@ -251,14 +246,17 @@ struct ir_set_t* ir_class_addset const uint8_t* name ) { struct ir_set_t* iter; - printf("Class %s, addset %s\n", class->name, name); if (class->root_set == NULL) - goto alloc; + { 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 %s\n", iter->name); + eprintf("Null set added to class %U\n", iter->name); check: if (bytes_identical(iter->name, name)) return iter; @@ -266,13 +264,26 @@ struct ir_set_t* ir_class_addset { iter = iter->nextsib; goto check; } - alloc: - 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; } +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 @@ -282,14 +293,17 @@ struct ir_set_t* ir_set_addchild const uint8_t* name ) { struct ir_set_t* iter; - printf("Set %s, addchild %s\n", set->name, name); if (set->nextchild == NULL) - goto alloc; + { set->nextchild = struct_alloc(ir_set_t); + struct_clear(set->nextchild); + set->nextchild->name = name_alloc(name); + return set->nextchild; + } iter = set->nextchild; - if (iter->name == NULL) - eprintf("Null name pointer in set %p\n", iter); 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; @@ -297,25 +311,30 @@ struct ir_set_t* ir_set_addchild { iter = iter->nextsib; goto check; } - alloc: - 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 ( struct ir_set_t* set, - const uint8_t* name + uint8_t* name ) { struct ir_framebox_t* iter; if (set->frameboxes == NULL) - goto alloc; + { 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)) @@ -324,11 +343,10 @@ struct ir_framebox_t* ir_set_add_framebox { iter = (struct ir_framebox_t*) iter->header.nextsib; goto check; } - alloc: - 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 @@ -347,9 +365,20 @@ int bytes_identical return (ca == cb); } -/* Assign Setdata to Set +static inline +int classnames_identical +( const uint8_t* stra, + const uint8_t* strb +) +{ int ca, cb; + do { + ca = *stra++; + cb = *strb++; + } while (ca && ca == cb); + return (ca == cb); +} - */ +/* Assign Setdata to Set */ void ir_set_assign_data ( struct ir_set_t* set, union ir_setdata_t* setdata @@ -401,13 +430,37 @@ 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 @@ -447,8 +500,9 @@ union ir_setdata_t* ir_framedata int height ) { struct ir_framedata_t* framedata = struct_alloc(ir_framedata_t); + struct_clear(framedata); if (name == NULL) - eprint("Null name in set allocation\n"); + eprintf("Null name in set allocation\n"); framedata->header.type = type; framedata->header.data_name = name_alloc(name); framedata->frameinfo.facing = d; @@ -460,8 +514,9 @@ union ir_setdata_t* ir_framedata union ir_setdata_t* ir_audio ( const uint8_t* name ) { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t); + struct_clear(audio); if (name == NULL) - eprint("Null audio\n"); + eprintf("Null audio\n"); audio->header.type = ADAT; audio->header.data_name = name_alloc(name); return (union ir_setdata_t*) audio; @@ -473,16 +528,18 @@ struct ir_classld_t* ir_classld_from_class ( struct ir_class_t* class ) { struct ir_classld_t* classld; if (class == NULL) - eprint("Null class in classld\n"); + 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; } @@ -493,7 +550,9 @@ struct ir_setld_t* ir_setld_from_classld ) { 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; @@ -506,10 +565,12 @@ struct ir_setld_t* ir_setld_addchild ) { 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); @@ -523,6 +584,7 @@ union ir_setdata_t* ir_link ) { 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; @@ -532,21 +594,33 @@ union ir_setdata_t* ir_link return (union ir_setdata_t*) link; } +static inline +void* pagelist_pop +( struct pagelist_t* pagelist, + size_t size +) +{ size_t headsize = PL_HEADSIZE((*pagelist)); + if (!headsize) + { free(pagelist->head); + pagelist->head = pagelist->root; + while (pagelist->head->header.next != NULL) + pagelist->head = pagelist->head->header.next; + } + if (headsize < size) + eprintf("Attempted to pop unaligned value from pagelist\n"); + pagelist->head->header.head -= size; + return pagelist->head->header.head; +} static void* stack_alloc ( size_t bytes ) -{ if (!bytes) //valid behavior to attain current head - return datapages.head->header.head; +{ void* p; 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; - } + pagelist_alloc(datapages); + p = datapages.head->header.head; datapages.head->header.head += bytes; - return (void*) datapages.head->header.head - bytes; + return p; } static @@ -558,16 +632,80 @@ uint8_t* name_alloc copy: name = (uint8_t*)namepages.head->header.head; iter = name_src; - for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && head_mem; head_mem--) + for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && *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 +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 < 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); +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); +} + +static +void crawl_class +( struct ir_class_t* class ) +{ struct ir_class_t* iter; + for (iter = class->nextchild; iter != NULL; iter = iter->nextsib) + { wprintf("%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"); + } +} + +static +void crawl_set +( struct ir_set_t* set, + int depth +) +{ struct ir_set_t* setlist[64], ** slp, * iter; + int i = depth * 12; + while (i--) + putchar('.'); + i = depth; + slp = setlist; + for(iter = set; iter != NULL; iter = iter->nextchild) + { uprintf("[%10U]", iter->name); + *slp++ = iter; + i++; + } + --i; + putchar('\n'); + for(iter = *--slp; slp >= setlist; iter = *--slp, --i) + if (iter->nextsib != NULL) + crawl_set(iter->nextsib,i); +}