apc init
authorJordan <jordanlavatai@gmail.com>
Thu, 15 Dec 2016 19:43:37 +0000 (11:43 -0800)
committerJordan <jordanlavatai@gmail.com>
Thu, 15 Dec 2016 19:43:37 +0000 (11:43 -0800)
24 files changed:
.gdb/ir.o [new file with mode: 0644]
.gdb/irmem.o [new file with mode: 0644]
.gdb/lexer.o [new file with mode: 0644]
.gdb/lexer_fsm.o [new file with mode: 0644]
.gdb/lexer_lex.o [new file with mode: 0644]
.gdb/output.o [new file with mode: 0644]
.gdb/parser-save.tab.o [new file with mode: 0644]
.gdb/parser.tab.o [new file with mode: 0644]
.gdb/scanner.o [new file with mode: 0644]
.gitignore [new file with mode: 0644]
apc.h [new file with mode: 0644]
ir.c [new file with mode: 0755]
ir.h [new file with mode: 0755]
lexer.c [new file with mode: 0644]
lexer_fsm.c [new file with mode: 0644]
lexer_fsm.rl [new file with mode: 0644]
lexer_lex.rl [new file with mode: 0755]
main.o [new file with mode: 0644]
name.c [new file with mode: 0644]
output.c [new file with mode: 0644]
parser.y [new file with mode: 0644]
ragraph [new file with mode: 0755]
ragraph.png [new file with mode: 0644]
scanner.c [new file with mode: 0644]

diff --git a/.gdb/ir.o b/.gdb/ir.o
new file mode 100644 (file)
index 0000000..ce9ee2e
Binary files /dev/null and b/.gdb/ir.o differ
diff --git a/.gdb/irmem.o b/.gdb/irmem.o
new file mode 100644 (file)
index 0000000..7822d5f
Binary files /dev/null and b/.gdb/irmem.o differ
diff --git a/.gdb/lexer.o b/.gdb/lexer.o
new file mode 100644 (file)
index 0000000..5833e5a
Binary files /dev/null and b/.gdb/lexer.o differ
diff --git a/.gdb/lexer_fsm.o b/.gdb/lexer_fsm.o
new file mode 100644 (file)
index 0000000..0ca1af2
Binary files /dev/null and b/.gdb/lexer_fsm.o differ
diff --git a/.gdb/lexer_lex.o b/.gdb/lexer_lex.o
new file mode 100644 (file)
index 0000000..a673dcf
Binary files /dev/null and b/.gdb/lexer_lex.o differ
diff --git a/.gdb/output.o b/.gdb/output.o
new file mode 100644 (file)
index 0000000..90e6880
Binary files /dev/null and b/.gdb/output.o differ
diff --git a/.gdb/parser-save.tab.o b/.gdb/parser-save.tab.o
new file mode 100644 (file)
index 0000000..4b63af1
Binary files /dev/null and b/.gdb/parser-save.tab.o differ
diff --git a/.gdb/parser.tab.o b/.gdb/parser.tab.o
new file mode 100644 (file)
index 0000000..d6f43c4
Binary files /dev/null and b/.gdb/parser.tab.o differ
diff --git a/.gdb/scanner.o b/.gdb/scanner.o
new file mode 100644 (file)
index 0000000..595a41c
Binary files /dev/null and b/.gdb/scanner.o differ
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..86a7b85
--- /dev/null
@@ -0,0 +1,3 @@
+*.tab.c
+*.tab.h
+lexer_lex.c
diff --git a/apc.h b/apc.h
new file mode 100644 (file)
index 0000000..6a8df1e
--- /dev/null
+++ b/apc.h
@@ -0,0 +1,33 @@
+#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];
+};
diff --git a/ir.c b/ir.c
new file mode 100755 (executable)
index 0000000..8652ddc
--- /dev/null
+++ b/ir.c
@@ -0,0 +1,1336 @@
+/*!@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
diff --git a/ir.h b/ir.h
new file mode 100755 (executable)
index 0000000..0d271b1
--- /dev/null
+++ b/ir.h
@@ -0,0 +1,16 @@
+\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
diff --git a/lexer.c b/lexer.c
new file mode 100644 (file)
index 0000000..1550db9
--- /dev/null
+++ b/lexer.c
@@ -0,0 +1,518 @@
+/*!@file
+  \brief   lexical analyzer implementation for APC
+  \details The lexer manages two FIFO stacks.  One for maintaining tokens, the
+           other for maintaining a list of files to be scanned.  During
+           execution, the lexer will return a token from its token queue if any
+           are present.  If not, the lexer will will pop an element from its
+           file queue to 'scanner' to be tokenized.  If the file queue is empty,
+           the lexer will instead call 'parsedir' to traverse the directory tree
+           and tokenize the results.  If 'parsedir' does not generate any new
+           tokens, we are done.
+  \author  Jordan Lavatai
+  \date    Aug 2016
+  ----------------------------------------------------------------------------*/
+/* Standard */
+#include <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); */
diff --git a/lexer_fsm.c b/lexer_fsm.c
new file mode 100644 (file)
index 0000000..1ae11bb
--- /dev/null
@@ -0,0 +1,1038 @@
+
+#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; */
+  
+
+/* } */
diff --git a/lexer_fsm.rl b/lexer_fsm.rl
new file mode 100644 (file)
index 0000000..344ffdb
--- /dev/null
@@ -0,0 +1,369 @@
+#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; */
+  
+
+/* } */
diff --git a/lexer_lex.rl b/lexer_lex.rl
new file mode 100755 (executable)
index 0000000..5e395d0
--- /dev/null
@@ -0,0 +1,69 @@
+/* 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
diff --git a/main.o b/main.o
new file mode 100644 (file)
index 0000000..db32a98
Binary files /dev/null and b/main.o differ
diff --git a/name.c b/name.c
new file mode 100644 (file)
index 0000000..612426c
--- /dev/null
+++ b/name.c
@@ -0,0 +1,41 @@
+/* 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);
+}
diff --git a/output.c b/output.c
new file mode 100644 (file)
index 0000000..4513d64
--- /dev/null
+++ b/output.c
@@ -0,0 +1,39 @@
+
+/* void */
+/* condense() */
+/* { */
+/*   FILE *vp, *op, *cp; */
+/*   int v, m; */
+/*   int num_models; */
+
+/*   vp = fopen("vdat_output", "w+"); */
+/*   if(!vp) */
+/*     perror("vdat_output failed to open\n"); */
+
+/*   op = fopen("odat_output", "w+"); */
+/*   if(!op) */
+/*     perror("odat_output failed to open\n"); */
+
+/*   cp = fopen("cdat_output", "w+"); */
+/*   if(!cp) */
+/*     perror("cdat_output failed to open\n"); */
+
+
+
+/*   /\* fwrite vdat *\/ */
+/*   for(v = 0; v <= vbi; v++) */
+/*     { */
+/*       num_models = vdat_buf[v].num_models; //data duplication for caching */
+/*       for(m = 0; m <= num_models; m++) */
+/*         { */
+            
+/*         } */
+/*     } */
+
+/*   /\* fwrite odat *\/ */
+/*   /\* Convert ref_list to actual offset *\/ */
+
+/*   /\* fwrite cdat *\/ */
+
+
+/* } */
diff --git a/parser.y b/parser.y
new file mode 100644 (file)
index 0000000..6fe0969
--- /dev/null
+++ b/parser.y
@@ -0,0 +1,177 @@
+/* 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);
+}
diff --git a/ragraph b/ragraph
new file mode 100755 (executable)
index 0000000..cc9c55f
--- /dev/null
+++ b/ragraph
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+ragel -V -p lexer_fsm.rl | dot -Tpng -o ragraph.png
diff --git a/ragraph.png b/ragraph.png
new file mode 100644 (file)
index 0000000..e8a831f
Binary files /dev/null and b/ragraph.png differ
diff --git a/scanner.c b/scanner.c
new file mode 100644 (file)
index 0000000..55245af
--- /dev/null
+++ b/scanner.c
@@ -0,0 +1,255 @@
+/*!@file
+  \brief   APC Directory Scanner
+  \details This hand-written parser/scanner traverses a directory tree and
+           tokenizes elements of the structure which correspond to APC grammar.
+           The parser is implemented as a 2D stack which populates a list of
+           child directories at each depth, handling only the leaf nodes
+           (regular files) of the directory open at the current depth to
+           conserve memory and speed up traversal.
+           The scanner works with the lexer to lexically analyze text, and
+           assumes the existence of an external 'lex' function
+  \author  Jordan Lavatai
+  \date    Aug 2016
+  ----------------------------------------------------------------------------*/
+/* Standard */
+#include <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();
+}