From: Jordan Date: Thu, 15 Dec 2016 19:43:37 +0000 (-0800) Subject: apc init X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=commitdiff_plain;h=a58c4564255146d9a9c7d4ee095558c91eaa874e apc init --- a58c4564255146d9a9c7d4ee095558c91eaa874e diff --git a/.gdb/ir.o b/.gdb/ir.o new file mode 100644 index 0000000..ce9ee2e Binary files /dev/null and b/.gdb/ir.o differ diff --git a/.gdb/irmem.o b/.gdb/irmem.o new file mode 100644 index 0000000..7822d5f Binary files /dev/null and b/.gdb/irmem.o differ diff --git a/.gdb/lexer.o b/.gdb/lexer.o new file mode 100644 index 0000000..5833e5a Binary files /dev/null and b/.gdb/lexer.o differ diff --git a/.gdb/lexer_fsm.o b/.gdb/lexer_fsm.o new file mode 100644 index 0000000..0ca1af2 Binary files /dev/null and b/.gdb/lexer_fsm.o differ diff --git a/.gdb/lexer_lex.o b/.gdb/lexer_lex.o new file mode 100644 index 0000000..a673dcf Binary files /dev/null and b/.gdb/lexer_lex.o differ diff --git a/.gdb/output.o b/.gdb/output.o new file mode 100644 index 0000000..90e6880 Binary files /dev/null and b/.gdb/output.o differ diff --git a/.gdb/parser-save.tab.o b/.gdb/parser-save.tab.o new file mode 100644 index 0000000..4b63af1 Binary files /dev/null and b/.gdb/parser-save.tab.o differ diff --git a/.gdb/parser.tab.o b/.gdb/parser.tab.o new file mode 100644 index 0000000..d6f43c4 Binary files /dev/null and b/.gdb/parser.tab.o differ diff --git a/.gdb/scanner.o b/.gdb/scanner.o new file mode 100644 index 0000000..595a41c Binary files /dev/null and b/.gdb/scanner.o differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86a7b85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.tab.c +*.tab.h +lexer_lex.c diff --git a/apc.h b/apc.h new file mode 100644 index 0000000..6a8df1e --- /dev/null +++ b/apc.h @@ -0,0 +1,33 @@ +#include +#include +#include + +//ir.h +#define BUF_SIZE 256 +#define MAX_SETS 256 +#define MAX_ELES 256 +#define MAX_QUADS 256 +#define MAX_MODELS 256 +#define MAX_MODEL_LEN 256 +#define MAX_MAPS 8 +#define MAX_POSTS 256 +#define MAX_CLASS_DEPTH 256 +#define MAX_CLASSES 256 +#define MAX_FRAMES 256 +#define PTRS_IN_PAGE 1024 +#define MAX_CHUNKS 256 +#define PAGES_PER_CHUNK 16 +#define MAX_DEPTH 8 +//irmem.c +#define PAGES_PER_CHUNK 16 +#define MAX_NAME_LEN 128 +#define MAX_DEPTH 8 +//lexer.c +#define FNAME_MAX 1024 +#define FPATH_MAX 8192 + + +struct name +{ + uint8_t name[MAX_NAME_LEN]; +}; diff --git a/ir.c b/ir.c new file mode 100755 index 0000000..8652ddc --- /dev/null +++ b/ir.c @@ -0,0 +1,1336 @@ +/*!@file + \brief IR Memory Implementation + \details Intermediary memory management + \author Jordan Lavatai + \date Aug 2016 + ----------------------------------------------------------------------------*/ +#include +#include +#include //uint8_t as a char +#include //u32_cpy +#include //uint64_t +#include //memset +#include //u8_* functions +#include "apc.h" + + +extern +int +name_u8_cpy(struct name*, struct name*); + +extern +int +name_u8_cmp(struct name*, struct name*); + +extern +int +name_u8_set(struct name*, ucs4_t); + +int +ir_init(void); +struct cdat* +alloc_cdat(void); +struct odat* +alloc_odat(void); +void +alloc_vdat(void); +struct link* +alloc_link(void); +struct ref* +alloc_ref(void); +struct set* +alloc_set(void); +struct cdat* +curr_cdat(void); +struct odat* +curr_odat(void); +struct vdat* +curr_vdat(void); +struct map* +curr_map(void); +struct set* +curr_cdat_set(void); +struct set* +curr_set(int); +struct ref* +curr_ref(void); +struct model* +curr_model(void); + +/* ir.c */ +void +inc_posts(void); +void +push_cdat(struct name*); +void +pop_cdat(void); +void +insert_link_name(struct name*); +void +insert_link_namelist(struct name*); +void +insert_ss_name(struct name*); +void +insert_ss_namelist(struct name*); +void +insert_mlink(struct name*, int); +void +insert_vlink(struct name*, int); +void +insert_ref(struct odat*, int); +void +alloc_vdat(void); +void +insert_vdat(void); +void +insert_map(struct name*, int, int, int, int, uint8_t*); +void +insert_framesheet(struct name*, int, int, int, int, uint8_t*); + + + +//type safety handled by macro expansion (do not call these directly from code, make dependent macros for access to these) +#define CHUNKS_LEN(STACK) ((STACK).csp - (STACK).chunks) +#define CURRENT_CHUNK(STACK) ((STACK).chunks[CHUNKS_LEN(STACK) - 1]) +#define CHUNKS_FULL(STACK) ( (STACK).csp >= \ + (STACK).chunks + MAX_CHUNKS * (STACK).chunk_size) +#define CURRENT_DSP(STACK,TYPE) ((TYPE*) ((STACK).dsp[CHUNKS_LEN(STACK) - 1])) +#define DATA_FULL(STACK,TYPE) ((void*) CURRENT_DSP(STACK,TYPE) >= \ + (CURRENT_CHUNK(STACK) + (STACK).chunk_size)) +#define CSP_PUSH(STACK) (*(++(STACK).csp) = malloc((STACK).chunk_size)) +#define CURRENT_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 1]) +#define PREVIOUS_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 2]) +#define ALLOC_DAT(STACK,TYPE) (++CURRENT_DATP(STACK,TYPE)) +#define INIT_STACK(STACK,TYPE) \ + { int i; \ + (STACK).chunk_size = PAGES_PER_CHUNK * pagesize; \ + (STACK).max_dats = (STACK).chunk_size / sizeof (TYPE); \ + CSP_PUSH(STACK); \ + for( i = 0; i < MAX_CHUNKS; i++){ \ + (STACK).dsp[i] += pagesize; \ + } \ + } +//Stack-specific macros (called directly from code (safety enforcement) +#define INIT_ODAT() (INIT_STACK(ocs, struct odat)) +#define CURRENT_ODAT() (CURRENT_DATP(ocs,struct odat)) +#define ODAT_FULL() (DATA_FULL(ocs,struct odat)) +#define ODAT_ALLOC() (ALLOC_DAT(ocs,struct odat)) +#define OCS_FULL() (CHUNKS_FULL(ocs)) +#define INIT_VDAT() (INIT_STACK(vcs, struct vdat)) +#define CURRENT_VDAT() (CURRENT_DATP(vcs,struct vdat)) +#define VDAT_FULL() (DATA_FULL(vcs,struct vdat)) +#define VDAT_ALLOC() (ALLOC_DAT(vcs,struct vdat)) +#define VCS_FULL() (CHUNKS_FULL(vcs)) +#define INIT_CDAT() (INIT_STACK(ccs, struct cdat)) +#define CURRENT_CDAT() (CURRENT_DATP(ccs,struct cdat)) +#define CDAT_FULL() (DATA_FULL(ccs, struct cdat)) +#define CDAT_ALLOC() (ALLOC_DAT(ccs, struct cdat)) +#define CCS_FULL() (CHUNKS_FULL(ccs)) +#define INIT_SET() (INIT_STACK(scs, struct set)) +#define CURRENT_SET() (CURRENT_DATP(scs, struct set)) +#define SET_FULL() (DATA_FULL(scs, struct set)) +#define SET_ALLOC() (ALLOC_DAT(scs, struct set)) +#define SCS_FULL() (CHUNKS_FULL(scs)) +#define INIT_LINK() (INIT_STACK(lcs, struct link)) +#define CURRENT_LINK() (CURRENT_DATP(lcs,struct link)) +#define LDAT_FULL() (DATA_FULL(lcs, struct link)) +#define LDAT_ALLOC() (ALLOC_DAT(lcs, struct link)) +#define LCS_FULL() (CHUNKS_FULL(lcs)) +#define INIT_POST() (INIT_STACK(rcs, struct ref)) +#define CURRENT_POST() (CURRENT_DATP(pcs,struct ref)) +#define POST_FULL() (DATA_FULL(pcs,struct ref)) +#define POST_ALLOC() (ALLOC_DAT(pcs,struct ref)) +#define PCS_FULL() (CHUNKS_FULL(pcs)) +#define INIT_REF() (INIT_STACK(rcs, struct ref)) +#define CURRENT_REF() (CURRENT_DATP(rcs,struct ref)) +#define PREVIOUS_REF() (PREVIOUS_DATP(rcs, struct ref)) +#define REF_FULL() (DATA_FULL(rcs,struct ref)) +#define REF_ALLOC() (ALLOC_DAT(rcs,struct ref)) +#define RCS_FULL() (CHUNKS_FULL(rcs)) +//Metadata +#define CURRENT_MODEL() (CURRENT_VDAT()->model_list[CURRENT_VDAT()->num_models]) + + + +/* Dynamically allocate memory for a class data structure, + or cdat, after a class has been identified in a grammar. + We also create a stack of class pointers so that + we can access the cdat during processing of that + cdats sets and elements, a requirement because the + nature of recursive classes prevents us from accessing + the cdat based on the previous index into cdat_buf, + which is a list of all allocated cdats +/* Cdats: A cdat is a class data structure. Cdats serve as the central */ +/* data types of the IR. Cdats contain pointers to their subclasses so that the relationship between */ +/* classes can be determined, but the subclasses are not represented inside */ +/* of the cdat itself but rather in subsequent cdats in cdat_buf. We */ +/* can determine the number of subclasses (the last index into cdat_buf */ +/* that represents a subclass of some arbitrary cdat) each cdat has by */ +/* incrementing num_classes during parse time. */ +/* TODO: Should classes point to their parent class? */ +/* TODO: Talk more about cdat set structure */ +struct cdat { + struct name name; + int idx; + int num_classes; + int num_sets; + struct cdat* class_list[MAX_CLASSES]; + struct set* set_list[MAX_SETS]; +}; + + +/* Sets: What is a set? + Instantiation? + Associations? + Containment? + Usage? + The set is populated at parse time AFTER the elements are populated, due to + the nature of bottom up parsing. */ +struct set { + int cdat_idx; + int num_sets; + struct set* set_list[MAX_SETS]; +}; + +/* Refs: Each set/ele has a reference to its object data (odat) through a refid. + refids are unsigned 64 byte integers that map to the hex values RGBA. During + the construction of the directory structure, users can choose a RGBA value for + each object that any other object can refer to via links (see link). If a user + does not choose an RGBA value, then the object is given one from the system space. + We maintain a doubly linked list of refs in the ref_buf at parse time so that + links can be resolved after the parsing of the directory structure is complete. + For every 16th ref, we create a post so that we can reduce on the search time for + a random access. */ + +struct ref { + int type; //TODO: Is this needed? + struct ref* nextref; + struct ref* lastref; + struct odat* odatp; + int refid; //0xFFFFFF->digit +}; + +/* Links: At parse time, a set/ele can include a link in their + grammar representation instead of the actual data and this signifies + to the APC that that set/ele wishes to use the data of another + set/ele, either its video data (vdat) or object data (odat). The link + itself contains the type of link it is, the refid OR name, and + which set/ele created the link. During parse time, links can be made + to o/vdats that have yet to be parsed. In order to accomodate for this, + we resolve all links AFTER parse time by iterating through the link_buf, + finding the refid that was stored for some object (if the refid exists), + and creating a relative pointer from the original object to the data that + was linked */ + +/* TODO: Explain links more betta */ + +struct olink { + int src_refid; +}; + +struct vlink { + int src_refid; + struct name src_animname; + struct name src_namelist[MAX_DEPTH]; +}; + +struct mlink { + int src_refid; + struct name src_mapname; + struct name src_namelist[MAX_DEPTH]; + +}; + +union link_t { + struct vlink vlink; + struct mlink mlink; + struct olink olink; +}; + + +/* From: src odat ()To: dest odat (refid)*/ +struct link { + int type; //1 = olink, 2 = vlink, 3 = mlink + union link_t link_t; + int dest_refid; //if it exists + struct odat* dest_odatp; + +}; + +struct map { + struct name name; + int height; + int width; + uint8_t filepath[FPATH_MAX]; +}; + +/* Odats: Odats consist of the object data necessary for + each object. Odats are sometimes referred to as archetypes + at compile-time, in order to distinguish the difference from + a runtime object and a compile-time object. + TODO: Need more info about objects at runtime, to described + the reasoning behind odat structure at compile-time*/ +struct odat { + struct name name; + int refid; + int ismap; + int vdat_idx; + struct link* linkp; + struct vdat* vdatp; + struct odat* parent_odatp; // odat == set ? null : set refid + struct ref* refp; /* pointer to it's ref on ref_list */ + struct map map; //only valid if odat ismap + +}; + +/* A framesheet is a grouping of animation frames in + a single direction (N,W,S,E) */ +struct framesheet { + int width; + int height; + int num_frames; + +}; + +/* A model is a collection of framesheets for every + direction (N,W,S,E,NW,NE,SW,SE)*/ +/* NAMED spritesheet */ +struct model { + struct name name; + uint8_t filepath[PATH_MAX]; + struct framesheet spritesheet[8]; //one for each +}; + +/* Vdat: Vdats are the video data of each object. They can not be + created as a stand alone object (because they consist solely + of animation information and not the map which the + animation manipulates). Vdats have a list of models for every + animation that the vdats odat can do for that vdat*/ +struct vdat { + struct odat* creator; //pointer to odat that made this vdat + int num_models; + uint8_t filename[FNAME_MAX]; + int height; + int width; + uint8_t filepath[FPATH_MAX]; + struct model model_list[MAX_MODELS]; +}; + + +struct set_frame +{ struct name namelist[MAX_DEPTH]; + int num_names; + struct set* setp; + struct odat* odatp; +} ; + + + +struct set_stack +{ struct set_frame set_frames[MAX_DEPTH]; + int curr_depth; //used to get most recently created set/odat + to check for undefined parents of namelists +}; + + +//"type free" chunk stacking +struct chunk_stack +{ void* chunks[MAX_CHUNKS]; + void* *csp; //chunk stack pointer + void* dsp[MAX_CHUNKS]; //dat stack pointer (per chunk) + int chunk_size; //size of a chunk (including its forfeited page) + int max_dats; //number of dats per chunk for this stack +} ocs, vcs, ccs, rcs, lcs, pcs, scs; //odat, vdat, cdat, ref, link, post stacks + + + + +/* The cdat_stack is a stack pointers to cdat pointers, the top of which is + the cdat that is currently being parsed. Whenever a new cdat is recognized + by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer + to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have + access to the current cdat so that the elements and sets can populate themselves + in the cdat accordingly. */ + + +struct cdat* cdat_stack[MAX_CLASSES]; +struct cdat** cdat_stackp; + +struct set_stack ss; +struct name set_namelist[MAX_DEPTH]; +int set_numnames = 0; + +struct name link_namelist[MAX_DEPTH]; +int link_numnames = 0; + +int num_cdats = 0; +int num_odats = 0; +int num_vdats = 0; +int num_sets = 0; +int num_refs = 0; +int ss_refid = 0x0FFFFFFF; /* system space for refids */ +int num_posts = 0; +int num_links = 0; +int num_models = 0; +long pagesize = 0; + + +/* The initalization function of the IR. */ +int +ir_init() +{ struct name name; + + + uint8_t root[4] = "root"; + + u8_stpncpy(name.name, root, 4); + + pagesize = sysconf(_SC_PAGESIZE); + printf("pagesize is %l\n", pagesize); + + INIT_CDAT(); + *cdat_stackp = CURRENT_CDAT(); + name_u8_cpy(&(*cdat_stackp)->name, &name); + + INIT_ODAT(); + INIT_VDAT(); + VDAT_ALLOC(); //NULL vdat + VDAT_ALLOC(); //First vdat req. because alloc_vdat happens after vdat is reduced + INIT_SET(); + INIT_LINK(); + INIT_REF(); + INIT_POST(); + + + return 0; + +} + +void +ir_quit() +{ + int i; + + for(i = 0; i < CHUNKS_LEN(ccs) ; i++) + { + free(ccs.chunks[i]); + } + for(i = 0; i < CHUNKS_LEN(ocs); i++) + { + free(ocs.chunks[i]); + } + for(i = 0; i < CHUNKS_LEN(vcs) ; i++) + { + free(vcs.chunks[i]); + } + for(i = 0; i < CHUNKS_LEN(rcs); i++) + { + free(rcs.chunks[i]); + } + for(i = 0; i < CHUNKS_LEN(lcs); i++) + { + free(lcs.chunks[i]); + } + for(i = 0; i < CHUNKS_LEN(pcs); i++) + { + free(pcs.chunks[i]); + } + +} + +struct cdat* +alloc_cdat() +{ + num_cdats++; + if(CDAT_FULL()) + { if(CCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) cdats ", num_cdats); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(ccs); + } + else + CDAT_ALLOC(); + + return CURRENT_CDAT(); +} + +//these should probably be inline +struct odat* +alloc_odat +() +{ + num_odats++; + if(ODAT_FULL()) + { if(!OCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) odats ", num_odats); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(ocs); + } + else + ODAT_ALLOC(); + + return CURRENT_ODAT(); +} + +void +alloc_vdat +() +{ num_vdats++; + if(VDAT_FULL()) + { if(!VCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) vdats ", num_vdats); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(vcs); + } + else + VDAT_ALLOC(); + + +} + +struct set* +alloc_set +() +{ num_sets++; + if(SET_FULL()) + { if(!SCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) sets ", num_sets); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(scs); + } + else + SET_ALLOC(); + + return CURRENT_SET(); +} + + +struct link* +alloc_link +() +{ num_links++; + if(LDAT_FULL()) + { if(!LCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) links ", num_links); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(lcs); + } + else + LDAT_ALLOC(); + + return CURRENT_LINK(); + +} + +struct ref* +alloc_ref +() +{ num_refs++; + if(REF_FULL()) + { if(!RCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) refs ", num_refs); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(rcs); + } + else + REF_ALLOC(); + + + if(num_refs % 16 == 0) + { CURRENT_POST() = CURRENT_REF(); + inc_posts(); + } + + return CURRENT_REF(); +} + +void +inc_posts() +{ num_posts++; + if(POST_FULL()) + { if(!PCS_FULL()) + { fprintf(stderr, "You have allocated to many (%d) refs ", num_posts); + exit(EXIT_FAILURE); + } + else + CSP_PUSH(pcs); + } + else + POST_ALLOC(); + +} + +struct cdat* +curr_cdat +() +{ + return (*cdat_stackp); +} + +struct odat* +curr_odat +() +{ + return CURRENT_ODAT(); +} + +struct vdat* +curr_vdat +() +{ + return CURRENT_VDAT(); +} + +struct set* +curr_cdat_set +() +{ + return CURRENT_SET(); +} + +struct set* +curr_set +(int depth) +{ int i; + struct set* setp; + + for(i = 0; i <= depth; i++) + { if(!(setp = setp->set_list[setp->num_sets])) + { printf("You are trying to access a set that does not exist irmem.c\n"); + return NULL; + } + } + + + return setp; +} + +struct ref* +curr_ref +() +{ + return CURRENT_REF(); +} +struct ref* +prev_ref +() +{ + return PREVIOUS_REF(); +} +struct model* +curr_model +() +{ + return &CURRENT_MODEL(); +} + +/* IR.C*/ +void +push_cdat +( name ) + struct name* name; +{ + struct cdat* curr_cdatp; + + curr_cdatp = alloc_cdat(); + + name_u8_cpy(&curr_cdatp->name, name); + curr_cdatp->idx = num_cdats; + + /* Set the cdat as a subclass of the previous cdat */ + (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes] = curr_cdatp; + /* Push the cdat onto the cdat_stack */ + *++cdat_stackp = curr_cdatp; + +} + +void +pop_cdat +() +{ + cdat_stackp--; +} + + +void +insert_set_name +( name ) + struct name* name; +{ + //Push name onto current namelist, set the set_namelist. + name_u8_cpy(&set_namelist[set_numnames++], name); + + +} + + +void +insert_set_namelist +( name ) + struct name* name; +{ int depth, nameidx, i; + + insert_set_name(name); + + //Check if entire string matches first? Only possible if namelist is contiguous (uint8_t strings seperated by \0) + //Create odats/sets for each name in namelist where nameidx > ns_depth + //first check if any parts of namelist matches what is currently on namestack + //we can gauruntee that from ns_depth + 1 -> set_numnames namelists dont match. x + + + //if name_list doesnt match, from the first depth at which namelist doesnt match + //remove the nameframes namelist (zero out ones below?) and replace with current namelist, + //then allocate a new odat and set it to the current set_frame. + for( depth = 0; depth < set_numnames ; depth++ ) + { for (nameidx = 0; nameidx <= depth; nameidx++) + { if( name_u8_cmp(&set_namelist[nameidx], &ss.set_frames[depth].namelist[nameidx]) != 0 ) + { /* Populate the namelist of the set at the current depth */ + for(i = 0; i <= depth; i++) + name_u8_cpy(&ss.set_frames[depth].namelist[i], &set_namelist[i]); + + /* Alloc set and odat */ + ss.set_frames[depth].odatp = alloc_odat(); + ss.set_frames[depth].setp = alloc_set(); + + /* populate set/odat name and cdat_idx */ + name_u8_cpy(&ss.set_frames[depth].odatp->name, &set_namelist[depth]); + ss.set_frames[depth].setp->cdat_idx = ( *cdat_stackp)->idx; + + /* Insert allocated set and odat into their respective trees if there is a depth + (they have parents) */ + if(depth) + { ss.set_frames[depth].odatp->parent_odatp = ss.set_frames[depth-1].odatp; + if(ss.set_frames[depth-1].setp->num_sets < MAX_SETS) + ss.set_frames[depth-1].setp->set_list[ss.set_frames[depth-1].setp->num_sets++] = ss.set_frames[depth].setp; + else + { printf("you have allocated too many sets in insert_namelist()\n"); + //TODO: EXIT() + } + } + else /* no parent set, so assign to cdat set_list */ + { ss.set_frames[depth].odatp->parent_odatp = NULL; //no parent odat = NULL. + if(curr_cdat_set()->num_sets < MAX_SETS) + curr_cdat_set()->set_list[curr_cdat_set()->num_sets++] = ss.set_frames[depth].setp; + else + { printf("you have allocated too many sets in insert_namelist()\n"); + //TODO: EXIT() + } + } + + + ss.set_frames[depth].num_names = set_numnames; + ss.curr_depth = depth; + } + + } + + } + done: + ; +} + +/*. We create new odats for each map variant that are children of the current odat/set + , set their name as the map name, and identify them by marking them as a map. This lets + us distinguish between sibling odatsthat have the same name because the map of the parent + odat had the same name as another, regular odat*/ +#define CURR_SS_FRAME() (ss.set_frames[ss.curr_depth]) +#define CURR_SS_SETP() (CURR_SS_FRAME().setp) +#define CURR_SS_ODATP() (CURR_SS_FRAME().odatp) +void +insert_map +( name, direction, height, width, refid, filepath ) + struct name* name; + int direction, height, width, refid; + uint8_t* filepath; +{ int i; + struct odat* curr_mem_odatp; //pointer to odat in odat_buf + struct set* curr_mem_setp; //pointer to set in set_buf + struct link* linkp; + + curr_mem_odatp = alloc_odat(); + curr_mem_setp = alloc_set(); + //Create a new odat, make its parent be the set. Make a set for mdat, its name should + //be the name of the odat + name of model. That makes a conflict beween odats that are named + //the same thing as the model of a sibling odat that was created from a map. They can have + //same name if the map odat is marked. So mark the map odat. + + //insert parent odat + curr_mem_odatp->parent_odatp = CURR_SS_ODATP(); + //insert into set_list + if(CURR_SS_SETP()->num_sets < MAX_SETS) + CURR_SS_SETP()->set_list[CURR_SS_SETP()->num_sets++] = curr_mem_setp; + else + { printf("You have allocated to many sets, error in insert_map()\n"); + //TODO: EXIT() + } + + //indicate that newly created odat is a map + curr_mem_odatp->ismap = 1; + //set odat and set name + name_u8_cpy(&curr_mem_odatp->name, name); + + /* set cdat idx values for both set and odat */ + curr_mem_setp->cdat_idx = num_cdats; + + + /* Generate refid if needed, put into ref_buf */ + if(!refid) + refid = ss_refid++; + + insert_ref(curr_mem_odatp, refid); + + /* If current odatp on stack has a link, then we need to make our own link. just set the vdat_idx */ + if(CURR_SS_ODATP()->vdat_idx = 0) + { //alloc a link + linkp = alloc_link(); + linkp->type = CURR_SS_ODATP()->linkp->type; + linkp->dest_odatp = CURR_SS_ODATP(); + linkp->dest_refid = refid; + linkp->link_t.mlink.src_refid = CURR_SS_ODATP()->linkp->link_t.mlink.src_refid; + + /* Copy the animation name of the vlink*/ + name_u8_cpy(&linkp->link_t.vlink.src_animname, &CURR_SS_ODATP()->linkp->link_t.vlink.src_animname); + /* Copy the namelist of the vlink*/ + for(i = 0; i < MAX_DEPTH; i++) + name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &CURR_SS_ODATP()->linkp->link_t.vlink.src_namelist[i]); + } + else + curr_mem_odatp->vdat_idx = CURR_SS_ODATP()->vdat_idx; + + + + +} + + +/* 11/22 Each vdat has a multiple models. Each model has 8 framesheets, one in each + direction, that create a spritesheet. Inserting framesheets into the correct + model is just a matter of checking whether or not the last models name matches + + the current one. We can never get a framesheet that is for the same model before + AND after some other model, due to alphasorting of the files in each directory */ +void +insert_framesheet +( model_name, direction, height, width, refid, filepath ) + struct name* model_name; + int direction, height, width, refid; + uint8_t* filepath; +{ struct vdat* curr_vdatp; + struct model* curr_modelp; + static struct name last_model_name[32]; + + + curr_vdatp = curr_vdat(); + + /* If the model name changed, that means there are no more + framesheets for that model to be processed, a guaruntee we make + b/c the filenames are alphabetically sorted */ + if(!name_u8_cmp(last_model_name, model_name)) + { if(curr_vdatp->num_models) + curr_vdatp->num_models++; + num_models++; // total number of models + } + + + if(CURR_SS_ODATP()->refid == 0) + { if(!refid) + refid = ss_refid++; + insert_ref(CURR_SS_ODATP(), refid);//given a odatp and a refid, insert the odatp into the ref_buf. + //push ref into ref_buf. + } + else + printf("error: redefining a previously set refid\n"); + + curr_modelp = curr_model(); + + name_u8_cpy(&curr_modelp->name, model_name); + curr_modelp->spritesheet[direction].height = height; + curr_modelp->spritesheet[direction].width = width; + + name_u8_cpy(last_model_name, model_name); + + +} + + + +//src_path is stored in link_namelist +void +insert_mlink +( src_mapname, src_refid) + struct name* src_mapname; + int src_refid; +{ struct link* linkp; + int i; + + linkp = alloc_link(); + + /* set type */ + linkp->type = 3; + /* set the name of the src map for the link, if a name exists */ + if(src_mapname) + name_u8_cpy(&linkp->link_t.mlink.src_mapname, src_mapname); + /* Set the source ref id of the link */ + linkp->link_t.mlink.src_refid = src_refid; + /* Copy the entire namelist of the link, if it exists */ + for(i = 0; i < link_numnames; i--) //TODO MAX_DEPTH -> link_namelist_num?? + { name_u8_cpy(&linkp->link_t.mlink.src_namelist[i], &link_namelist[i]); + name_u8_set(&link_namelist[i], (ucs4_t) 0); + } + link_numnames = 0; + + linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack + +} + +void +insert_link_name +( name ) + struct name* name; +{ + //Push name onto current namelist, set the set_namelist. + name_u8_cpy(&link_namelist[link_numnames++], name); + +} + +/* Nearly identical to mlink */ +void +insert_vlink +( src_animname, src_refid ) + struct name* src_animname; + int src_refid; +{ struct link* linkp; + int i; + + linkp = alloc_link(); + + /* set type */ + linkp->type = 2; + + /* set the name of the src animname for the link, if a name exists */ + if(src_animname) + name_u8_cpy(&linkp->link_t.vlink.src_animname, src_animname); + + /* Set the source ref id of the link */ + linkp->link_t.mlink.src_refid = src_refid; + + /* Copy the entire namelist of the link, if it exists */ + for(i = 0; i < link_numnames; i++) //TODO MAX_DEPTH -> link_namelist_num?? + { name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &link_namelist[i]); + name_u8_set(&link_namelist[i], (ucs4_t) 0);//set to null for next link_namelist + } + + linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack + +} + + +/* TODO: Do we really need to store the prev/next pointer? iterating through the + ref_buf could be achieved by iterating until the num_refs anyway. */ +void +insert_ref +( odatp, refid ) + struct odat* odatp; + int refid; +{ struct ref* curr_refp; + struct ref* prev_refp; + + curr_refp = alloc_ref(); + prev_refp = prev_ref(); + + prev_refp->nextref = curr_refp; + curr_refp->lastref = prev_refp; + + curr_refp->odatp = odatp; + curr_refp->refid = refid; + + if(refid % 16) + { POST_ALLOC(); + CURRENT_POST()->refid = refid; + CURRENT_POST()->odatp = odatp; + } + + + +} + +void +insert_vdat +() +{ struct odat* curr_ss_odatp; + struct vdat* curr_vdatp; + + curr_vdatp->creator = curr_ss_odatp; + curr_ss_odatp->vdat_idx = num_vdats; + curr_ss_odatp->vdatp = curr_vdatp; + alloc_vdat(); +} + +void +insert_refid_statement +( refid ) + int refid; +{ CURR_SS_ODATP()->refid = refid; +} +#if 0 + + +/* Called in the reduction of a set. While both odats (eles and sets) + have identical label terminals, we are unable to give a single grammatical rule + for both due to how we allocate odats in the odat buf. Due to the + nature of bottom up parsing, the set label is recognized first, and then the + sets elements are recognized. This means that after we have processed the sets elemenets, + the curr_odat is going to be the last element and NOT the set that was first allocated. + To get around this, we create a global variable set_odatp that will store the pointer + to the odat when it is first allocated (in insert_set_label()) so that insert_set() can + have access to it. Curr set points the sets representation in the cdat, curr_set_odatp + points to the sets representation as an odat*/ + +//TODO: Add insert_set_ref() +//TODO: Is this the correct allocation scheme? No do the one ken suggested +void +insert_s_name +( struct name* name +) +{ + + struct set* curr_setp; + + curr_setp = curr_set(); + curr_set_odatp = alloc_odat(); + + u8_cpy(curr_set_odatp->name, name, 32); + u8_cpy(curr_setp->name, name, 32); + curr_set_odatp->parent_odatp = NULL; + + +} + +/* Inserting a olink instead of a set. Set is really just a placeholder + for another set. Allocate the memory for the set so taht it can be populated*/ +void +insert_set_olink +( int refid +) +{ + struct set* curr_setp; + + curr_setp = curr_set(); + + curr_setp->refid = refid; + +} + +void +insert_set_vlink +( int refid, + uint8_t* anim_name +) +{ + struct cdat* curr_cdatp; + struct odat* curr_odatp; + struct link* curr_linkp; + + + curr_cdatp = curr_cdat(); + curr_odatp = curr_odat(); + curr_linkp = alloc_link(); + + /* Insert vlink into link_stack so that it gets processed at + output time */ + curr_linkp->type = 2; + /* Store the target odat information*/ + curr_linkp->link_t.vlink.refid = refid; + u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32); + /* Store the linking odat/cdat information */ + curr_linkp->classp = curr_cdatp; + curr_linkp->odatp = curr_odatp; + curr_linkp->set_idx = curr_cdatp->num_sets; + // curr_linkp->ele_idx = -1; + +} + +/* Svlinks dont have animation names */ +void +insert_set_svlink +( int refid +) +{ + struct cdat* curr_cdatp; + struct link* curr_linkp; + + curr_cdatp = curr_cdat(); + curr_linkp = alloc_link(); + + /* Insert svlink into link_stack so that it gets processed at + output time */ + curr_linkp->type = 3; + curr_linkp->classp = curr_cdatp; + curr_linkp->set_idx = curr_cdatp->num_sets; + // curr_linkp->ele_idx = -1; + curr_linkp->link_t.svlink.refid = refid; + +} + +/* At the point of reducing to a set, most of the + sets odat information has already been populated + during the reduction of its right hand side + non terminals (hitbox, root, quad_list). */ +void +insert_set +() +{ int refid; + struct odat* curr_odatp; + struct cdat* curr_cdatp; + struct set* curr_setp; + struct ref* prev_refp; + struct ref* curr_refp; + struct vdat* curr_vdatp; + + curr_odatp = curr_set_odatp; //allocated at insert_set_label + curr_cdatp = curr_cdat(); + curr_setp = curr_set(); + prev_refp = curr_ref(); + curr_refp = alloc_ref(); + curr_vdatp = curr_vdat(); + + curr_vdatp->creator = curr_set_odatp; + + curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx? + u8_cpy(curr_setp->name, curr_odatp->name, 32); + curr_cdatp->num_sets++; + + curr_odatp->cdat_idx = curr_cdatp->idx; + curr_odatp->refp = curr_refp; + + refid = curr_setp->refid; // refid set by insert_set_label(name, refid) + + curr_refp->refid = refid; + curr_refp->lastref = prev_refp; + curr_refp->odatp = curr_odatp; + prev_refp->nextref = curr_refp; + + + +} +/* Created as a seperate function, instead of setting the ODATS vdat_id and + calling inc_vdat() inside of insert_set(), to account for the set reduction + where a vdat is not created (o/v/svlinks). */ +void +insert_set_vdatid +() +{ + struct vdat* curr_vdatp; + + curr_vdatp = curr_vdat(); + + curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks + curr_set_odatp->vdatp = curr_vdatp; + curr_set_odatp = NULL; //This sets odat shouldnt be modified after populating odats vdat info +} + +/* Populates the odat name and refid for odat, allocate the odat here for the rest of + the functions to use via curr_odat(). */ +void +insert_ele_label +( uint8_t* name, + int refid +) +{ + struct odat* curr_odatp; + + curr_odatp = alloc_odat(); + + u8_cpy(curr_odatp->name, name, 32); + curr_odatp->map[0] = 0; + + if(refid != -1) + curr_odatp->refid = refid; + else + curr_odatp->refid = ss_refid++; + +} + +/* We don't make an odat here, at output time we will resolve + the refid to the corresponding odat. */ +void +insert_ele_olink +( int refid +) +{ + /* Do nothing because we already know the refid that + the odat needs for this element (in the quad_file) */ +} + +void +insert_ele_vlink +( int refid, + uint8_t* anim_name +) +{ + struct cdat* curr_cdatp; + struct set* curr_setp; + struct link* curr_linkp; + + curr_cdatp = curr_cdat(); + curr_setp = curr_set(); + curr_linkp = alloc_link(); + + /* Insert vlink into link_stack so that it gets processed at + output time */ + curr_linkp->classp = curr_cdatp; + curr_linkp->type = 2; + curr_linkp->set_idx = curr_cdatp->num_sets; + //curr_linkp->ele_idx = curr_setp->num_ele; + curr_linkp->link_t.vlink.refid = refid; + u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32); + +} + +void +insert_ele_svlink +( int refid +) +{ + struct cdat* curr_cdatp; + struct set* curr_setp; + struct link* curr_linkp; + + curr_cdatp = curr_cdat(); + curr_setp = curr_set(); + curr_linkp = alloc_link(); + + curr_linkp->classp = curr_cdatp; + curr_linkp->type = 3; + + //curr_linkp->ele_idx = curr_setp->num_ele; + curr_linkp->link_t.svlink.refid = refid; + + +} + +//Insert element into odat_buf and cdatpages +void +insert_ele() +{ + int refid; + struct cdat* curr_cdatp; + struct odat* curr_odatp; + struct vdat* curr_vdatp; + struct set* curr_setp; + struct ele* curr_elep; + struct ref* curr_refp; + struct ref* prev_refp; + + + curr_odatp = curr_odat(); //malloced @ insert_ele_label + curr_vdatp = curr_vdat(); + curr_setp = curr_set(); + prev_refp = curr_ref(); + curr_refp = alloc_ref(); + + curr_vdatp->creator = curr_odatp; + + /* Populate odat for ele */ + curr_odatp->cdat_idx = curr_cdatp->idx; + curr_odatp->refp = curr_refp; + curr_odatp->parent_odatp = curr_set_odatp; + + refid = curr_odatp->refid; + + curr_refp->refid = refid; + curr_refp->lastref = prev_refp; + curr_refp->odatp = curr_odatp; + prev_refp->nextref = curr_refp; + +} + +void +insert_ele_vdatid +() +{ struct odat* curr_odatp; + curr_odatp = curr_odat(); + curr_odatp->vdat_id = num_vdats; +} + + + +#endif + + + + +/* void */ +/* insert_quad */ +/* ( int x, int y, int z, int refid */ +/* ) */ +/* { */ +/* struct quad* curr_quadp; */ + +/* curr_quadp = curr_quad(); */ + +/* curr_quadp->x = x; */ +/* curr_quadp->y = y; */ +/* curr_quadp->z = z; */ +/* curr_quadp->refid = refid; */ + + + +/* } */ + +/* /\* serting the hitbox into the set */ +/* odat. Elements that don't have */ +/* a hitbox will use the sets root. *\/ */ +/* void */ +/* insert_hitbox */ +/* ( int hitbox */ +/* ) */ +/* { struct odat* curr_odatp; */ + +/* curr_odatp = curr_odat(); */ +/* curr_odatp->hitbox = hitbox; */ +/* } */ + +/* /\* Inserting the root into the set */ +/* odat. Elements that don't have */ +/* a root will use the sets root. *\/ */ +/* void */ +/* insert_root */ +/* ( int x, */ +/* int y, */ +/* int z */ +/* ) */ +/* { struct odat* curr_odatp; */ + +/* curr_odatp = curr_odat(); */ +/* curr_odatp->root.x = x; */ +/* curr_odatp->root.y = y; */ +/* curr_odatp->root.z = z; */ +/* } */ + + + + +/* void */ +/* insert_frame_pointer */ +/* ( uint8_t direction, */ +/* void* frame */ +/* ) */ +/* { struct model* curr_modelp; */ + +/* curr_modelp = curr_model(); */ + +/* curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame; */ +/* } */ + diff --git a/ir.h b/ir.h new file mode 100755 index 0000000..0d271b1 --- /dev/null +++ b/ir.h @@ -0,0 +1,16 @@ + + +/*!@file +\brief Intermediate Representation (IR) between Directory Structure and Engine Input +\details The IR serves as a storage structure that is populated during the + parsing of the input directory structure. After parsing is complete, + the IR will be condensed (removed of excess allocated space) and then + output as the input for the engine. In this file we describe the semantic actions + that are called at each step, and the memory buffers that they populate. + See parser.y for the description on how the input grammar is constructed, + and where/when semantic actions are called. + TODO: or just write it here. +\author Jordan Lavatai +\date Aug 2016 +----------------------------------------------------------------------------*/ + diff --git a/lexer.c b/lexer.c new file mode 100644 index 0000000..1550db9 --- /dev/null +++ b/lexer.c @@ -0,0 +1,518 @@ +/*!@file + \brief lexical analyzer implementation for APC + \details The lexer manages two FIFO stacks. One for maintaining tokens, the + other for maintaining a list of files to be scanned. During + execution, the lexer will return a token from its token queue if any + are present. If not, the lexer will will pop an element from its + file queue to 'scanner' to be tokenized. If the file queue is empty, + the lexer will instead call 'parsedir' to traverse the directory tree + and tokenize the results. If 'parsedir' does not generate any new + tokens, we are done. + \author Jordan Lavatai + \date Aug 2016 + ----------------------------------------------------------------------------*/ +/* Standard */ +#include +#include +#include +#include +/* Posix */ +#include +#include +#include +#include +#include +#include +#include +#include //realpath, NAME_MAX, FPATH_MAX +#include + +/* Local */ +#include "parser.tab.h" +#ifndef DE_STACKSIZE +#define DE_STACKSIZE 1024 +#endif +#ifndef TK_STACKSIZE +#define TK_STACKSIZE 1024 +#endif + + +/* Public */ +int lexer_init(void); +int lexer(void); +int lexer_lexfile(const uint8_t*); +void lexer_pushtok(int, YYSTYPE); +uint8_t const* lexer_get_current_filepath(void); +int lexer_lexfilename(uint8_t*); +struct dirent* lexer_direntpa[DE_STACKSIZE],** lexer_direntpp,** lexer_direntpb; +/* Private */ +extern //lexer_fsm.rl +int lexer_lexstring(uint8_t*, int); +extern //lexer_fsm.rl +int lexer_setstr(uint8_t*, int); +extern //scanner.c +int scanner_init(void); +extern //scanner.c +int scanner(void); +static inline +int dredge_current_depth(void); +extern //bison +YYSTYPE yylval; +static +uint8_t const* current_filename; + +static +struct tok +{ YYSTYPE lval; //token val + int tok_t; //token type +} token_stack[TK_STACKSIZE], *tsp, *tsx; + +/* Directory Entity Array/Stack + Simple array for keeping track of dirents yet to be processed by the scanner. + If this list is empty and there are no tokens, the lexer is done. + This array is populated by the scanner as an array, and popped locally by the + lexer as a stack, and is popped as a FIFO stack. +*/ +#define DE_STACK (lexer_direntpa) +#define DE_STACKP (lexer_direntpp) +#define DE_STACKB (lexer_direntpb) +#define DE_LEN() (DE_STACKP - DE_STACKB) +#define DE_INIT() (DE_STACKP = DE_STACKB = DE_STACK) +#define DE_POP() (*DE_STACKB++) + +/* Token Stack + This is a FIFO stack whose pointers are a union of either a pointer to an + integer, or a pointer to two integers (a struct tok). This way, integers may + be added or removed from the stack either singularly (IPUSH/IPOP), or as a + full token of two integers (PUSH/POP). + An alignment error will occur if IPOP or IPUSH are used a non-even number of + times in a sequence! +*/ +#define TK_STACK (token_stack) +#define TK_STACKP (tsp) +#define TK_STACKX (tsx) +#define TK_LEN() (TK_STACKX - TK_STACKP) +#define TK_INIT() (TK_STACKP = TK_STACKX = TK_STACK) +#define TK_POP() (*TK_STACKP++) +#define TK_PUSH(T,L) (*TK_STACKX++ = (struct tok){L,T}) + +/* Initializer + The initializer returns boolean true if an error occurs, which may be handled + with standard errno. +*/ +int lexer_init +() +{ TK_INIT(); + DE_INIT(); + return scanner_init(); +} + +/* Lexer + If the token buffer is empty, 'lexer' will initialize the token buffer and + call 'lexer_scandir'. If SCAN_ERROR is returned, an error is printed + before sending a null return to bison. If 0 tokens are generated, the error + printing is skipped. In all other cases, 'yylval' is set, and the token's + integer representation is returned. +*/ +int lexer +#define $($)#$ +#define SCAN_ERROR -1 +#define TK_EMPTY (TK_STACKP == TK_STACKX) +#define FAIL(...) \ + do { \ + fprintf(stderr,__VA_ARGS__); \ + goto done; \ + } while (0) +() +{ struct tok token; + start: + while (DE_LEN() > 0)//lex any directory entries in our stack + { + if (lexer_lexfile(DE_POP()->d_name) == 0) + FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKB)->d_name); + } + if (TK_EMPTY) //if there are no tokens, + { TK_INIT(); //initialize the token stack back to 0 + switch (scanner()) + { case SCAN_ERROR: //if an error occurred, + FAIL("Scanner error\n"); + case 0: //if the the scanner finds no dirents, + goto done; //then we are done + default: //if we found some elements to scan, + goto start; //start over and lex them + } + } + token = TK_POP(); + yylval = token.lval; + return token.tok_t; + done: + yylval.val = 0; + return 0; +} + + +/* Token Receiver + This receiver takes a struct tok and pushes it to the FIFO stack. +*/ +void lexer_pushtok +#define $($)#$ //stringifier +#define ERR_TK "Fatal: Generated over " $(TK_STACKSIZE) " tokens in one pass." +( int tok, YYSTYPE lval ) +{ if (TK_LEN() >= TK_STACKSIZE) + { fprintf(stderr, ERR_TK); + exit(EXIT_FAILURE); + } + TK_PUSH(tok, lval); +} + +/* Lexical analysis of a file + Strips a filename to its base name, then sends it to lexer_lex +*/ +int lexer_lexfile +#define HIDDEN_WARNING "%s is hidden and will not be parsed!\n", filename +( const uint8_t *filename +) +{ static uint8_t fname[FNAME_MAX]; + uint8_t *last_period = NULL, *iter; + + if (*filename == '.') + { fprintf (stderr, HIDDEN_WARNING); + return 0; + } + /* Copy the filename and remove its suffix */ + u8_strncpy(fname,filename,FNAME_MAX); + last_period = NULL; + for (iter = fname; *iter; iter++) //find the last '.' char + if (*iter == '.') + last_period = iter; + if (last_period) //if we found one, + *last_period = 0; //truncate the string there + /* Register the current_filename */ + current_filename = filename; + printf("lexer_lexfilename(%s)\n",fname); + return lexer_lexfilename(fname); +} + +uint8_t const* lexer_get_current_filepath +() +{ static uint8_t current_path[FPATH_MAX]; + static uint8_t const* last_filename; + if ((!last_filename || last_filename != current_filename) && + ((uint8_t*) realpath(current_filename, current_path) != (uint8_t*) current_path)) + { perror("realpath: "); + return NULL; + } + return (const uint8_t*)current_path; +} + +/* Scan filename and push the its tokens + onto the stack */ +int lexer_lexfilename +(uint8_t* str) +{ int ntok, len; + uint8_t *filepath; + + + printf("|---- Begin lexerfilename on %s ----|\n", str); + + if(*str == 0) + perror("Lexfilename:: str is NULL so fail\n"); + + /* Determine the filetype of str */ + len = u8_strlen(str); + + ntok += lexer_lexstring(str, len); + + /* Pass back filepath as end of statment operator */ + filepath = u8_strdup(lexer_get_current_filepath()); + yylval.str = filepath; + lexer_pushtok(NAME, yylval); + printf("Pushing filepath %s\n", filepath); + ntok++; + + printf("|---- Ending lexer_lexfilename on %s, %d tokens were lexed ----|\n", str, ntok); + return ntok; +} + +/**************************/ +/****Abandon All Hope******/ +/**************************/ +/*** ***/ +/*** ***/ +/*** ***/ +/*** ***/ + +#if 0 +int +lexer_lexelemap +( uint8_t* str) +{ int setname_len, elename_len, strlen; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + SET_CURR_ELENAME(newstrt); + if(PREV_MAPFILE()) + { printf("Lexer_lexelemap:: previous file was mapfile*\n"); + SET_MAPSTR(newstrt); + } + else + { + if(SETNAME_MATCHES()) + { DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + printf("Lexer_lexelemap:: setname matches\n"); + if(ELENAME_MATCHES()) + DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + } + } + + UPDATE_PREV_ELENAME(newstrt); + UPDATE_PREV_SETNAME(newstrt); + + return newstrt - str; + + +} + +int +lexer_lexelemodel +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + printf("Lexer_lexelemodel:: Begin str is %s\n", str); + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + SET_CURR_ELENAME(newstrt); + if(SETNAME_MATCHES()) + { printf("Lexer_lexelemodel:: curr_setname(%s) matches prev_setname (%s)\n", curr_setname, prev_setname); + DEL_FTOK(newstrt); + printf("Lexer_lexelemodel:: Deleted setname, newstrt is now %s\n", newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + if(ELENAME_MATCHES()) + { printf("Lexer_lexelemodel:: elename matches\n"); + DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + } + } + UPDATE_PREV_ELENAME(newstrt); + UPDATE_PREV_SETNAME(newstrt); + + return newstrt - str; +} + +int +lexer_lexsetmap +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + if(PREV_MAPFILE()) + SET_MAPSTR(newstrt); + else + if( SETNAME_MATCHES()) + DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + + UPDATE_PREV_SETNAME(newstrt); + + return newstrt - str; +} + +int +lexer_lexsetmodel +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + if( SETNAME_MATCHES()) + DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + UPDATE_PREV_SETNAME(newstrt); + + return newstrt - str; + +} + +int +lexer_lexsetvlink +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + if( SETNAME_MATCHES()) + DEL_FTOK(newstrt); + if(REF((NEXT_TOK(newstrt)))) //if NAME REF REF + DEL_FTOK(newstrt); + UPDATE_PREV_SETNAME(newstrt); + + return newstrt - str; + +} + +int +lexer_lexelevlink +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + SET_CURR_ELENAME(newstrt); + if(SETNAME_MATCHES()) + { DEL_FTOK(newstrt); + if(REF(NEXT_TOK(newstrt))) //NAME REF REF, where is set_label + DEL_FTOK(newstrt); + } + + return newstrt - str; +} + +int +lexer_lexsetolink +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + return 0; + + //do nothing +} + +int +lexer_lexeleolink +(uint8_t* str) +{ int setname_len, elename_len; + uint8_t* setname_end, *elename_end, *newstrt; + uint8_t curr_setname[MAX_SETNAME_LEN] = {0}; + uint8_t curr_elename[MAX_ELENAME_LEN] = {0}; + + newstrt = str; + + SET_CURR_SETNAME(newstrt); + printf("prev_setname %s, curr_setname %s\n", prev_setname, curr_setname); + if(SETNAME_MATCHES()) + { DEL_FTOK(newstrt); + if(REF(newstrt)) + DEL_FTOK(newstrt); + } + + return newstrt - str; + + +} + + + +#define REF(STR) (STR[0] <= 0x39 && STR[0] >= 0x30) +#define DEL_FTOK(STR) (STR = u8_strchr(STR, '_') + 1) +#define NEXT_TOK(STR) (u8_strchr(STR, '_') + 1) +#define SET_CURR_SETNAME(STR) \ + do { \ + printf("Lexer_lexX:: setting curr_setname of str(%s)\n", STR); \ + setname_end = u8_chr(STR, FNAME_MAX, '_'); \ + setname_len = setname_end - str; \ + u8_move(curr_setname, STR, setname_len); \ + printf("Lexer_lexX:: curr_setname is now %s\n",curr_setname); \ + } while (0) +#define SET_CURR_ELENAME(STR) \ + do { \ + printf("Lexer_lexX:: setting curr_elename of str(%s)\n", STR); \ + setname_end = u8_chr(STR, FNAME_MAX, '_') + 1; \ + if(REF(setname_end)) \ + setname_end = u8_chr(setname_end, FNAME_MAX, '_') + 1; \ + elename_end = u8_chr(setname_end, FNAME_MAX, '_'); \ + elename_len = elename_end - setname_end; \ + u8_move(curr_elename, setname_end, elename_len); \ + printf("Lexer_lexX:: curr_elename is now %s\n", curr_elename); \ + } while (0) + +#define SETNAME_MATCHES() (u8_strcmp(curr_setname, prev_setname) == 0) +#define ELENAME_MATCHES() (u8_strcmp(curr_elename, prev_elename) == 0) +#define UPDATE_PREV_SETNAME(STR) \ + do { \ + printf("Lexer_lexX:: updating prev_setname from (%s)", prev_setname); \ + u8_set(prev_setname , (ucs4_t) 0, MAX_SETNAME_LEN ); \ + u8_move(prev_setname, curr_setname, setname_len); \ + printf(" to %s\n", prev_setname); \ + } while (0) +#define UPDATE_PREV_ELENAME(STR) \ + do { \ + u8_set(prev_elename , (ucs4_t) 0, MAX_ELENAME_LEN ); \ + u8_move(prev_elename, curr_elename, elename_len); \ + } while (0) +#define PREV_MAPFILE() (TK_STACKX - 5)->tok_t == MOPEN || (TK_STACKX-3)->tok_t == MOPEN +#define SET_MAPSTR(STR) (STR = u8_strstr(STR, map_key)) + + +#endif + + +/* int lexer_lexmapfile */ +/* #define INC_X() */ +/* (int height, int width) */ +/* { */ +/* int x, y; */ + +/* /\* Give scanner_scanpixels a buffer and a len. Iterate through */ +/* buf with buf[n]. If n == 0, do nothing. if n has a value, push x, */ +/* push y, push (z = n << 24), push (ref_id = n >> 8) *\/ */ +/* //scanner_scanpixels() */ + +/* for(i = 0; i < len; i++) */ +/* if(buf[i] == 0) */ +/* if(x == width) */ +/* x = 0; */ +/* else */ + + + + +/* } */ +/* fname_bytes = (uint8_t*)(DE_POP()->d_name); */ + /* printf("d_name is %s\n", fname_bytes); */ + /* for (fnp = filename, i = 0; i < FNAME_MAX; i += unit_size, fnp++) */ + /* { unit_size = u8_mblen(fname_bytes + i, min(4, FNAME_MAX - i)); */ + /* if (u8_mbtouc(fnp, fname_bytes + i, unit_size) == -1) //add ucs4 char to the filename */ + /* FAIL("Lexer failed to convert ^%s to unicode\n", (fname_bytes + i)); */ + /* if (*fnp == 0) //added a terminating char */ + /* break; */ + /* } */ + /* if(u8_mbtouc(filename, DE_POP()->d_name, FNAME_MAXy) == -1) */ + /* FAIL("Lexer failed to convert d_name into uint8_t\n"); */ + /* ulc_fprintf(stdout, "filename is %11U\n c", filename); */ diff --git a/lexer_fsm.c b/lexer_fsm.c new file mode 100644 index 0000000..1ae11bb --- /dev/null +++ b/lexer_fsm.c @@ -0,0 +1,1038 @@ + +#line 1 "lexer_fsm.rl" +#include +#include +#include +#include +#include + +extern void lexer_pushtok(int, YYSTYPE); +extern int lexer_lexmapfile(int, int); +extern int ipower(int, int); +extern int ttov(uint8_t*, int); +extern uint8_t* ttos(const uint8_t*, int); + +int lexer_setdirection(uint8_t*, int); +int lexer_lexstring(uint8_t*, int); +int lexer_setstr(uint8_t*, int); + +#define $($)#$ +#define PUSHTOK(TOK,LFUNC,UTYPE) \ + do { \ + printf("Lexer_lexstring:: PUSHTOK(" $(TOK) $(LFUNC) $(UTYPE) ")\n"); \ + tok_t = TOK; \ + yylval.UTYPE = LFUNC(ts, p-ts); \ + lexer_pushtok(tok_t, yylval); \ + ++ntok; \ + } while (0); + + +#line 31 "lexer_fsm.c" +static const char _lexstring_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 1, + 3, 1, 4, 1, 5, 1, 13, 1, + 14, 1, 15, 2, 0, 14, 2, 2, + 6, 2, 2, 7, 2, 2, 8, 2, + 2, 9, 2, 2, 10, 2, 2, 11, + 2, 2, 12 +}; + +static const short _lexstring_key_offsets[] = { + 0, 0, 12, 17, 22, 24, 28, 34, + 40, 48, 54, 63, 69, 75, 76, 82, + 83, 89, 95, 103, 111, 123, 135, 147, + 159, 171, 183, 195, 207, 219, 231, 243, + 255, 267, 279 +}; + +static const char _lexstring_trans_keys[] = { + 48, 69, 78, 83, 87, 126, 49, 57, + 65, 90, 97, 122, 0, 95, 120, 48, + 57, 0, 95, 120, 48, 57, 48, 57, + 0, 95, 48, 57, 0, 95, 65, 90, + 97, 122, 0, 95, 65, 90, 97, 122, + 0, 69, 87, 95, 65, 90, 97, 122, + 0, 95, 65, 90, 97, 122, 0, 69, + 83, 87, 95, 65, 90, 97, 122, 0, + 95, 65, 90, 97, 122, 0, 95, 65, + 90, 97, 122, 95, 35, 95, 65, 90, + 97, 122, 95, 0, 95, 65, 90, 97, + 122, 48, 57, 65, 90, 97, 122, 0, + 95, 48, 57, 65, 90, 97, 122, 0, + 95, 48, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 48, 69, 78, 83, 87, + 126, 49, 57, 65, 90, 97, 122, 48, + 69, 78, 83, 87, 126, 49, 57, 65, + 90, 97, 122, 0 +}; + +static const char _lexstring_single_lengths[] = { + 0, 6, 3, 3, 0, 2, 2, 2, + 4, 2, 5, 2, 2, 1, 2, 1, + 2, 0, 2, 2, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6 +}; + +static const char _lexstring_range_lengths[] = { + 0, 3, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 0, 2, 0, + 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3 +}; + +static const short _lexstring_index_offsets[] = { + 0, 0, 10, 15, 20, 22, 26, 31, + 36, 43, 48, 56, 61, 66, 68, 73, + 75, 80, 84, 90, 96, 106, 116, 126, + 136, 146, 156, 166, 176, 186, 196, 206, + 216, 226, 236 +}; + +static const char _lexstring_indicies[] = { + 0, 4, 5, 6, 7, 8, 2, 3, + 3, 1, 9, 9, 11, 10, 1, 9, + 9, 12, 10, 1, 13, 1, 14, 14, + 15, 1, 16, 16, 17, 17, 1, 16, + 18, 17, 17, 1, 16, 19, 19, 20, + 17, 17, 1, 16, 21, 17, 17, 1, + 16, 22, 23, 24, 25, 17, 17, 1, + 16, 26, 17, 17, 1, 16, 27, 17, + 17, 1, 28, 1, 29, 30, 17, 17, + 1, 31, 1, 16, 32, 17, 17, 1, + 33, 34, 34, 1, 35, 35, 36, 34, + 34, 1, 37, 37, 34, 34, 34, 1, + 0, 4, 5, 6, 7, 8, 2, 3, + 3, 1, 0, 4, 5, 6, 7, 8, + 2, 3, 3, 1, 0, 4, 5, 6, + 7, 8, 2, 3, 3, 1, 0, 4, + 5, 6, 7, 8, 2, 3, 3, 1, + 0, 4, 5, 6, 7, 8, 2, 3, + 3, 1, 0, 4, 5, 6, 7, 8, + 2, 3, 3, 1, 0, 4, 5, 6, + 7, 8, 2, 3, 3, 1, 0, 4, + 5, 6, 7, 8, 2, 3, 3, 1, + 0, 4, 5, 6, 7, 8, 2, 3, + 3, 1, 0, 4, 5, 6, 7, 8, + 2, 3, 3, 1, 0, 4, 5, 6, + 7, 8, 2, 3, 3, 1, 0, 4, + 5, 6, 7, 8, 2, 3, 3, 1, + 0, 4, 5, 6, 7, 8, 2, 3, + 3, 1, 0, 4, 5, 6, 7, 8, + 2, 3, 3, 1, 0, 4, 5, 6, + 7, 8, 2, 3, 3, 1, 0 +}; + +static const char _lexstring_trans_targs[] = { + 2, 0, 3, 6, 7, 8, 10, 12, + 13, 20, 3, 17, 4, 5, 21, 5, + 22, 6, 23, 9, 32, 24, 11, 14, + 16, 31, 25, 26, 27, 15, 29, 28, + 30, 18, 19, 33, 18, 34 +}; + +static const char _lexstring_trans_actions[] = { + 9, 0, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 13, 13, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 0, + 0, 9, 0, 0, 0, 0 +}; + +static const char _lexstring_to_state_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 3, 15, 5, 37, + 31, 40, 28, 7, 0, 11, 25, 22, + 34, 19, 1 +}; + +static const int lexstring_start = 1; +static const int lexstring_first_final = 20; +static const int lexstring_error = 0; + +static const int lexstring_en_tok_lexer = 1; + + +#line 114 "lexer_fsm.rl" + + +int +lexer_lexstring +(uint8_t* str, int size) +{ uint8_t *p; + uint8_t *ts, *pe, *eof; + int cs, ntok, tok_t, direction; + + ntok = direction = 0; + p = ts = str; + pe = p + size +1; + + printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe); + + +#line 195 "lexer_fsm.c" + { + cs = lexstring_start; + } + +#line 130 "lexer_fsm.rl" + +#line 202 "lexer_fsm.c" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _lexstring_trans_keys + _lexstring_key_offsets[cs]; + _trans = _lexstring_index_offsets[cs]; + + _klen = _lexstring_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _lexstring_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + _trans = _lexstring_indicies[_trans]; + cs = _lexstring_trans_targs[_trans]; + + if ( _lexstring_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _lexstring_actions + _lexstring_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 4: +#line 41 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p); ts = p; } + break; + case 5: +#line 42 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p); + yylval.str = (uint8_t*) "SS"; + lexer_pushtok(SS, yylval); + ntok++; + } + break; + case 13: +#line 79 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_height p = %s\n", p); + PUSHTOK(HEIGHT, ttov, val); + } + break; +#line 294 "lexer_fsm.c" + } + } + +_again: + _acts = _lexstring_actions + _lexstring_to_state_actions[cs]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: +#line 31 "lexer_fsm.rl" + { PUSHTOK(REF, ttov, ref); } + break; + case 1: +#line 32 "lexer_fsm.rl" + { PUSHTOK(NUM, ttov, val); } + break; + case 2: +#line 33 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p); + PUSHTOK(NAME, ttos, str); + } + break; + case 3: +#line 36 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_map: pushing '~'\n"); + yylval.str = (uint8_t*) '~'; + lexer_pushtok(MOPEN, yylval); + ntok++; + } + break; + case 5: +#line 42 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p); + yylval.str = (uint8_t*) "SS"; + lexer_pushtok(SS, yylval); + ntok++; + } + break; + case 6: +#line 47 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_S. p = %s\n", p); + yylval.val = 0; + lexer_pushtok(D, yylval); + } + break; + case 7: +#line 51 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_SW. p = %s\n", p); + yylval.val = 1; + lexer_pushtok(D, yylval); + } + break; + case 8: +#line 55 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_W. p = %s\n", p); + yylval.val = 2; + lexer_pushtok(D, yylval); + } + break; + case 9: +#line 59 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_NW. p = %s\n", p); + yylval.val = 3; + lexer_pushtok(D, yylval); + } + break; + case 10: +#line 63 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 4; + lexer_pushtok(D, yylval); + } + break; + case 11: +#line 71 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 6; + lexer_pushtok(D, yylval); + } + break; + case 12: +#line 75 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 7; + lexer_pushtok(D, yylval); + } + break; + case 14: +#line 82 "lexer_fsm.rl" + { printf("Lexer_lexstring:: action:push_height p = %s\n", p); + PUSHTOK(WIDTH, ttov, val); + } + break; + case 15: +#line 85 "lexer_fsm.rl" + {yylval.str = (uint8_t*) '#'; lexer_pushtok(LINK),yylval); } + break; +#line 392 "lexer_fsm.c" + } + } + + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +#line 131 "lexer_fsm.rl" + + printf("Ending lexstring of file %s, pushed %d tokens.\n",str, ntok); + + return ntok; +} + + + +#line 413 "lexer_fsm.c" +static const char _setdirection_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 1, + 3, 1, 4, 1, 5, 1, 6, 1, + 7 +}; + +static const char _setdirection_key_offsets[] = { + 0, 0, 6, 8, 12, 14, 16, 20, + 22, 24, 26, 26, 26, 26, 26, 26, + 26, 26 +}; + +static const char _setdirection_trans_keys[] = { + 0, 69, 78, 83, 87, 95, 0, 95, + 0, 69, 87, 95, 0, 95, 0, 95, + 0, 69, 87, 95, 0, 95, 0, 95, + 0, 95, 0 +}; + +static const char _setdirection_single_lengths[] = { + 0, 6, 2, 4, 2, 2, 4, 2, + 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0 +}; + +static const char _setdirection_range_lengths[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 +}; + +static const char _setdirection_index_offsets[] = { + 0, 0, 7, 10, 15, 18, 21, 26, + 29, 32, 35, 36, 37, 38, 39, 40, + 41, 42 +}; + +static const char _setdirection_indicies[] = { + 0, 2, 3, 4, 5, 0, 1, 6, + 6, 1, 7, 8, 9, 7, 1, 10, + 10, 1, 11, 11, 1, 0, 12, 13, + 0, 1, 14, 14, 1, 15, 15, 1, + 16, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0 +}; + +static const char _setdirection_trans_targs[] = { + 10, 0, 2, 3, 6, 9, 11, 12, + 4, 5, 13, 14, 7, 8, 15, 16, + 17 +}; + +static const char _setdirection_trans_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0 +}; + +static const char _setdirection_to_state_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 5, 1, 9, 11, 13, + 15, 3 +}; + +static const int setdirection_start = 1; +static const int setdirection_first_final = 10; +static const int setdirection_error = 0; + +static const int setdirection_en_main = 1; + + +#line 166 "lexer_fsm.rl" + + +int +lexer_setdirection +(uint8_t* str, int size) +{ uint8_t *p, *pe, *eof; + int cs; + + + p = str; + pe = str + size + 1; + + printf("|--- Begin lexer_setdirection str = %s, p = %s, pe = %s ---|\n", str,p, pe); + + +#line 501 "lexer_fsm.c" + { + cs = setdirection_start; + } + +#line 181 "lexer_fsm.rl" + +#line 508 "lexer_fsm.c" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( cs == 0 ) + goto _out; +_resume: + _keys = _setdirection_trans_keys + _setdirection_key_offsets[cs]; + _trans = _setdirection_index_offsets[cs]; + + _klen = _setdirection_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _setdirection_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + _trans = _setdirection_indicies[_trans]; + cs = _setdirection_trans_targs[_trans]; + + _acts = _setdirection_actions + _setdirection_to_state_actions[cs]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: +#line 141 "lexer_fsm.rl" + {printf("Lexer_setdirection:: direction is north, returning 4\n"); return 4;; } + break; + case 1: +#line 142 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is west, returning 2\n");return 2;} + break; + case 2: +#line 143 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is east, returning 6\n");return 6;} + break; + case 3: +#line 144 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is south, returning 0\n");return 0;} + break; + case 4: +#line 145 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is northeast, returning 5\n");return 5 ;} + break; + case 5: +#line 146 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is northwest, returning 3\n");return 3;} + break; + case 6: +#line 147 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is southeast, returning 7\n");return 7;} + break; + case 7: +#line 148 "lexer_fsm.rl" + { printf("Lexer_setdirection:: direction is southwest, returning 1\n");return 1;} + break; +#line 607 "lexer_fsm.c" + } + } + + if ( cs == 0 ) + goto _out; + p += 1; + goto _resume; + _out: {} + } + +#line 182 "lexer_fsm.rl" + + printf("|--- Error in: lexer_setdirection ---|\n"); + + return -1; +} + + + +/**************************/ +/****Abandon All Hope******/ +/**************************/ +/*** ***/ +/*** ***/ +/*** ***/ +/*** ***/ + + +#if 0 + +#line 638 "lexer_fsm.c" +static const char _setstr_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 1, + 3, 1, 4, 1, 5, 1, 6, 1, + 7, 1, 8 +}; + +static const unsigned char _setstr_key_offsets[] = { + 0, 0, 6, 7, 13, 20, 25, 33, + 34, 35, 36, 42, 50, 55, 60, 66, + 75, 79, 85, 86, 92, 99, 106, 111, + 115, 116, 117, 118, 124, 132, 137, 142, + 148, 157, 161, 167, 168, 174, 181, 184, + 185, 191, 195, 201, 202, 203, 209, 216, + 222, 231, 235, 241, 241, 241, 241, 241, + 241, 250, 251 +}; + +static const char _setstr_trans_keys[] = { + 48, 83, 65, 90, 97, 122, 120, 48, + 57, 65, 90, 97, 122, 0, 48, 57, + 65, 90, 97, 122, 95, 65, 90, 97, + 122, 35, 48, 83, 126, 65, 90, 97, + 122, 95, 48, 120, 48, 57, 65, 90, + 97, 122, 0, 95, 48, 57, 65, 90, + 97, 122, 83, 65, 90, 97, 122, 0, + 65, 90, 97, 122, 0, 83, 65, 90, + 97, 122, 0, 69, 78, 83, 87, 65, + 90, 97, 122, 65, 90, 97, 122, 69, + 87, 65, 90, 97, 122, 120, 48, 57, + 65, 90, 97, 122, 95, 48, 57, 65, + 90, 97, 122, 35, 83, 126, 65, 90, + 97, 122, 95, 65, 90, 97, 122, 35, + 48, 83, 126, 95, 48, 120, 48, 57, + 65, 90, 97, 122, 0, 95, 48, 57, + 65, 90, 97, 122, 83, 65, 90, 97, + 122, 0, 65, 90, 97, 122, 0, 83, + 65, 90, 97, 122, 0, 69, 78, 83, + 87, 65, 90, 97, 122, 65, 90, 97, + 122, 69, 87, 65, 90, 97, 122, 120, + 48, 57, 65, 90, 97, 122, 95, 48, + 57, 65, 90, 97, 122, 35, 83, 126, + 83, 83, 95, 65, 90, 97, 122, 65, + 90, 97, 122, 69, 87, 65, 90, 97, + 122, 48, 120, 48, 57, 65, 90, 97, + 122, 0, 48, 57, 65, 90, 97, 122, + 83, 95, 65, 90, 97, 122, 69, 78, + 83, 87, 95, 65, 90, 97, 122, 65, + 90, 97, 122, 69, 87, 65, 90, 97, + 122, 69, 78, 83, 87, 95, 65, 90, + 97, 122, 95, 0 +}; + +static const char _setstr_single_lengths[] = { + 0, 2, 1, 0, 1, 1, 4, 1, + 1, 1, 0, 2, 1, 1, 2, 5, + 0, 2, 1, 0, 1, 3, 1, 4, + 1, 1, 1, 0, 2, 1, 1, 2, + 5, 0, 2, 1, 0, 1, 3, 1, + 2, 0, 2, 1, 1, 0, 1, 2, + 5, 0, 2, 0, 0, 0, 0, 0, + 5, 1, 0 +}; + +static const char _setstr_range_lengths[] = { + 0, 2, 0, 3, 3, 2, 2, 0, + 0, 0, 3, 3, 2, 2, 2, 2, + 2, 2, 0, 3, 3, 2, 2, 0, + 0, 0, 0, 3, 3, 2, 2, 2, + 2, 2, 2, 0, 3, 3, 0, 0, + 2, 2, 2, 0, 0, 3, 3, 2, + 2, 2, 2, 0, 0, 0, 0, 0, + 2, 0, 0 +}; + +static const short _setstr_index_offsets[] = { + 0, 0, 5, 7, 11, 16, 20, 27, + 29, 31, 33, 37, 43, 47, 51, 56, + 64, 67, 72, 74, 78, 83, 89, 93, + 98, 100, 102, 104, 108, 114, 118, 122, + 127, 135, 138, 143, 145, 149, 154, 158, + 160, 165, 168, 173, 175, 177, 181, 186, + 191, 199, 202, 207, 208, 209, 210, 211, + 212, 220, 222 +}; + +static const char _setstr_indicies[] = { + 0, 3, 2, 2, 1, 4, 1, 5, + 5, 5, 1, 6, 5, 5, 5, 1, + 7, 2, 2, 1, 8, 9, 11, 12, + 10, 10, 1, 13, 1, 14, 1, 15, + 1, 16, 16, 16, 1, 17, 18, 16, + 16, 16, 1, 20, 19, 19, 1, 17, + 19, 19, 1, 17, 21, 19, 19, 1, + 17, 22, 23, 23, 22, 19, 19, 1, + 19, 19, 1, 22, 22, 19, 19, 1, + 24, 1, 25, 25, 25, 1, 26, 25, + 25, 25, 1, 8, 11, 12, 10, 10, + 1, 27, 10, 10, 1, 28, 29, 30, + 31, 1, 32, 1, 33, 1, 34, 1, + 35, 35, 35, 1, 36, 37, 35, 35, + 35, 1, 39, 38, 38, 1, 36, 38, + 38, 1, 36, 40, 38, 38, 1, 36, + 41, 42, 42, 41, 38, 38, 1, 38, + 38, 1, 41, 41, 38, 38, 1, 43, + 1, 44, 44, 44, 1, 45, 44, 44, + 44, 1, 28, 30, 31, 1, 46, 1, + 47, 27, 10, 10, 1, 10, 10, 1, + 48, 48, 10, 10, 1, 49, 1, 50, + 1, 51, 51, 51, 1, 52, 51, 51, + 51, 1, 53, 7, 2, 2, 1, 54, + 55, 55, 54, 7, 2, 2, 1, 2, + 2, 1, 54, 54, 2, 2, 1, 1, + 1, 1, 1, 1, 48, 56, 56, 48, + 27, 10, 10, 1, 57, 1, 1, 0 +}; + +static const char _setstr_trans_targs[] = { + 2, 0, 5, 47, 3, 4, 51, 6, + 7, 18, 22, 40, 57, 8, 9, 10, + 11, 52, 12, 13, 14, 15, 16, 17, + 19, 20, 21, 23, 24, 35, 39, 55, + 25, 26, 27, 28, 53, 29, 30, 31, + 32, 33, 34, 36, 37, 38, 54, 56, + 41, 44, 45, 46, 58, 48, 49, 50, + 42, 43 +}; + +static const char _setstr_trans_actions[] = { + 17, 0, 17, 17, 17, 17, 0, 0, + 0, 17, 17, 17, 0, 0, 17, 17, + 17, 0, 0, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 17, 0, 0, + 0, 17, 17, 17, 0, 0, 17, 17, + 17, 17, 17, 17, 17, 0, 0, 17, + 17, 17, 17, 17, 0, 17, 17, 17, + 17, 0 +}; + +static const char _setstr_to_state_actions[] = { + 0, 0, 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 3, 9, 11, + 5, 7, 15 +}; + +static const int setstr_start = 1; +static const int setstr_first_final = 51; +static const int setstr_error = 0; + +static const int setstr_en_main = 1; + + +#line 260 "lexer_fsm.rl" + + +int +lexer_setstr +(uint8_t* str, int size) +{ uint8_t *p, *pe, *eof; + int cs, type, newstrt; + + type = newstrt = 0; + + p = str; + pe = str + size + 1; + + printf("|--- Begin lexer_setstr with str = %s, p = %s, pe = %s ---|\n", str,p, pe); + + +#line 812 "lexer_fsm.c" + { + cs = setstr_start; + } + +#line 276 "lexer_fsm.rl" + +#line 819 "lexer_fsm.c" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( cs == 0 ) + goto _out; +_resume: + _keys = _setstr_trans_keys + _setstr_key_offsets[cs]; + _trans = _setstr_index_offsets[cs]; + + _klen = _setstr_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _setstr_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + _trans = _setstr_indicies[_trans]; + cs = _setstr_trans_targs[_trans]; + + if ( _setstr_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _setstr_actions + _setstr_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 8: +#line 212 "lexer_fsm.rl" + {printf("p = %s \n",p);} + break; +#line 895 "lexer_fsm.c" + } + } + +_again: + _acts = _setstr_actions + _setstr_to_state_actions[cs]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: +#line 204 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning setvlink filetype for %s\n", str); type = 5; newstrt = lexer_lexsetvlink(str); {p++; goto _out; }} + break; + case 1: +#line 205 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning elevlink filetype for %s\n", str); type = 6; newstrt = lexer_lexelevlink(str); {p++; goto _out; }} + break; + case 2: +#line 206 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning setmodel filetype\n"); newstrt = lexer_lexsetmodel(str); type = 1; {p++; goto _out; }} + break; + case 3: +#line 207 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning setmap filetype\n"); newstrt = lexer_lexsetmap(str); type = 2; {p++; goto _out; }} + break; + case 4: +#line 208 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning elemodel filetype for %s\n", str); newstrt = lexer_lexelemodel(str); type = 3; {p++; goto _out; }} + break; + case 5: +#line 209 "lexer_fsm.rl" + {printf("Lexer_setstr:: Returning elemap filetype for %s\n", str); newstrt = lexer_lexelemap(str); type = 4; {p++; goto _out; }} + break; + case 6: +#line 210 "lexer_fsm.rl" + { printf("Lexer_setstr:: Returning setolink filetype\n"); type = 8; newstrt = lexer_lexsetolink(str); {p++; goto _out; }} + break; + case 7: +#line 211 "lexer_fsm.rl" + { printf("Lexer_setstr:: Returning eleolink filetype\n"); type = 7; newstrt = lexer_lexeleolink(str); {p++; goto _out; }} + break; +#line 936 "lexer_fsm.c" + } + } + + if ( cs == 0 ) + goto _out; + p += 1; + goto _resume; + _out: {} + } + +#line 277 "lexer_fsm.rl" + + printf("|--- End lexer_setstr. Incrementing str by %d, type is %d ---|\n", newstrt, type); + + return newstrt; +} + +#endif + + +/* %%{ */ +/* machine file_matcher; */ + +/* action call_ml { ts = p; fgoto set_hw ;} */ +/* action call_tl { return 0;} */ +/* action set_height {height = ttov(p, p-ts+1); ts = p;} */ +/* action set_width { width = ttov(p, p-ts+1);} */ +/* action call_lmf {lexer_lexmapfile(height, width); } */ +/* action lex_error {printf("input error: character %c in filename %s is invalid\n = %s\n", fc, str, p);} */ + +/* #This machine determines the type of file we are lexing */ +/* #and calls the appropriate machine to handle it. */ + +/* #TODO add mapping name */ +/* width = digit+ %set_width; */ +/* height = digit+ %set_height; */ + +/* set_hw := height . '_' . width [\0] %to(call_lmf); */ + +/* tok_segment = alnum; */ +/* map_end = 'm' . '_' %to(call_ml); */ +/* tok_end = alnum+ . [\0] %to(call_tl); */ + +/* file_matcher := (tok_segment+ . '_' )+ ( map_end | tok_end ); */ + +/* write data; */ +/* }%% */ + +/* int */ +/* lexer_matchfile */ +/* (char* str, int size) */ +/* { *p, *pe; */ +/* char* ts; */ +/* int cs, ntok, height, width; */ + +/* p = str; */ +/* pe = p + size; */ +/* height = width = 0; */ + +/* printf("Checking if filename is a map file:: filename = %s, p = %c, pe = %c\n", str, *p, *pe); */ + +/* %%write init; */ +/* %%write exec noend; */ + +/* printf("Ending lexer_ismapfile on %s\n", str); */ + +/* return ntok; */ +/* } */ + +/* %%{ */ +/* machine vartype; */ + +/* action isele {return 0;} */ +/* action ismodel {return 1;} */ + +/* set_name = alpha+; */ +/* ele_name = alpha+; */ +/* model_name = alpha+; */ + +/* ele = set_name '_' model_name '_' ele_name %isele; */ +/* model = set_name '_' model_name [\0] %ismodel; */ + + +/* ismodel := (ele | model); */ + +/* write data; */ + +/* }%% */ + +/* int */ +/* lexer_ismodel */ +/* (uint8_t* str, int size) */ +/* { uint8_t *p, *pe, *eof; */ +/* int cs; */ + +/* p = str; */ +/* pe = p + size + 1; */ + +/* %%write init; */ +/* %%write exec; */ + + +/* } */ diff --git a/lexer_fsm.rl b/lexer_fsm.rl new file mode 100644 index 0000000..344ffdb --- /dev/null +++ b/lexer_fsm.rl @@ -0,0 +1,369 @@ +#include +#include +#include +#include "apc.h" +#include +#include + +extern void lexer_pushtok(int, YYSTYPE); +extern int lexer_lexmapfile(int, int); +extern int ipower(int, int); +extern int ttov(uint8_t*, int); +extern struct name* tton(const uint8_t*, int); + +int lexer_setdirection(uint8_t*, int); +int lexer_lexstring(uint8_t*, int); +int lexer_setstr(uint8_t*, int); + +#define $($)#$ +#define PUSHTOK(TOK,LFUNC,UTYPE) \ + do { \ + printf("Lexer_lexstring:: PUSHTOK(" $(TOK) $(LFUNC) $(UTYPE) ")\n"); \ + tok_t = TOK; \ + yylval.UTYPE = LFUNC(ts, p-ts); \ + lexer_pushtok(tok_t, yylval); \ + ++ntok; \ + } while (0); + +%%{ + machine lexstring; + + # set up yylval and tok_t to be pushed to stack + action push_ref { PUSHTOK(REF, ttov, ref); } + action push_val { PUSHTOK(NUM, ttov, val); } + action push_name { printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p); + PUSHTOK(NAME, tton, str); + } + action push_map { printf("Lexer_lexstring:: action:push_map: pushing '~'\n"); + yylval.str = (uint8_t*) '~'; + lexer_pushtok(MOPEN, yylval); + ntok++; + } + action set_ts { printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p); ts = p; } + action push_SS { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p); + yylval.str = (uint8_t*) "SS"; + lexer_pushtok(SS, yylval); + ntok++; + } + action push_S { printf("Lexer_lexstring:: action:push_S. p = %s\n", p); + yylval.val = 0; + lexer_pushtok(D, yylval); + } + action push_SW { printf("Lexer_lexstring:: action:push_SW. p = %s\n", p); + yylval.val = 1; + lexer_pushtok(D, yylval); + } + action push_W { printf("Lexer_lexstring:: action:push_W. p = %s\n", p); + yylval.val = 2; + lexer_pushtok(D, yylval); + } + action push_NW { printf("Lexer_lexstring:: action:push_NW. p = %s\n", p); + yylval.val = 3; + lexer_pushtok(D, yylval); + } + action push_N { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 4; + lexer_pushtok(D, yylval); + } + action push_NE { printf("Lexer_lexstring:: action:push_NE. p = %s\n", p); + yylval.val = 5; + lexer_pushtok(D, yylval); + } + action push_E { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 6; + lexer_pushtok(D, yylval); + } + action push_SE { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); + yylval.val = 7; + lexer_pushtok(D, yylval); + } + action push_height { printf("Lexer_lexstring:: action:push_height p = %s\n", p); + PUSHTOK(HEIGHT, ttov, val); + } + action push_width { printf("Lexer_lexstring:: action:push_height p = %s\n", p); + PUSHTOK(WIDTH, ttov, val); + } + action push_link {yylval.str = (uint8_t*) '#'; lexer_pushtok(LINK),yylval); } + action lex_error { printf("input error: character %c in filename %s is invalid\n p = %s\n", fc, str, p);} + action p { printf("Lexer_lexstring:: p = %s\n", p);} + + # Parses a regular filename (not a mapping) and pushes + # tokens to the parser + N = 'N' %push_N; + W = 'W' %push_W; + S = 'S' %push_S; + E = 'E' %push_E; + NW = 'NW' %push_NW; + NE = 'NE' %push_NW; + SW = 'SW' %push_SW; + SE = 'SE' %push_SE; + + tok_delimiter = [_]; + direction = (N | W | S | E | NW | NE | SW | SE) ; + #make sure 0x123123 doesnt get mistaken for a ref + dimensions = (digit+ - '0') >set_ts %push_height 'x' (digit+ - '0') >set_ts %push_width; + link = '#' %push_link; + SS = ('+SS' %to(push_SS)) | ('+SS' %to(push_SS) link ) ; + ref = '0x' >set_ts alnum+ %push_ref; + val = digit+ >set_ts %push_val ; + name = (lower+ >set_ts) %push_name ; + map = '+MAP' %to(push_map); + tok = name %to(push_name) ; + + +tok_lexer := ((name | val | ref | dimensions | map) tok_delimiter)+ tok [\0]; + + write data; + +}%% + +int +lexer_lexstring +(uint8_t* str, int size) +{ uint8_t *p; + uint8_t *ts, *pe, *eof; + int cs, ntok, tok_t, direction; + + ntok = direction = 0; + p = ts = str; + pe = p + size +1; + + printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe); + + %%write init; + %%write exec ; + + printf("Ending lexstring of file %s, pushed %d tokens.\n",str, ntok); + + return ntok; +} + + +%%{ + machine setdirection; + + action ret_north {printf("Lexer_setdirection:: direction is north, returning 4\n"); return 4;; } + action ret_west { printf("Lexer_setdirection:: direction is west, returning 2\n");return 2;} + action ret_east { printf("Lexer_setdirection:: direction is east, returning 6\n");return 6;} + action ret_south { printf("Lexer_setdirection:: direction is south, returning 0\n");return 0;} + action ret_northeast { printf("Lexer_setdirection:: direction is northeast, returning 5\n");return 5 ;} + action ret_northwest { printf("Lexer_setdirection:: direction is northwest, returning 3\n");return 3;} + action ret_southeast { printf("Lexer_setdirection:: direction is southeast, returning 7\n");return 7;} + action ret_southwest { printf("Lexer_setdirection:: direction is southwest, returning 1\n");return 1;} + + def = [_\0] %to(ret_south); + N = 'N'[_\0] %to(ret_north); + W = 'W' [_\0] %to(ret_west); + S = 'S' [_\0] %to(ret_south); + E = 'E' [_\0] %to(ret_east); + NW = 'NW' [_\0] %to(ret_northwest); + NE = 'NE' [_\0] %to(ret_northeast); + SW = 'SW' [_\0] %to(ret_southwest); + SE = 'SE' [_\0] %to(ret_southeast); + + direction = (N | W | S | E | NW | NE | SW | SE | def); + + main := direction; + + write data; + +}%% + +int +lexer_setdirection +(uint8_t* str, int size) +{ uint8_t *p, *pe, *eof; + int cs; + + + p = str; + pe = str + size + 1; + + printf("|--- Begin lexer_setdirection str = %s, p = %s, pe = %s ---|\n", str,p, pe); + + %%write init; + %%write exec noend; + + printf("|--- Error in: lexer_setdirection ---|\n"); + + return -1; +} + + + +/**************************/ +/****Abandon All Hope******/ +/**************************/ +/*** ***/ +/*** ***/ +/*** ***/ +/*** ***/ + + +#if 0 +%%{ + machine setstr; + + + action lex_setvlink {printf("Lexer_setstr:: Returning setvlink filetype for %s\n", str); type = 5; newstrt = lexer_lexsetvlink(str); fbreak;} + action lex_elevlink {printf("Lexer_setstr:: Returning elevlink filetype for %s\n", str); type = 6; newstrt = lexer_lexelevlink(str); fbreak;} + action lex_setmodel {printf("Lexer_setstr:: Returning setmodel filetype\n"); newstrt = lexer_lexsetmodel(str); type = 1; fbreak;} + action lex_setmap {printf("Lexer_setstr:: Returning setmap filetype\n"); newstrt = lexer_lexsetmap(str); type = 2; fbreak;} + action lex_elemodel {printf("Lexer_setstr:: Returning elemodel filetype for %s\n", str); newstrt = lexer_lexelemodel(str); type = 3; fbreak;} + action lex_elemap {printf("Lexer_setstr:: Returning elemap filetype for %s\n", str); newstrt = lexer_lexelemap(str); type = 4; fbreak;} + action lex_setolink { printf("Lexer_setstr:: Returning setolink filetype\n"); type = 8; newstrt = lexer_lexsetolink(str); fbreak;} + action lex_eleolink { printf("Lexer_setstr:: Returning eleolink filetype\n"); type = 7; newstrt = lexer_lexeleolink(str); fbreak;} + action p {printf("p = %s \n",p);} + action name_error {printf("In %s, there is a syntactic error. Make sure your set/element names dont conflict with the reserved keywords.\n", str);} + + + N = 'N'; + W = 'W'; + S = 'S'; + E = 'E'; + NW = 'NW'; + NE = 'NE'; + SW = 'SW'; + SE = 'SE'; + + SS = 'SS'; + direction = (N | W | S | E | NW | NE | SW | SE) $p; + + SSD = SS direction; + + + + name = alpha+ $p - SSD $p; + num = digit+ $p; + ref = '0x' $p alnum+ $p; + + + set_label = name | (name '_' ref); + ele_label = name | (name '_' ref); + + model_types = (name) | (name '_' num '_' num) | (name '_' num); + + + set_model = set_label '_' SS %to(lex_setmodel); + set_map = set_label '_' '~' %to(lex_setmap); + ele_model = set_label '_' ele_label '_' SS %to(lex_elemodel); + ele_map = set_label '_' ele_label '_' '~' %to(lex_elemap); + set_olink = ref %to(lex_setolink) [\0] ; + ele_olink = set_label '_' '~' '_' ref [\0] %to(lex_eleolink); + set_vlink = set_label '_' '#' '_' (ref | ref '_' name) [\0] %to(lex_setvlink); + ele_vlink = set_label '_' ele_label '_' '#' '_' (ref | ref '_' name) [\0] %to(lex_elevlink); + + main := (ele_map | set_model | set_map |ele_model | ele_vlink | set_vlink | set_olink | ele_olink); + + write data; + + +}%% + +int +lexer_setstr +(uint8_t* str, int size) +{ uint8_t *p, *pe, *eof; + int cs, type, newstrt; + + type = newstrt = 0; + + p = str; + pe = str + size + 1; + + printf("|--- Begin lexer_setstr with str = %s, p = %s, pe = %s ---|\n", str,p, pe); + + %%write init; + %%write exec noend; + + printf("|--- End lexer_setstr. Incrementing str by %d, type is %d ---|\n", newstrt, type); + + return newstrt; +} + +#endif + + +/* %%{ */ +/* machine file_matcher; */ + +/* action call_ml { ts = p; fgoto set_hw ;} */ +/* action call_tl { return 0;} */ +/* action set_height {height = ttov(p, p-ts+1); ts = p;} */ +/* action set_width { width = ttov(p, p-ts+1);} */ +/* action call_lmf {lexer_lexmapfile(height, width); } */ +/* action lex_error {printf("input error: character %c in filename %s is invalid\n = %s\n", fc, str, p);} */ + +/* #This machine determines the type of file we are lexing */ +/* #and calls the appropriate machine to handle it. */ + +/* #TODO add mapping name */ +/* width = digit+ %set_width; */ +/* height = digit+ %set_height; */ + +/* set_hw := height . '_' . width [\0] %to(call_lmf); */ + +/* tok_segment = alnum; */ +/* map_end = 'm' . '_' %to(call_ml); */ +/* tok_end = alnum+ . [\0] %to(call_tl); */ + +/* file_matcher := (tok_segment+ . '_' )+ ( map_end | tok_end ); */ + +/* write data; */ +/* }%% */ + +/* int */ +/* lexer_matchfile */ +/* (char* str, int size) */ +/* { *p, *pe; */ +/* char* ts; */ +/* int cs, ntok, height, width; */ + +/* p = str; */ +/* pe = p + size; */ +/* height = width = 0; */ + +/* printf("Checking if filename is a map file:: filename = %s, p = %c, pe = %c\n", str, *p, *pe); */ + +/* %%write init; */ +/* %%write exec noend; */ + +/* printf("Ending lexer_ismapfile on %s\n", str); */ + +/* return ntok; */ +/* } */ + +/* %%{ */ +/* machine vartype; */ + +/* action isele {return 0;} */ +/* action ismodel {return 1;} */ + +/* set_name = alpha+; */ +/* ele_name = alpha+; */ +/* model_name = alpha+; */ + +/* ele = set_name '_' model_name '_' ele_name %isele; */ +/* model = set_name '_' model_name [\0] %ismodel; */ + + +/* ismodel := (ele | model); */ + +/* write data; */ + +/* }%% */ + +/* int */ +/* lexer_ismodel */ +/* (uint8_t* str, int size) */ +/* { uint8_t *p, *pe, *eof; */ +/* int cs; */ + +/* p = str; */ +/* pe = p + size + 1; */ + +/* %%write init; */ +/* %%write exec; */ + + +/* } */ diff --git a/lexer_lex.rl b/lexer_lex.rl new file mode 100755 index 0000000..5e395d0 --- /dev/null +++ b/lexer_lex.rl @@ -0,0 +1,69 @@ +/* Ragel State Machine for tokenizing text */ +#include +#include +#include +#include + + +int ipow(int, int); +int ttov(const uint8_t* , int); +uint64_t ttor(const uint8_t* , int); +struct name* tton(const uint8_t* , int); + + +#define MAX_TOK_LEN 64 +#define MAX_TOKENS 16 +#define MAX_STR_SIZE (MAX_TOK_LEN * MAX_TOKENS) + +int ipow(int base, int exp) +{ + int result = 1; + while (exp) + { + if (exp & 1) + result = result * base; + exp = exp >> 1; + base *= base; + } + + return result; +} + +/* Token to Value */ +int ttov(const uint8_t* str, int len) +{ + int i, val = 0; + + for (i = 0; i < len; i++) + { + val += ((str[len - (i + 1)] - '0') * ipow(10,i)); + } + + return val; +} + +uint64_t ttor(const uint8_t* str, int len) +{ + int i; + uint64_t num = 0; + + for (i = 0; i < len; i++) + { + num += ((str[len - (i + 1)] - '0') * ipow(10,i)); + } + + return num; +} + +struct name* tton(const uint8_t* str, int len) +{ + int i; + struct name* namep; + + namep = (name*) malloc(MAX_NAME_LEN); + for(i = 0; i < MAX_NAME_LEN - 1; i++) + namep[i] = str[i]; + namep[i] = '\0'; + + return namep; +} diff --git a/main.o b/main.o new file mode 100644 index 0000000..db32a98 Binary files /dev/null and b/main.o differ diff --git a/name.c b/name.c new file mode 100644 index 0000000..612426c --- /dev/null +++ b/name.c @@ -0,0 +1,41 @@ +/* Functions for operating on names */ +#include "apc.h" +#include + + +int +name_u8_cpy(struct name*, struct name*); + +int +name_u8_cmp(struct name*, struct name*); + + +/* Copies src into dst. 1 if sucessful, 0 if not */ +int +name_u8_cpy +( struct name* dst, + struct name* src +) +{ if(u8_stpncpy(dst->name, src->name, MAX_NAME_LEN)) + return 1; + + return 0; + +} + + +int +name_u8_cmp +( struct name* x, + struct name* y +) +{ return u8_strncmp(x->name, y->name, MAX_NAME_LEN); +} + +int +name_u8_set +( struct name* name, + ucs4_t uc +) +{ return u8_set(name->name, uc); +} diff --git a/output.c b/output.c new file mode 100644 index 0000000..4513d64 --- /dev/null +++ b/output.c @@ -0,0 +1,39 @@ + +/* void */ +/* condense() */ +/* { */ +/* FILE *vp, *op, *cp; */ +/* int v, m; */ +/* int num_models; */ + +/* vp = fopen("vdat_output", "w+"); */ +/* if(!vp) */ +/* perror("vdat_output failed to open\n"); */ + +/* op = fopen("odat_output", "w+"); */ +/* if(!op) */ +/* perror("odat_output failed to open\n"); */ + +/* cp = fopen("cdat_output", "w+"); */ +/* if(!cp) */ +/* perror("cdat_output failed to open\n"); */ + + + +/* /\* fwrite vdat *\/ */ +/* for(v = 0; v <= vbi; v++) */ +/* { */ +/* num_models = vdat_buf[v].num_models; //data duplication for caching */ +/* for(m = 0; m <= num_models; m++) */ +/* { */ + +/* } */ +/* } */ + +/* /\* fwrite odat *\/ */ +/* /\* Convert ref_list to actual offset *\/ */ + +/* /\* fwrite cdat *\/ */ + + +/* } */ diff --git a/parser.y b/parser.y new file mode 100644 index 0000000..6fe0969 --- /dev/null +++ b/parser.y @@ -0,0 +1,177 @@ +/* Asset Package Compiler */ +%code requires{ + #include + #include + #include "apc.h" +} +%{ + #include + #include + #include + + extern int lexer_init(); //? + extern int lexer(); //? + extern void pop_cdat(void); + extern void push_cdat(uint8_t*); + extern void insert_vdat(void); + extern void insert_refid(int); + extern void insert_set_name(uint8_t*); + extern void insert_set_namelist(uint8_t*); + extern void insert_link_name(uint8_t*); + extern void insert_map(int, uint8_t*, int, int, uint8_t*); + extern void insert_mlink(uint8_t*, int); + extern void insert_vlink(uint8_t*, int); + extern void insert_framesheet(uint_t* int, int, int,int, uint8_t*); + + #define yylex lexer + + + void yyerror(); +%} +%define parse.error verbose +%define lr.type ielr +%glr-parser + +%union { + int ref; + int val; + uint8_t *str; + struct name* name; + void *voidp; +} + + //operators +%token CLOPEN // ( +%token CLCLOSE // ) +%token MOPEN // ~ +%token HB +%token ROOT +%token SS +%token LINK //# +%token SCLOSE +%token CHILD +//terminals +%token NUM +%token PATH +%token REF +%token HEIGHT +%token WIDTH +%token D +%token NAME +%token SHIFT +//nonterminals +%type ref_id + /* Syntax Directed Translation Scheme of the APC grammar */ + +/* Rules */ +%% +cdat_buf: +class_block +; + +class: +NAME CLOPEN {push_cdat($1);} class_block CLCLOSE {pop_cdat();}; +; + +class_list: +class_list class +| class +; + +class_block: +class_list +| class_list statement_list +| statement_list +; + +statement_list: +statement_list statement +| statement +; + +statement: +vdat_statement +| map_statement +| ref_statement +| olink +; + +ref_statement: +set_namelist ref_id {insert_set_refid($2);}; +; + +link_namelist: +link_namelist NAME {insert_link_name($2);}; +| NAME {}; +; + + +set_namelist: +set_namelist NAME {insert_set_name($2);}; +| NAME {insert_set_namelist($1);}; +; + +map_statement: +set_namelist MOPEN map +| set_namelist MOPEN mlink +; + +map: +NAME NUM NUM PATH {insert_map($1, 0, $3, $4, 0, $5);}; +| NAME PATH {insert_map($1, 0, 0, 0, 0, $2);}; +| NAME D PATH {insert_map($1, $2, 0, 0, 0, $3);}; +| NAME D NUM NUM PATH {insert_map($1, $2, $3, $4, 0, $5);}; +| NAME NUM NUM ref_id PATH {insert_map($1, 0, $2, $3, $4, $5);}; +| NAME ref_id PATH {insert_map($1, 0, 0, 0, $2, $3);}; +| NAME D ref_id PATH {insert_map($1, $2, 0, 0, $3, $4);}; +| NAME D NUM NUM ref_id PATH {insert_map($1, $2, $3, $4, $5, $6);}; +; + +//shift list_namelist name > reduce mlink +mlink: +MOPEN LINK NAME LINK link_namelist PATH {insert_mlink($4, 0); }; +| MOPEN LINK link_namelist PATH {insert_mlink(NULL, 0); }; +| MOPEN LINK ref_id PATH {insert_mlink(NULL, $4); }; +| MOPEN LINK NAME LINK ref_id PATH {insert_mlink($4,$6); }; +; + +//shift list_namelist name > reduce vlink +vlink: +LINK NAME LINK link_namelist PATH {insert_vlink($2, 0); }; +| LINK link_namelist PATH {insert_vlink(NULL, 0);}; +| LINK REF PATH {insert_vlink(NULL, $2);};//vdat of ref +| LINK NAME LINK REF PATH {insert_vlink($2, $4);};//modelname of ref +; + + +olink: +set_namelist MOPEN REF +; + +ref_id: +LINK REF {$$ = $2;}; +; + + +vdat_statement: +set_namelist SS spritesheet_statement +| set_namelist SS vlink +; + +spritesheet_statement: +NAME D HEIGHT WIDTH PATH {insert_framesheet($1, $2, $3, $4, 0, $5);}; +| NAME D PATH {insert_framesheet($1, $2, 0, 0, 0, $3);}; +| NAME HEIGHT WIDTH PATH {insert_framesheet($1, 0, $2, $3, 0, $4);}; +| NAME PATH {insert_framesheet($1, 0, 0, 0, 0, $2);}; +| NAME D HEIGHT WIDTH ref_id PATH {insert_framesheet($1, $2, $3, $4, $5, $6);}; +| NAME D ref_id PATH {insert_framesheet($1, $2, 0, 0, $3, $4);}; +| NAME HEIGHT WIDTH ref_id PATH {insert_framesheet($1, 0, $2, $3, $4, $5);}; +| NAME ref_id PATH {insert_framesheet($1, 0, 0, 0, $2, $3);}; +; + +%% + +void +yyerror (char const *s) +{ fprintf(stderr, "%s\n", s); +} diff --git a/ragraph b/ragraph new file mode 100755 index 0000000..cc9c55f --- /dev/null +++ b/ragraph @@ -0,0 +1,3 @@ +#!/bin/bash + +ragel -V -p lexer_fsm.rl | dot -Tpng -o ragraph.png diff --git a/ragraph.png b/ragraph.png new file mode 100644 index 0000000..e8a831f Binary files /dev/null and b/ragraph.png differ diff --git a/scanner.c b/scanner.c new file mode 100644 index 0000000..55245af --- /dev/null +++ b/scanner.c @@ -0,0 +1,255 @@ +/*!@file + \brief APC Directory Scanner + \details This hand-written parser/scanner traverses a directory tree and + tokenizes elements of the structure which correspond to APC grammar. + The parser is implemented as a 2D stack which populates a list of + child directories at each depth, handling only the leaf nodes + (regular files) of the directory open at the current depth to + conserve memory and speed up traversal. + The scanner works with the lexer to lexically analyze text, and + assumes the existence of an external 'lex' function + \author Jordan Lavatai + \date Aug 2016 + ----------------------------------------------------------------------------*/ +/* Standard */ +#include //print +#include //strncmp +#include //errno +#include //tolower +/* Posix */ +#include //warnx +#include //exit +#include //chdir +#include //opendir +#include //unicode strings +/* Internal */ +#include "parser.tab.h" +/* Public */ +int scanner_init(void); +void scanner_quit(void); +int scanner(void); +int scanner_scanpixels(int*,int); +/* Private */ +extern //lexer.c +int lexer_lexstring(const uint8_t*); +extern //lexer.c +void lexer_pushtok(int, int); +static +int dredge_current_depth(void); +/* Mem */ +extern //lexer.c +struct dirent* lexer_direntpa[], **lexer_direntpp; +extern //SRC_DIR/bin/tools/apc.c +const char* cargs['Z']; +#ifndef DL_STACKSIZE +#define DL_STACKSIZE 64 +#endif +#ifndef DL_CD_STACKSIZE +#define DL_CD_STACKSIZE DL_STACKSIZE //square tree +#endif +static +struct dirlist +{ DIR* dirp; + struct dirent* child_directory_stack[DL_CD_STACKSIZE],** cds; +} directory_list_stack[DL_STACKSIZE + 1],* dls; //+1 for the root dir +static +FILE* current_open_file = NULL; + +/* Directory Listing Stack + FILO Stack for keeping an open DIR* at each directory depth for treewalk. + This stack is depth-safe, checking its depth during push operations, but not + during pop operations, to ensure the thread doesn't open too many files at + once (512 in c runtime), or traverse too far through symbolic links. + A directory listing includes a DIR* and all DIR-typed entity in the directory + as recognized by dirent, populated externally (and optionally). + This stack behaves abnormally by incrementing its PUSH operation prior to + evaluation, and the POP operations after evaluation. This behavior allows + the 'DL_CURDEPTH' operation to map to the current element in the 'dl_stack' + array, and it is always treated as the "current depth". This also allows us + to init the root directory to 'directory_list_stack'[0] and pop it in a safe + and explicit manner. +*/ +#define DL_STACK (directory_list_stack) +#define DL_STACKP (dls) +#define DL_CD_STACK ((*DL_STACKP).child_directory_stack) +#define DL_CD_STACKP ((*DL_STACKP).cds) +#define DL_CURDIR() ((*DL_STACKP).dirp) +#define DL_LEN() (DL_STACKP - DL_STACK) +#define DL_CD_LEN() (DL_CD_STACKP - DL_CD_STACK) +#define DL_INIT() (DL_STACKP = DL_STACK) +#define DL_CD_INIT() (DL_CD_STACKP = DL_CD_STACK) +#define DL_POP() ((*DL_STACKP--).dirp) +#define DL_CD() (*DL_CD_STACKP) +#define DL_CD_CURNAME() (DL_CD()->d_name) +#define DL_CD_POP() (*--DL_CD_STACKP) +#define DL_PUSH(D) ((*++DL_STACKP).dirp = D) +#define DL_CD_PUSH(E) (*DL_CD_STACKP++ = E) + + +/* Initializer + Initializer expects a function pointer to its lexical analysis function. + Sets up stack pointers and returns boolean true if 'opendir' encounters an + error, or if dredge_current_depth returns boolean true. +*/ +int scanner_init +#define CWDSTR "./" +#define ROOTDIR (cargs['d'] ? cargs['d'] : CWDSTR) +() +{ DL_INIT(); + DL_STACK[0].dirp = opendir(ROOTDIR); + if (current_open_file != NULL) + { fclose(current_open_file); + current_open_file = NULL; + } + printf("Root dir %s\n",ROOTDIR); + return !chdir(ROOTDIR) && (DL_STACK[0].dirp == NULL || dredge_current_depth() == -1); +} + +/* Quit */ +void scanner_quit +() +{ if (DL_CURDIR()) + closedir(DL_CURDIR()); +} + +/* Scanner + The main driver of the scanner will advance the current treewalk state and + tokenize tree-based push/pop operations. It will call 'lexer_lex' to + tokenize directory names prior to making a push operation. safe checking for + all returns from the filesystem handler will exit on serious system errors. + + after pushing a new directory to the directory list, the scanner will dredge + the directory and alphabetically sort all file entries into the lexer's file + array, while placing all subdirectory entries in the current depth's child + directory stack to be scanned later. + + Returns the number of tokens generated on success, -1 on error. +*/ +int scanner +#define $($)#$ //stringifier +#define ERR_CHILD "Fatal: Maximum of " $(DL_CD_STACKSIZE) \ + " child directories exceeded for directory at depth %i\n" \ + ,DL_LEN() +#define ERR_DEPTH "Fatal: Maximum directory depth of " $(DL_STACKSIZE) \ + " exceeded during directory scan\n" +#define ERR_DL "Fatal: Directory List Stack Corruption %x\n", DL_LEN() +() +{ int ntok = 0; + scan: + if (DL_CD_LEN() >= DL_CD_STACKSIZE)//fail if maxchildren exceeded + { fprintf(stderr, ERR_CHILD); + goto fail; + } + if (DL_CD_LEN() > 0) //There are entities to process + { if (DL_CD_POP() == NULL) //If the dirent is null, then the + goto libfail; //lib function in dirent has failed +<<<<<<< HEAD + ntok += lexer_lexstring(DL_CD_CURNAME());//lex the directory name +======= + ntok += lexer_lexstring(DL_CD_CURNAME()); //lex the directory name +>>>>>>> 15d3ab5e7871ff459af13089b82bf5f17f731ebd + if (DL_LEN() >= DL_STACKSIZE) //fail if maxdepth exceeded + { fprintf(stderr, ERR_DEPTH); + goto fail; + } + if (chdir(DL_CD_CURNAME())) //move into the new directory + goto libfail; + if (DL_CURDIR() == NULL) //open the cwd + goto libfail; + lexer_pushtok(CLOPEN, 0); //Push "Open Directory" token + ntok++; + return dredge_current_depth(); //Filter and sort the current depth + } + else if (DL_LEN() >= 0) //Any dirs left? (Including root) + { if (closedir(DL_POP())) //close the directory we just left + goto libfail; + if (DL_LEN() == -1) //If we just popped root, + goto done; //we're done + lexer_pushtok(CLCLOSE, 0); //Else push "Close Directory" token, + ntok++; + if (!chdir("..")) //move up a directory and + goto scan; //start over + } + fprintf(stderr, ERR_DL); + libfail: + perror("scanner: "); + fail: + return -1; + done: + return ntok; +} + +/* Scan Pixels + Scans up to 'len' pixels from the current file into 'buf'. + Returns the number of pixels scanned from the file, or -1 on error +*/ +int scanner_scanpixels +( int* buf, + int max_len +) +{ static int col_len, row_len, row; + //Open the current file if not yet open + if (current_open_file == NULL) + { if ((current_open_file = fopen(DL_CD_CURNAME(),"rb")) == NULL) + { perror("fopen: "); + return -1; + } + //Verify file header, get row_len/col_len + //if (read_img_header(&row_len, &col_len)) + //return -1; + row = 0; + } + //Read pixels into the buffer if there are rows left in the image + if (row++ < row_len) + //TODO: return read_img_pixels(buf, col_len); + printf("SCANPIXELS NOT IMPLEMENTED\n."); + //Close the file and return 0 + fclose(current_open_file); + current_open_file = NULL; + return 0; +} + +/* Directory Entity Sort and Filter (Dredge) + This filter removes all unhandled file types, and places any 'DT_DIR' type + files in the current Directory List's directory stack. Upon finishing, + the 'CE_STACK' is sorted alphabetically, and the current 'DL_CD_STACK' is + populated. Prints warnings for unhandled files. + + Returns -1 if 'readdir' encounters an error, otherwise returns the number of + directory entries sent to the external 'lexer_direntpa' array. +*/ +typedef //so we can typecast dirent's 'alphasort()' to take const void*s +int (*qcomp)(const void*, const void*); +static inline +int dredge_current_depth +#define READDIR_ERROR (-1) +#define READDIR_DONE (0) +#define DPS_LEN() (lexer_direntpp - lexer_direntpa) +#define DPS_PUSH(E) (*lexer_direntpp++ = E) +() +{ struct dirent** direntpp = lexer_direntpa; + DIR* cwd = DL_CURDIR(); + struct dirent* direntp; + DL_CD_INIT(); + scan_next: + if ((direntp = readdir(cwd)) != NULL) + { switch (direntp->d_type) + { case DT_REG: + DPS_PUSH(direntp); + goto scan_next; + case DT_DIR: + if (*(direntp->d_name) == '.') //skip hidden files and relative dirs + goto scan_next; + DL_CD_PUSH(direntp); + goto scan_next; + case DT_UNKNOWN: + warnx("unknown file %s: ignoring", direntp->d_name); + default: + goto scan_next; + } + } + if (errno) + return -1; + qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort); + return DPS_LEN(); +}