--- /dev/null
+*.tab.c
+*.tab.h
+lexer_lex.c
--- /dev/null
+#include <stdint.h>
+#include <unitypes.h>
+#include <limits.h>
+
+//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];
+};
--- /dev/null
+/*!@file\r
+ \brief IR Memory Implementation\r
+ \details Intermediary memory management\r
+ \author Jordan Lavatai\r
+ \date Aug 2016\r
+ ----------------------------------------------------------------------------*/\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <unitypes.h> //uint8_t as a char\r
+#include <unistr.h> //u32_cpy\r
+#include <stdint.h> //uint64_t\r
+#include <string.h> //memset\r
+#include <unistd.h> //u8_* functions\r
+#include "apc.h"\r
+\r
+\r
+extern\r
+int\r
+name_u8_cpy(struct name*, struct name*);\r
+\r
+extern\r
+int\r
+name_u8_cmp(struct name*, struct name*);\r
+\r
+extern\r
+int\r
+name_u8_set(struct name*, ucs4_t);\r
+\r
+int\r
+ir_init(void);\r
+struct cdat*\r
+alloc_cdat(void);\r
+struct odat*\r
+alloc_odat(void);\r
+void\r
+alloc_vdat(void);\r
+struct link*\r
+alloc_link(void);\r
+struct ref*\r
+alloc_ref(void);\r
+struct set*\r
+alloc_set(void);\r
+struct cdat*\r
+curr_cdat(void);\r
+struct odat*\r
+curr_odat(void);\r
+struct vdat*\r
+curr_vdat(void);\r
+struct map*\r
+curr_map(void);\r
+struct set*\r
+curr_cdat_set(void);\r
+struct set*\r
+curr_set(int);\r
+struct ref*\r
+curr_ref(void);\r
+struct model*\r
+curr_model(void);\r
+\r
+/* ir.c */\r
+void\r
+inc_posts(void);\r
+void\r
+push_cdat(struct name*);\r
+void\r
+pop_cdat(void);\r
+void\r
+insert_link_name(struct name*);\r
+void\r
+insert_link_namelist(struct name*);\r
+void\r
+insert_ss_name(struct name*);\r
+void\r
+insert_ss_namelist(struct name*);\r
+void\r
+insert_mlink(struct name*, int);\r
+void\r
+insert_vlink(struct name*, int);\r
+void\r
+insert_ref(struct odat*, int);\r
+void\r
+alloc_vdat(void);\r
+void\r
+insert_vdat(void);\r
+void\r
+insert_map(struct name*, int, int, int, int, uint8_t*);\r
+void\r
+insert_framesheet(struct name*, int, int, int, int, uint8_t*);\r
+\r
+\r
+\r
+//type safety handled by macro expansion (do not call these directly from code, make dependent macros for access to these)\r
+#define CHUNKS_LEN(STACK) ((STACK).csp - (STACK).chunks)\r
+#define CURRENT_CHUNK(STACK) ((STACK).chunks[CHUNKS_LEN(STACK) - 1])\r
+#define CHUNKS_FULL(STACK) ( (STACK).csp >= \\r
+ (STACK).chunks + MAX_CHUNKS * (STACK).chunk_size)\r
+#define CURRENT_DSP(STACK,TYPE) ((TYPE*) ((STACK).dsp[CHUNKS_LEN(STACK) - 1]))\r
+#define DATA_FULL(STACK,TYPE) ((void*) CURRENT_DSP(STACK,TYPE) >= \\r
+ (CURRENT_CHUNK(STACK) + (STACK).chunk_size))\r
+#define CSP_PUSH(STACK) (*(++(STACK).csp) = malloc((STACK).chunk_size))\r
+#define CURRENT_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 1])\r
+#define PREVIOUS_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 2])\r
+#define ALLOC_DAT(STACK,TYPE) (++CURRENT_DATP(STACK,TYPE))\r
+#define INIT_STACK(STACK,TYPE) \\r
+ { int i; \\r
+ (STACK).chunk_size = PAGES_PER_CHUNK * pagesize; \\r
+ (STACK).max_dats = (STACK).chunk_size / sizeof (TYPE); \\r
+ CSP_PUSH(STACK); \\r
+ for( i = 0; i < MAX_CHUNKS; i++){ \\r
+ (STACK).dsp[i] += pagesize; \\r
+ } \\r
+ }\r
+//Stack-specific macros (called directly from code (safety enforcement)\r
+#define INIT_ODAT() (INIT_STACK(ocs, struct odat))\r
+#define CURRENT_ODAT() (CURRENT_DATP(ocs,struct odat))\r
+#define ODAT_FULL() (DATA_FULL(ocs,struct odat))\r
+#define ODAT_ALLOC() (ALLOC_DAT(ocs,struct odat))\r
+#define OCS_FULL() (CHUNKS_FULL(ocs))\r
+#define INIT_VDAT() (INIT_STACK(vcs, struct vdat))\r
+#define CURRENT_VDAT() (CURRENT_DATP(vcs,struct vdat))\r
+#define VDAT_FULL() (DATA_FULL(vcs,struct vdat))\r
+#define VDAT_ALLOC() (ALLOC_DAT(vcs,struct vdat))\r
+#define VCS_FULL() (CHUNKS_FULL(vcs))\r
+#define INIT_CDAT() (INIT_STACK(ccs, struct cdat))\r
+#define CURRENT_CDAT() (CURRENT_DATP(ccs,struct cdat))\r
+#define CDAT_FULL() (DATA_FULL(ccs, struct cdat))\r
+#define CDAT_ALLOC() (ALLOC_DAT(ccs, struct cdat))\r
+#define CCS_FULL() (CHUNKS_FULL(ccs))\r
+#define INIT_SET() (INIT_STACK(scs, struct set))\r
+#define CURRENT_SET() (CURRENT_DATP(scs, struct set))\r
+#define SET_FULL() (DATA_FULL(scs, struct set))\r
+#define SET_ALLOC() (ALLOC_DAT(scs, struct set))\r
+#define SCS_FULL() (CHUNKS_FULL(scs))\r
+#define INIT_LINK() (INIT_STACK(lcs, struct link))\r
+#define CURRENT_LINK() (CURRENT_DATP(lcs,struct link))\r
+#define LDAT_FULL() (DATA_FULL(lcs, struct link))\r
+#define LDAT_ALLOC() (ALLOC_DAT(lcs, struct link))\r
+#define LCS_FULL() (CHUNKS_FULL(lcs))\r
+#define INIT_POST() (INIT_STACK(rcs, struct ref))\r
+#define CURRENT_POST() (CURRENT_DATP(pcs,struct ref))\r
+#define POST_FULL() (DATA_FULL(pcs,struct ref))\r
+#define POST_ALLOC() (ALLOC_DAT(pcs,struct ref))\r
+#define PCS_FULL() (CHUNKS_FULL(pcs))\r
+#define INIT_REF() (INIT_STACK(rcs, struct ref))\r
+#define CURRENT_REF() (CURRENT_DATP(rcs,struct ref))\r
+#define PREVIOUS_REF() (PREVIOUS_DATP(rcs, struct ref))\r
+#define REF_FULL() (DATA_FULL(rcs,struct ref))\r
+#define REF_ALLOC() (ALLOC_DAT(rcs,struct ref))\r
+#define RCS_FULL() (CHUNKS_FULL(rcs))\r
+//Metadata\r
+#define CURRENT_MODEL() (CURRENT_VDAT()->model_list[CURRENT_VDAT()->num_models])\r
+\r
+\r
+\r
+/* Dynamically allocate memory for a class data structure,\r
+ or cdat, after a class has been identified in a grammar.\r
+ We also create a stack of class pointers so that\r
+ we can access the cdat during processing of that\r
+ cdats sets and elements, a requirement because the\r
+ nature of recursive classes prevents us from accessing\r
+ the cdat based on the previous index into cdat_buf,\r
+ which is a list of all allocated cdats\r
+/* Cdats: A cdat is a class data structure. Cdats serve as the central */\r
+/* data types of the IR. Cdats contain pointers to their subclasses so that the relationship between */\r
+/* classes can be determined, but the subclasses are not represented inside */\r
+/* of the cdat itself but rather in subsequent cdats in cdat_buf. We */\r
+/* can determine the number of subclasses (the last index into cdat_buf */\r
+/* that represents a subclass of some arbitrary cdat) each cdat has by */\r
+/* incrementing num_classes during parse time. */\r
+/* TODO: Should classes point to their parent class? */\r
+/* TODO: Talk more about cdat set structure */\r
+struct cdat {\r
+ struct name name;\r
+ int idx;\r
+ int num_classes;\r
+ int num_sets;\r
+ struct cdat* class_list[MAX_CLASSES];\r
+ struct set* set_list[MAX_SETS];\r
+};\r
+\r
+\r
+/* Sets: What is a set? \r
+ Instantiation?\r
+ Associations? \r
+ Containment?\r
+ Usage?\r
+ The set is populated at parse time AFTER the elements are populated, due to\r
+ the nature of bottom up parsing. */\r
+struct set {\r
+ int cdat_idx;\r
+ int num_sets;\r
+ struct set* set_list[MAX_SETS];\r
+};\r
+\r
+/* Refs: Each set/ele has a reference to its object data (odat) through a refid.\r
+ refids are unsigned 64 byte integers that map to the hex values RGBA. During\r
+ the construction of the directory structure, users can choose a RGBA value for\r
+ each object that any other object can refer to via links (see link). If a user\r
+ does not choose an RGBA value, then the object is given one from the system space.\r
+ We maintain a doubly linked list of refs in the ref_buf at parse time so that\r
+ links can be resolved after the parsing of the directory structure is complete.\r
+ For every 16th ref, we create a post so that we can reduce on the search time for\r
+ a random access. */\r
+\r
+struct ref {\r
+ int type; //TODO: Is this needed?\r
+ struct ref* nextref;\r
+ struct ref* lastref;\r
+ struct odat* odatp;\r
+ int refid; //0xFFFFFF->digit\r
+};\r
+\r
+/* Links: At parse time, a set/ele can include a link in their\r
+ grammar representation instead of the actual data and this signifies\r
+ to the APC that that set/ele wishes to use the data of another\r
+ set/ele, either its video data (vdat) or object data (odat). The link\r
+ itself contains the type of link it is, the refid OR name, and\r
+ which set/ele created the link. During parse time, links can be made\r
+ to o/vdats that have yet to be parsed. In order to accomodate for this,\r
+ we resolve all links AFTER parse time by iterating through the link_buf,\r
+ finding the refid that was stored for some object (if the refid exists),\r
+ and creating a relative pointer from the original object to the data that\r
+ was linked */\r
+\r
+/* TODO: Explain links more betta */\r
+\r
+struct olink {\r
+ int src_refid;\r
+};\r
+ \r
+struct vlink {\r
+ int src_refid;\r
+ struct name src_animname;\r
+ struct name src_namelist[MAX_DEPTH];\r
+};\r
+\r
+struct mlink {\r
+ int src_refid;\r
+ struct name src_mapname;\r
+ struct name src_namelist[MAX_DEPTH];\r
+\r
+};\r
+\r
+union link_t {\r
+ struct vlink vlink;\r
+ struct mlink mlink;\r
+ struct olink olink;\r
+};\r
+\r
+\r
+/* From: src odat ()To: dest odat (refid)*/\r
+struct link {\r
+ int type; //1 = olink, 2 = vlink, 3 = mlink\r
+ union link_t link_t;\r
+ int dest_refid; //if it exists\r
+ struct odat* dest_odatp;\r
+\r
+};\r
+\r
+struct map {\r
+ struct name name;\r
+ int height;\r
+ int width;\r
+ uint8_t filepath[FPATH_MAX];\r
+};\r
+\r
+/* Odats: Odats consist of the object data necessary for\r
+ each object. Odats are sometimes referred to as archetypes\r
+ at compile-time, in order to distinguish the difference from\r
+ a runtime object and a compile-time object.\r
+ TODO: Need more info about objects at runtime, to described\r
+ the reasoning behind odat structure at compile-time*/\r
+struct odat {\r
+ struct name name;\r
+ int refid; \r
+ int ismap;\r
+ int vdat_idx;\r
+ struct link* linkp; \r
+ struct vdat* vdatp;\r
+ struct odat* parent_odatp; // odat == set ? null : set refid\r
+ struct ref* refp; /* pointer to it's ref on ref_list */\r
+ struct map map; //only valid if odat ismap\r
+\r
+};\r
+\r
+/* A framesheet is a grouping of animation frames in\r
+ a single direction (N,W,S,E) */\r
+struct framesheet {\r
+ int width;\r
+ int height;\r
+ int num_frames;\r
+\r
+};\r
+\r
+/* A model is a collection of framesheets for every\r
+ direction (N,W,S,E,NW,NE,SW,SE)*/\r
+/* NAMED spritesheet */\r
+struct model {\r
+ struct name name;\r
+ uint8_t filepath[PATH_MAX];\r
+ struct framesheet spritesheet[8]; //one for each\r
+};\r
+\r
+/* Vdat: Vdats are the video data of each object. They can not be\r
+ created as a stand alone object (because they consist solely\r
+ of animation information and not the map which the\r
+ animation manipulates). Vdats have a list of models for every\r
+ animation that the vdats odat can do for that vdat*/\r
+struct vdat {\r
+ struct odat* creator; //pointer to odat that made this vdat\r
+ int num_models;\r
+ uint8_t filename[FNAME_MAX];\r
+ int height;\r
+ int width;\r
+ uint8_t filepath[FPATH_MAX];\r
+ struct model model_list[MAX_MODELS];\r
+};\r
+\r
+\r
+struct set_frame\r
+{ struct name namelist[MAX_DEPTH];\r
+ int num_names;\r
+ struct set* setp;\r
+ struct odat* odatp;\r
+} ;\r
+\r
+\r
+\r
+struct set_stack\r
+{ struct set_frame set_frames[MAX_DEPTH];\r
+ int curr_depth; //used to get most recently created set/odat + to check for undefined parents of namelists\r
+};\r
+\r
+\r
+//"type free" chunk stacking\r
+struct chunk_stack\r
+{ void* chunks[MAX_CHUNKS];\r
+ void* *csp; //chunk stack pointer\r
+ void* dsp[MAX_CHUNKS]; //dat stack pointer (per chunk)\r
+ int chunk_size; //size of a chunk (including its forfeited page)\r
+ int max_dats; //number of dats per chunk for this stack\r
+} ocs, vcs, ccs, rcs, lcs, pcs, scs; //odat, vdat, cdat, ref, link, post stacks\r
+\r
+\r
+\r
+\r
+/* The cdat_stack is a stack pointers to cdat pointers, the top of which is\r
+ the cdat that is currently being parsed. Whenever a new cdat is recognized\r
+ by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer\r
+ to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have\r
+ access to the current cdat so that the elements and sets can populate themselves\r
+ in the cdat accordingly. */\r
+\r
+\r
+struct cdat* cdat_stack[MAX_CLASSES];\r
+struct cdat** cdat_stackp;\r
+\r
+struct set_stack ss;\r
+struct name set_namelist[MAX_DEPTH];\r
+int set_numnames = 0;\r
+\r
+struct name link_namelist[MAX_DEPTH];\r
+int link_numnames = 0;\r
+\r
+int num_cdats = 0;\r
+int num_odats = 0;\r
+int num_vdats = 0;\r
+int num_sets = 0;\r
+int num_refs = 0;\r
+int ss_refid = 0x0FFFFFFF; /* system space for refids */\r
+int num_posts = 0;\r
+int num_links = 0;\r
+int num_models = 0;\r
+long pagesize = 0;\r
+\r
+\r
+/* The initalization function of the IR. */\r
+int\r
+ir_init()\r
+{ struct name name;\r
+\r
+\r
+ uint8_t root[4] = "root";\r
+\r
+ u8_stpncpy(name.name, root, 4);\r
+\r
+ pagesize = sysconf(_SC_PAGESIZE);\r
+ printf("pagesize is %l\n", pagesize);\r
+\r
+ INIT_CDAT();\r
+ *cdat_stackp = CURRENT_CDAT();\r
+ name_u8_cpy(&(*cdat_stackp)->name, &name);\r
+\r
+ INIT_ODAT();\r
+ INIT_VDAT();\r
+ VDAT_ALLOC(); //NULL vdat\r
+ VDAT_ALLOC(); //First vdat req. because alloc_vdat happens after vdat is reduced\r
+ INIT_SET();\r
+ INIT_LINK();\r
+ INIT_REF();\r
+ INIT_POST();\r
+\r
+\r
+ return 0;\r
+\r
+}\r
+\r
+void\r
+ir_quit()\r
+{\r
+ int i;\r
+\r
+ for(i = 0; i < CHUNKS_LEN(ccs) ; i++)\r
+ {\r
+ free(ccs.chunks[i]);\r
+ }\r
+ for(i = 0; i < CHUNKS_LEN(ocs); i++)\r
+ {\r
+ free(ocs.chunks[i]);\r
+ }\r
+ for(i = 0; i < CHUNKS_LEN(vcs) ; i++)\r
+ {\r
+ free(vcs.chunks[i]);\r
+ }\r
+ for(i = 0; i < CHUNKS_LEN(rcs); i++)\r
+ {\r
+ free(rcs.chunks[i]);\r
+ }\r
+ for(i = 0; i < CHUNKS_LEN(lcs); i++)\r
+ {\r
+ free(lcs.chunks[i]);\r
+ }\r
+ for(i = 0; i < CHUNKS_LEN(pcs); i++)\r
+ {\r
+ free(pcs.chunks[i]);\r
+ }\r
+\r
+}\r
+\r
+struct cdat*\r
+alloc_cdat()\r
+{\r
+ num_cdats++;\r
+ if(CDAT_FULL())\r
+ { if(CCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) cdats ", num_cdats);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(ccs);\r
+ }\r
+ else\r
+ CDAT_ALLOC();\r
+\r
+ return CURRENT_CDAT();\r
+}\r
+\r
+//these should probably be inline\r
+struct odat*\r
+alloc_odat\r
+()\r
+{\r
+ num_odats++;\r
+ if(ODAT_FULL())\r
+ { if(!OCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) odats ", num_odats);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(ocs);\r
+ }\r
+ else\r
+ ODAT_ALLOC();\r
+\r
+ return CURRENT_ODAT();\r
+}\r
+\r
+void\r
+alloc_vdat\r
+()\r
+{ num_vdats++;\r
+ if(VDAT_FULL())\r
+ { if(!VCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) vdats ", num_vdats);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(vcs);\r
+ }\r
+ else\r
+ VDAT_ALLOC();\r
+\r
+ \r
+}\r
+\r
+struct set* \r
+alloc_set\r
+()\r
+{ num_sets++;\r
+ if(SET_FULL())\r
+ { if(!SCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) sets ", num_sets);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(scs);\r
+ }\r
+ else\r
+ SET_ALLOC();\r
+\r
+ return CURRENT_SET();\r
+}\r
+\r
+\r
+struct link*\r
+alloc_link\r
+()\r
+{ num_links++;\r
+ if(LDAT_FULL())\r
+ { if(!LCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) links ", num_links);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(lcs);\r
+ }\r
+ else\r
+ LDAT_ALLOC();\r
+\r
+ return CURRENT_LINK();\r
+\r
+}\r
+\r
+struct ref*\r
+alloc_ref\r
+()\r
+{ num_refs++;\r
+ if(REF_FULL())\r
+ { if(!RCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) refs ", num_refs);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(rcs);\r
+ }\r
+ else\r
+ REF_ALLOC();\r
+\r
+\r
+ if(num_refs % 16 == 0)\r
+ { CURRENT_POST() = CURRENT_REF();\r
+ inc_posts();\r
+ }\r
+\r
+ return CURRENT_REF();\r
+}\r
+\r
+void\r
+inc_posts()\r
+{ num_posts++;\r
+ if(POST_FULL())\r
+ { if(!PCS_FULL())\r
+ { fprintf(stderr, "You have allocated to many (%d) refs ", num_posts);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ else\r
+ CSP_PUSH(pcs);\r
+ }\r
+ else\r
+ POST_ALLOC();\r
+\r
+}\r
+\r
+struct cdat*\r
+curr_cdat\r
+()\r
+{\r
+ return (*cdat_stackp);\r
+}\r
+\r
+struct odat*\r
+curr_odat\r
+()\r
+{\r
+ return CURRENT_ODAT();\r
+}\r
+\r
+struct vdat*\r
+curr_vdat\r
+()\r
+{\r
+ return CURRENT_VDAT();\r
+}\r
+\r
+struct set*\r
+curr_cdat_set \r
+()\r
+{\r
+ return CURRENT_SET();\r
+}\r
+\r
+struct set*\r
+curr_set\r
+(int depth)\r
+{ int i;\r
+ struct set* setp;\r
+\r
+ for(i = 0; i <= depth; i++)\r
+ { if(!(setp = setp->set_list[setp->num_sets]))\r
+ { printf("You are trying to access a set that does not exist irmem.c\n");\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+\r
+ return setp;\r
+}\r
+\r
+struct ref*\r
+curr_ref\r
+()\r
+{\r
+ return CURRENT_REF();\r
+}\r
+struct ref*\r
+prev_ref\r
+()\r
+{\r
+ return PREVIOUS_REF();\r
+}\r
+struct model*\r
+curr_model\r
+()\r
+{\r
+ return &CURRENT_MODEL();\r
+}\r
+\r
+/* IR.C*/\r
+void\r
+push_cdat\r
+( name )\r
+ struct name* name;\r
+{\r
+ struct cdat* curr_cdatp;\r
+\r
+ curr_cdatp = alloc_cdat();\r
+\r
+ name_u8_cpy(&curr_cdatp->name, name);\r
+ curr_cdatp->idx = num_cdats;\r
+\r
+ /* Set the cdat as a subclass of the previous cdat */\r
+ (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes] = curr_cdatp;\r
+ /* Push the cdat onto the cdat_stack */\r
+ *++cdat_stackp = curr_cdatp;\r
+\r
+}\r
+\r
+void\r
+pop_cdat\r
+()\r
+{\r
+ cdat_stackp--;\r
+}\r
+\r
+\r
+void\r
+insert_set_name\r
+( name )\r
+ struct name* name;\r
+{ \r
+ //Push name onto current namelist, set the set_namelist.\r
+ name_u8_cpy(&set_namelist[set_numnames++], name);\r
+ \r
+ \r
+}\r
+\r
+\r
+void\r
+insert_set_namelist\r
+( name )\r
+ struct name* name;\r
+{ int depth, nameidx, i;\r
+\r
+ insert_set_name(name);\r
+\r
+ //Check if entire string matches first? Only possible if namelist is contiguous (uint8_t strings seperated by \0)\r
+ //Create odats/sets for each name in namelist where nameidx > ns_depth\r
+ //first check if any parts of namelist matches what is currently on namestack\r
+ //we can gauruntee that from ns_depth + 1 -> set_numnames namelists dont match. x\r
+ \r
+\r
+ //if name_list doesnt match, from the first depth at which namelist doesnt match\r
+ //remove the nameframes namelist (zero out ones below?) and replace with current namelist,\r
+ //then allocate a new odat and set it to the current set_frame.\r
+ for( depth = 0; depth < set_numnames ; depth++ )\r
+ { for (nameidx = 0; nameidx <= depth; nameidx++)\r
+ { if( name_u8_cmp(&set_namelist[nameidx], &ss.set_frames[depth].namelist[nameidx]) != 0 )\r
+ { /* Populate the namelist of the set at the current depth */\r
+ for(i = 0; i <= depth; i++)\r
+ name_u8_cpy(&ss.set_frames[depth].namelist[i], &set_namelist[i]);\r
+\r
+ /* Alloc set and odat */\r
+ ss.set_frames[depth].odatp = alloc_odat();\r
+ ss.set_frames[depth].setp = alloc_set();\r
+\r
+ /* populate set/odat name and cdat_idx */\r
+ name_u8_cpy(&ss.set_frames[depth].odatp->name, &set_namelist[depth]);\r
+ ss.set_frames[depth].setp->cdat_idx = ( *cdat_stackp)->idx;\r
+ \r
+ /* Insert allocated set and odat into their respective trees if there is a depth \r
+ (they have parents) */ \r
+ if(depth)\r
+ { ss.set_frames[depth].odatp->parent_odatp = ss.set_frames[depth-1].odatp;\r
+ if(ss.set_frames[depth-1].setp->num_sets < MAX_SETS)\r
+ ss.set_frames[depth-1].setp->set_list[ss.set_frames[depth-1].setp->num_sets++] = ss.set_frames[depth].setp;\r
+ else\r
+ { printf("you have allocated too many sets in insert_namelist()\n");\r
+ //TODO: EXIT()\r
+ }\r
+ }\r
+ else /* no parent set, so assign to cdat set_list */\r
+ { ss.set_frames[depth].odatp->parent_odatp = NULL; //no parent odat = NULL.\r
+ if(curr_cdat_set()->num_sets < MAX_SETS)\r
+ curr_cdat_set()->set_list[curr_cdat_set()->num_sets++] = ss.set_frames[depth].setp;\r
+ else\r
+ { printf("you have allocated too many sets in insert_namelist()\n");\r
+ //TODO: EXIT()\r
+ }\r
+ }\r
+ \r
+ \r
+ ss.set_frames[depth].num_names = set_numnames;\r
+ ss.curr_depth = depth;\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ done:\r
+ ;\r
+}\r
+\r
+/*. We create new odats for each map variant that are children of the current odat/set\r
+ , set their name as the map name, and identify them by marking them as a map. This lets\r
+ us distinguish between sibling odatsthat have the same name because the map of the parent\r
+ odat had the same name as another, regular odat*/\r
+#define CURR_SS_FRAME() (ss.set_frames[ss.curr_depth])\r
+#define CURR_SS_SETP() (CURR_SS_FRAME().setp)\r
+#define CURR_SS_ODATP() (CURR_SS_FRAME().odatp)\r
+void\r
+insert_map\r
+( name, direction, height, width, refid, filepath )\r
+ struct name* name;\r
+ int direction, height, width, refid;\r
+ uint8_t* filepath;\r
+{ int i;\r
+ struct odat* curr_mem_odatp; //pointer to odat in odat_buf\r
+ struct set* curr_mem_setp; //pointer to set in set_buf\r
+ struct link* linkp;\r
+\r
+ curr_mem_odatp = alloc_odat();\r
+ curr_mem_setp = alloc_set();\r
+ //Create a new odat, make its parent be the set. Make a set for mdat, its name should\r
+ //be the name of the odat + name of model. That makes a conflict beween odats that are named\r
+ //the same thing as the model of a sibling odat that was created from a map. They can have\r
+ //same name if the map odat is marked. So mark the map odat.\r
+\r
+ //insert parent odat\r
+ curr_mem_odatp->parent_odatp = CURR_SS_ODATP(); \r
+ //insert into set_list\r
+ if(CURR_SS_SETP()->num_sets < MAX_SETS)\r
+ CURR_SS_SETP()->set_list[CURR_SS_SETP()->num_sets++] = curr_mem_setp;\r
+ else\r
+ { printf("You have allocated to many sets, error in insert_map()\n");\r
+ //TODO: EXIT()\r
+ }\r
+ \r
+ //indicate that newly created odat is a map\r
+ curr_mem_odatp->ismap = 1;\r
+ //set odat and set name\r
+ name_u8_cpy(&curr_mem_odatp->name, name);\r
+\r
+ /* set cdat idx values for both set and odat */\r
+ curr_mem_setp->cdat_idx = num_cdats;\r
+\r
+\r
+ /* Generate refid if needed, put into ref_buf */\r
+ if(!refid)\r
+ refid = ss_refid++;\r
+\r
+ insert_ref(curr_mem_odatp, refid);\r
+\r
+ /* If current odatp on stack has a link, then we need to make our own link. just set the vdat_idx */\r
+ if(CURR_SS_ODATP()->vdat_idx = 0)\r
+ { //alloc a link\r
+ linkp = alloc_link();\r
+ linkp->type = CURR_SS_ODATP()->linkp->type;\r
+ linkp->dest_odatp = CURR_SS_ODATP();\r
+ linkp->dest_refid = refid;\r
+ linkp->link_t.mlink.src_refid = CURR_SS_ODATP()->linkp->link_t.mlink.src_refid;\r
+\r
+ /* Copy the animation name of the vlink*/\r
+ name_u8_cpy(&linkp->link_t.vlink.src_animname, &CURR_SS_ODATP()->linkp->link_t.vlink.src_animname);\r
+ /* Copy the namelist of the vlink*/\r
+ for(i = 0; i < MAX_DEPTH; i++)\r
+ name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &CURR_SS_ODATP()->linkp->link_t.vlink.src_namelist[i]);\r
+ }\r
+ else\r
+ curr_mem_odatp->vdat_idx = CURR_SS_ODATP()->vdat_idx;\r
+\r
+ \r
+ \r
+ \r
+}\r
+ \r
+\r
+/* 11/22 Each vdat has a multiple models. Each model has 8 framesheets, one in each\r
+ direction, that create a spritesheet. Inserting framesheets into the correct \r
+ model is just a matter of checking whether or not the last models name matches\r
+\r
+ the current one. We can never get a framesheet that is for the same model before \r
+ AND after some other model, due to alphasorting of the files in each directory */\r
+void\r
+insert_framesheet\r
+( model_name, direction, height, width, refid, filepath )\r
+ struct name* model_name;\r
+ int direction, height, width, refid;\r
+ uint8_t* filepath;\r
+{ struct vdat* curr_vdatp;\r
+ struct model* curr_modelp;\r
+ static struct name last_model_name[32];\r
+\r
+ \r
+ curr_vdatp = curr_vdat();\r
+\r
+ /* If the model name changed, that means there are no more\r
+ framesheets for that model to be processed, a guaruntee we make\r
+ b/c the filenames are alphabetically sorted */\r
+ if(!name_u8_cmp(last_model_name, model_name))\r
+ { if(curr_vdatp->num_models)\r
+ curr_vdatp->num_models++;\r
+ num_models++; // total number of models\r
+ }\r
+ \r
+\r
+ if(CURR_SS_ODATP()->refid == 0)\r
+ { if(!refid)\r
+ refid = ss_refid++;\r
+ insert_ref(CURR_SS_ODATP(), refid);//given a odatp and a refid, insert the odatp into the ref_buf.\r
+ //push ref into ref_buf. \r
+ } \r
+ else\r
+ printf("error: redefining a previously set refid\n");\r
+ \r
+ curr_modelp = curr_model(); \r
+\r
+ name_u8_cpy(&curr_modelp->name, model_name);\r
+ curr_modelp->spritesheet[direction].height = height;\r
+ curr_modelp->spritesheet[direction].width = width;\r
+\r
+ name_u8_cpy(last_model_name, model_name);\r
+\r
+ \r
+}\r
+\r
+\r
+\r
+//src_path is stored in link_namelist\r
+void\r
+insert_mlink\r
+( src_mapname, src_refid)\r
+ struct name* src_mapname;\r
+ int src_refid;\r
+{ struct link* linkp;\r
+ int i;\r
+\r
+ linkp = alloc_link();\r
+\r
+ /* set type */\r
+ linkp->type = 3;\r
+ /* set the name of the src map for the link, if a name exists */\r
+ if(src_mapname)\r
+ name_u8_cpy(&linkp->link_t.mlink.src_mapname, src_mapname);\r
+ /* Set the source ref id of the link */\r
+ linkp->link_t.mlink.src_refid = src_refid;\r
+ /* Copy the entire namelist of the link, if it exists */\r
+ for(i = 0; i < link_numnames; i--) //TODO MAX_DEPTH -> link_namelist_num??\r
+ { name_u8_cpy(&linkp->link_t.mlink.src_namelist[i], &link_namelist[i]);\r
+ name_u8_set(&link_namelist[i], (ucs4_t) 0);\r
+ }\r
+ link_numnames = 0;\r
+ \r
+ linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack\r
+\r
+}\r
+\r
+void\r
+insert_link_name\r
+( name )\r
+ struct name* name;\r
+{ \r
+ //Push name onto current namelist, set the set_namelist.\r
+ name_u8_cpy(&link_namelist[link_numnames++], name);\r
+ \r
+}\r
+\r
+/* Nearly identical to mlink */\r
+void\r
+insert_vlink\r
+( src_animname, src_refid ) \r
+ struct name* src_animname;\r
+ int src_refid;\r
+{ struct link* linkp;\r
+ int i;\r
+\r
+ linkp = alloc_link();\r
+\r
+ /* set type */\r
+ linkp->type = 2;\r
+ \r
+ /* set the name of the src animname for the link, if a name exists */\r
+ if(src_animname)\r
+ name_u8_cpy(&linkp->link_t.vlink.src_animname, src_animname);\r
+ \r
+ /* Set the source ref id of the link */\r
+ linkp->link_t.mlink.src_refid = src_refid;\r
+ \r
+ /* Copy the entire namelist of the link, if it exists */\r
+ for(i = 0; i < link_numnames; i++) //TODO MAX_DEPTH -> link_namelist_num??\r
+ { name_u8_cpy(&linkp->link_t.vlink.src_namelist[i], &link_namelist[i]);\r
+ name_u8_set(&link_namelist[i], (ucs4_t) 0);//set to null for next link_namelist\r
+ }\r
+ \r
+ linkp->dest_odatp = CURR_SS_ODATP();//current odat on set_stack\r
+\r
+}\r
+\r
+\r
+/* TODO: Do we really need to store the prev/next pointer? iterating through the \r
+ ref_buf could be achieved by iterating until the num_refs anyway. */\r
+void\r
+insert_ref\r
+( odatp, refid )\r
+ struct odat* odatp;\r
+ int refid;\r
+{ struct ref* curr_refp;\r
+ struct ref* prev_refp;\r
+\r
+ curr_refp = alloc_ref();\r
+ prev_refp = prev_ref();\r
+\r
+ prev_refp->nextref = curr_refp;\r
+ curr_refp->lastref = prev_refp;\r
+\r
+ curr_refp->odatp = odatp;\r
+ curr_refp->refid = refid;\r
+\r
+ if(refid % 16)\r
+ { POST_ALLOC();\r
+ CURRENT_POST()->refid = refid;\r
+ CURRENT_POST()->odatp = odatp;\r
+ }\r
+ \r
+ \r
+ \r
+}\r
+\r
+void\r
+insert_vdat\r
+()\r
+{ struct odat* curr_ss_odatp;\r
+ struct vdat* curr_vdatp;\r
+ \r
+ curr_vdatp->creator = curr_ss_odatp;\r
+ curr_ss_odatp->vdat_idx = num_vdats;\r
+ curr_ss_odatp->vdatp = curr_vdatp;\r
+ alloc_vdat();\r
+}\r
+\r
+void\r
+insert_refid_statement\r
+( refid )\r
+ int refid;\r
+{ CURR_SS_ODATP()->refid = refid;\r
+}\r
+#if 0\r
+\r
+\r
+/* Called in the reduction of a set. While both odats (eles and sets)\r
+ have identical label terminals, we are unable to give a single grammatical rule\r
+ for both due to how we allocate odats in the odat buf. Due to the\r
+ nature of bottom up parsing, the set label is recognized first, and then the\r
+ sets elements are recognized. This means that after we have processed the sets elemenets,\r
+ the curr_odat is going to be the last element and NOT the set that was first allocated.\r
+ To get around this, we create a global variable set_odatp that will store the pointer\r
+ to the odat when it is first allocated (in insert_set_label()) so that insert_set() can\r
+ have access to it. Curr set points the sets representation in the cdat, curr_set_odatp\r
+ points to the sets representation as an odat*/\r
+\r
+//TODO: Add insert_set_ref()\r
+//TODO: Is this the correct allocation scheme? No do the one ken suggested\r
+void\r
+insert_s_name\r
+( struct name* name\r
+)\r
+{\r
+\r
+ struct set* curr_setp;\r
+\r
+ curr_setp = curr_set();\r
+ curr_set_odatp = alloc_odat();\r
+\r
+ u8_cpy(curr_set_odatp->name, name, 32);\r
+ u8_cpy(curr_setp->name, name, 32);\r
+ curr_set_odatp->parent_odatp = NULL;\r
+ \r
+\r
+}\r
+\r
+/* Inserting a olink instead of a set. Set is really just a placeholder\r
+ for another set. Allocate the memory for the set so taht it can be populated*/\r
+void\r
+insert_set_olink\r
+( int refid\r
+)\r
+{\r
+ struct set* curr_setp;\r
+\r
+ curr_setp = curr_set();\r
+\r
+ curr_setp->refid = refid;\r
+\r
+}\r
+\r
+void\r
+insert_set_vlink\r
+( int refid,\r
+ uint8_t* anim_name\r
+)\r
+{\r
+ struct cdat* curr_cdatp;\r
+ struct odat* curr_odatp;\r
+ struct link* curr_linkp;\r
+\r
+\r
+ curr_cdatp = curr_cdat();\r
+ curr_odatp = curr_odat();\r
+ curr_linkp = alloc_link();\r
+\r
+ /* Insert vlink into link_stack so that it gets processed at\r
+ output time */\r
+ curr_linkp->type = 2;\r
+ /* Store the target odat information*/\r
+ curr_linkp->link_t.vlink.refid = refid;\r
+ u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32);\r
+ /* Store the linking odat/cdat information */\r
+ curr_linkp->classp = curr_cdatp;\r
+ curr_linkp->odatp = curr_odatp;\r
+ curr_linkp->set_idx = curr_cdatp->num_sets;\r
+ // curr_linkp->ele_idx = -1;\r
+\r
+}\r
+\r
+/* Svlinks dont have animation names */\r
+void\r
+insert_set_svlink\r
+( int refid \r
+)\r
+{\r
+ struct cdat* curr_cdatp;\r
+ struct link* curr_linkp;\r
+\r
+ curr_cdatp = curr_cdat();\r
+ curr_linkp = alloc_link();\r
+\r
+ /* Insert svlink into link_stack so that it gets processed at\r
+ output time */\r
+ curr_linkp->type = 3;\r
+ curr_linkp->classp = curr_cdatp;\r
+ curr_linkp->set_idx = curr_cdatp->num_sets;\r
+ // curr_linkp->ele_idx = -1;\r
+ curr_linkp->link_t.svlink.refid = refid;\r
+\r
+}\r
+\r
+/* At the point of reducing to a set, most of the\r
+ sets odat information has already been populated\r
+ during the reduction of its right hand side\r
+ non terminals (hitbox, root, quad_list). */\r
+void\r
+insert_set\r
+()\r
+{ int refid;\r
+ struct odat* curr_odatp;\r
+ struct cdat* curr_cdatp;\r
+ struct set* curr_setp;\r
+ struct ref* prev_refp;\r
+ struct ref* curr_refp;\r
+ struct vdat* curr_vdatp;\r
+\r
+ curr_odatp = curr_set_odatp; //allocated at insert_set_label\r
+ curr_cdatp = curr_cdat();\r
+ curr_setp = curr_set();\r
+ prev_refp = curr_ref();\r
+ curr_refp = alloc_ref();\r
+ curr_vdatp = curr_vdat();\r
+\r
+ curr_vdatp->creator = curr_set_odatp;\r
+\r
+ curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx?\r
+ u8_cpy(curr_setp->name, curr_odatp->name, 32);\r
+ curr_cdatp->num_sets++;\r
+\r
+ curr_odatp->cdat_idx = curr_cdatp->idx;\r
+ curr_odatp->refp = curr_refp;\r
+\r
+ refid = curr_setp->refid; // refid set by insert_set_label(name, refid)\r
+\r
+ curr_refp->refid = refid;\r
+ curr_refp->lastref = prev_refp;\r
+ curr_refp->odatp = curr_odatp;\r
+ prev_refp->nextref = curr_refp;\r
+\r
+\r
+\r
+}\r
+/* Created as a seperate function, instead of setting the ODATS vdat_id and\r
+ calling inc_vdat() inside of insert_set(), to account for the set reduction\r
+ where a vdat is not created (o/v/svlinks). */\r
+void\r
+insert_set_vdatid\r
+()\r
+{\r
+ struct vdat* curr_vdatp;\r
+\r
+ curr_vdatp = curr_vdat();\r
+\r
+ curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks\r
+ curr_set_odatp->vdatp = curr_vdatp;\r
+ curr_set_odatp = NULL; //This sets odat shouldnt be modified after populating odats vdat info\r
+}\r
+\r
+/* Populates the odat name and refid for odat, allocate the odat here for the rest of\r
+ the functions to use via curr_odat(). */\r
+void\r
+insert_ele_label\r
+( uint8_t* name,\r
+ int refid\r
+)\r
+{\r
+ struct odat* curr_odatp;\r
+\r
+ curr_odatp = alloc_odat();\r
+\r
+ u8_cpy(curr_odatp->name, name, 32);\r
+ curr_odatp->map[0] = 0;\r
+\r
+ if(refid != -1)\r
+ curr_odatp->refid = refid;\r
+ else\r
+ curr_odatp->refid = ss_refid++;\r
+\r
+}\r
+\r
+/* We don't make an odat here, at output time we will resolve\r
+ the refid to the corresponding odat. */\r
+void\r
+insert_ele_olink\r
+( int refid\r
+)\r
+{\r
+ /* Do nothing because we already know the refid that\r
+ the odat needs for this element (in the quad_file) */\r
+}\r
+\r
+void\r
+insert_ele_vlink\r
+( int refid,\r
+ uint8_t* anim_name\r
+)\r
+{\r
+ struct cdat* curr_cdatp;\r
+ struct set* curr_setp;\r
+ struct link* curr_linkp;\r
+\r
+ curr_cdatp = curr_cdat();\r
+ curr_setp = curr_set();\r
+ curr_linkp = alloc_link();\r
+\r
+ /* Insert vlink into link_stack so that it gets processed at\r
+ output time */\r
+ curr_linkp->classp = curr_cdatp;\r
+ curr_linkp->type = 2;\r
+ curr_linkp->set_idx = curr_cdatp->num_sets;\r
+ //curr_linkp->ele_idx = curr_setp->num_ele;\r
+ curr_linkp->link_t.vlink.refid = refid;\r
+ u8_cpy(curr_linkp->link_t.vlink.anim_name, anim_name, 32);\r
+\r
+}\r
+\r
+void\r
+insert_ele_svlink\r
+( int refid\r
+)\r
+{\r
+ struct cdat* curr_cdatp;\r
+ struct set* curr_setp;\r
+ struct link* curr_linkp;\r
+\r
+ curr_cdatp = curr_cdat();\r
+ curr_setp = curr_set();\r
+ curr_linkp = alloc_link();\r
+\r
+ curr_linkp->classp = curr_cdatp;\r
+ curr_linkp->type = 3;\r
+\r
+ //curr_linkp->ele_idx = curr_setp->num_ele;\r
+ curr_linkp->link_t.svlink.refid = refid;\r
+\r
+\r
+}\r
+\r
+//Insert element into odat_buf and cdatpages\r
+void\r
+insert_ele()\r
+{\r
+ int refid;\r
+ struct cdat* curr_cdatp;\r
+ struct odat* curr_odatp;\r
+ struct vdat* curr_vdatp;\r
+ struct set* curr_setp;\r
+ struct ele* curr_elep;\r
+ struct ref* curr_refp;\r
+ struct ref* prev_refp;\r
+\r
+\r
+ curr_odatp = curr_odat(); //malloced @ insert_ele_label\r
+ curr_vdatp = curr_vdat();\r
+ curr_setp = curr_set();\r
+ prev_refp = curr_ref();\r
+ curr_refp = alloc_ref();\r
+\r
+ curr_vdatp->creator = curr_odatp;\r
+\r
+ /* Populate odat for ele */\r
+ curr_odatp->cdat_idx = curr_cdatp->idx;\r
+ curr_odatp->refp = curr_refp;\r
+ curr_odatp->parent_odatp = curr_set_odatp;\r
+\r
+ refid = curr_odatp->refid;\r
+\r
+ curr_refp->refid = refid;\r
+ curr_refp->lastref = prev_refp;\r
+ curr_refp->odatp = curr_odatp;\r
+ prev_refp->nextref = curr_refp;\r
+\r
+}\r
+\r
+void\r
+insert_ele_vdatid\r
+()\r
+{ struct odat* curr_odatp;\r
+ curr_odatp = curr_odat();\r
+ curr_odatp->vdat_id = num_vdats;\r
+}\r
+\r
+\r
+\r
+#endif\r
+\r
+\r
+ \r
+\r
+/* void */\r
+/* insert_quad */\r
+/* ( int x, int y, int z, int refid */\r
+/* ) */\r
+/* { */\r
+/* struct quad* curr_quadp; */\r
+\r
+/* curr_quadp = curr_quad(); */\r
+\r
+/* curr_quadp->x = x; */\r
+/* curr_quadp->y = y; */\r
+/* curr_quadp->z = z; */\r
+/* curr_quadp->refid = refid; */\r
+ \r
+\r
+\r
+/* } */\r
+\r
+/* /\* serting the hitbox into the set */\r
+/* odat. Elements that don't have */\r
+/* a hitbox will use the sets root. *\/ */\r
+/* void */\r
+/* insert_hitbox */\r
+/* ( int hitbox */\r
+/* ) */\r
+/* { struct odat* curr_odatp; */\r
+\r
+/* curr_odatp = curr_odat(); */\r
+/* curr_odatp->hitbox = hitbox; */\r
+/* } */\r
+\r
+/* /\* Inserting the root into the set */\r
+/* odat. Elements that don't have */\r
+/* a root will use the sets root. *\/ */\r
+/* void */\r
+/* insert_root */\r
+/* ( int x, */\r
+/* int y, */\r
+/* int z */\r
+/* ) */\r
+/* { struct odat* curr_odatp; */\r
+\r
+/* curr_odatp = curr_odat(); */\r
+/* curr_odatp->root.x = x; */\r
+/* curr_odatp->root.y = y; */\r
+/* curr_odatp->root.z = z; */\r
+/* } */\r
+\r
+\r
+\r
+\r
+/* void */\r
+/* insert_frame_pointer */\r
+/* ( uint8_t direction, */\r
+/* void* frame */\r
+/* ) */\r
+/* { struct model* curr_modelp; */\r
+\r
+/* curr_modelp = curr_model(); */\r
+\r
+/* curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame; */\r
+/* } */\r
+\r
--- /dev/null
+\r
+\r
+/*!@file\r
+\brief Intermediate Representation (IR) between Directory Structure and Engine Input\r
+\details The IR serves as a storage structure that is populated during the\r
+ parsing of the input directory structure. After parsing is complete,\r
+ the IR will be condensed (removed of excess allocated space) and then\r
+ output as the input for the engine. In this file we describe the semantic actions\r
+ that are called at each step, and the memory buffers that they populate.\r
+ See parser.y for the description on how the input grammar is constructed,\r
+ and where/when semantic actions are called.\r
+ TODO: or just write it here.\r
+\author Jordan Lavatai\r
+\date Aug 2016\r
+----------------------------------------------------------------------------*/\r
+\r
--- /dev/null
+/*!@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 <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+/* Posix */
+#include <unistd.h>
+#include <unitypes.h>
+#include <unistr.h>
+#include <uniconv.h>
+#include <uniname.h>
+#include <unistdio.h>
+#include <stdlib.h>
+#include <limits.h> //realpath, NAME_MAX, FPATH_MAX
+#include <dirent.h>
+
+/* 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); */
--- /dev/null
+
+#line 1 "lexer_fsm.rl"
+#include <stdio.h>
+#include <stdint.h>
+#include <apc/parser.tab.h>
+#include <unistdio.h>
+#include <unistr.h>
+
+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; */
+
+
+/* } */
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <apc/parser.tab.h>
+#include "apc.h"
+#include <unistdio.h>
+#include <unistr.h>
+
+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; */
+
+
+/* } */
--- /dev/null
+/* Ragel State Machine for tokenizing text */\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <apc/apc.h>\r
+#include <apc/parser.tab.h>\r
+\r
+\r
+int ipow(int, int);\r
+int ttov(const uint8_t* , int);\r
+uint64_t ttor(const uint8_t* , int);\r
+struct name* tton(const uint8_t* , int);\r
+\r
+\r
+#define MAX_TOK_LEN 64\r
+#define MAX_TOKENS 16\r
+#define MAX_STR_SIZE (MAX_TOK_LEN * MAX_TOKENS)\r
+\r
+int ipow(int base, int exp)\r
+{\r
+ int result = 1;\r
+ while (exp)\r
+ {\r
+ if (exp & 1)\r
+ result = result * base;\r
+ exp = exp >> 1;\r
+ base *= base;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* Token to Value */\r
+int ttov(const uint8_t* str, int len)\r
+{\r
+ int i, val = 0;\r
+\r
+ for (i = 0; i < len; i++)\r
+ {\r
+ val += ((str[len - (i + 1)] - '0') * ipow(10,i));\r
+ }\r
+\r
+ return val;\r
+}\r
+\r
+uint64_t ttor(const uint8_t* str, int len)\r
+{\r
+ int i;\r
+ uint64_t num = 0;\r
+\r
+ for (i = 0; i < len; i++)\r
+ {\r
+ num += ((str[len - (i + 1)] - '0') * ipow(10,i));\r
+ }\r
+\r
+ return num;\r
+}\r
+\r
+struct name* tton(const uint8_t* str, int len)\r
+{\r
+ int i;\r
+ struct name* namep;\r
+\r
+ namep = (name*) malloc(MAX_NAME_LEN);\r
+ for(i = 0; i < MAX_NAME_LEN - 1; i++)\r
+ namep[i] = str[i];\r
+ namep[i] = '\0';\r
+\r
+ return namep;\r
+}\r
--- /dev/null
+/* Functions for operating on names */
+#include "apc.h"
+#include <unistr.h>
+
+
+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);
+}
--- /dev/null
+
+/* 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 *\/ */
+
+
+/* } */
--- /dev/null
+/* Asset Package Compiler */
+%code requires{
+ #include <stdint.h>
+ #include <unitypes.h>
+ #include "apc.h"
+}
+%{
+ #include <stdio.h>
+ #include <string.h>
+ #include <dirent.h>
+
+ 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 <val> NUM
+%token <str> PATH
+%token <ref> REF
+%token <val> HEIGHT
+%token <val> WIDTH
+%token <val> D
+%token <name> NAME
+%token SHIFT
+//nonterminals
+%type <int> 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);
+}
--- /dev/null
+#!/bin/bash
+
+ragel -V -p lexer_fsm.rl | dot -Tpng -o ragraph.png
--- /dev/null
+/*!@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 <stdio.h> //print
+#include <string.h> //strncmp
+#include <errno.h> //errno
+#include <ctype.h> //tolower
+/* Posix */
+#include <err.h> //warnx
+#include <stdlib.h> //exit
+#include <unistd.h> //chdir
+#include <dirent.h> //opendir
+#include <unistr.h> //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();
+}