X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fir.c;h=bdf0d36e23468ad00a5f264aef40abea4d299380;hp=e61d388f466c782efeae8be5dbbd7b2745d612f8;hb=f4410cd4b87c75bb112264cf38951461065b7ef9;hpb=03bec8cb89af10a1bac8f7bd90484f6cb32fbad5 diff --git a/src/ir.c b/src/ir.c index e61d388..bdf0d36 100644 --- a/src/ir.c +++ b/src/ir.c @@ -17,12 +17,11 @@ #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" -#undef do_error -#define do_error(...) exit(-1) #define XXH_PRIVATE_API #include "../xxHash/xxhash.h" /* Public */ @@ -65,8 +64,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 @@ -98,6 +98,8 @@ struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*,uint8_t*); static inline union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int); static inline +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*); @@ -110,10 +112,12 @@ uint8_t* classname_alloc(const uint8_t*); #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T))) extern //apc.c long sys_pagesize; +extern //apc.c +char* apc_package_name; static 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 @@ -121,7 +125,7 @@ int ir_init { 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; } @@ -592,8 +596,7 @@ union ir_setdata_t* ir_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); @@ -615,72 +618,188 @@ 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 ) -{ if (linkdata->header.type != LDAT) - eprintf("Data %s is not a link\n", linkdata->header.data_name); +{ assert_link(linkdata); return linkdata->link.type; } /* Return the link type */ uint32_t ir_linkdata_ref ( union ir_setdata_t* linkdata ) -{ if (linkdata->header.type != LDAT) - eprintf("Data %s is not a link\n", linkdata->header.data_name); +{ assert_link(linkdata); return linkdata->link.setld->ref; } -/* Resolve and return the link's target set */ +/* 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; + 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; - if (linkdata->header.type != LDAT) - eprintf("Data %s is not a link\n", linkdata->header.data_name); + class_iter = NULL; + assert_link(linkdata); setld = linkdata->link.setld; if (linkdata->link.setld == NULL) eprintf("Link data is invalid\n"); - classld = linkdata->link.classld; + 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) - eprintf("Class resolution failed\n"); + { 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 if (setld->ref) + else set = ir_set_from_ref(setld->ref); if (set == NULL) eprintf("Initial set resolution failed\n"); namelist_iter = setld->namelist; - while (set != NULL) - { if (bytes_identical(set->name, namelist_iter->name)) - { if (namelist_iter == setld->namelist_head) - break; - set = set->nextchild; - namelist_iter = namelist_iter->nextsib; - } - else - set = set->nextsib; + 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; } - return set; + 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 */ @@ -710,6 +829,11 @@ void ir_setdata_assign_fpos ) { 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;} + /* Return a framebox's specified framesheet */ union ir_setdata_t* ir_framebox_framesheet ( union ir_setdata_t* fbox,