wip
authorken <ken@mihrtec.com>
Thu, 5 Jan 2017 17:42:53 +0000 (09:42 -0800)
committerken <ken@mihrtec.com>
Thu, 5 Jan 2017 17:42:53 +0000 (09:42 -0800)
src/apc.c
src/apc.h
src/ir.c
src/ir.h
src/parser.y
src/scanner.c

index cea3847..3b5774f 100644 (file)
--- a/src/apc.c
+++ b/src/apc.c
 #include <string.h> //strndupa
 /* Posix */
 #include <stdlib.h> //exit
 #include <string.h> //strndupa
 /* Posix */
 #include <stdlib.h> //exit
-#include <unistd.h> //getopt
+#include <unistd.h> //getopt, sysconf
 /* Internal */
 #include "parser.tab.h" //bison
 
 /* Internal */
 #include "parser.tab.h" //bison
 
+#define DEFAULT_PAGESIZE 4096
 const char* cargs['Z'] = {0};
 const char* cargs['Z'] = {0};
+const long  sys_pagesize;
 
 int main(int, char*[]);
 
 
 int main(int, char*[]);
 
@@ -76,6 +78,8 @@ int main
       printf(USAGE_LONG);
       exit(EXIT_SUCCESS);
   }
       printf(USAGE_LONG);
       exit(EXIT_SUCCESS);
   }
+  if ((sys_pagesize = sysconf(_SC_PAGESIZE)) == 0)
+    sys_pagesize = DEFAULT_PAGESIZE;
   if (lexer_init() || ir_init())
     { perror("init");
       exit(EXIT_FAILURE);
   if (lexer_init() || ir_init())
     { perror("init");
       exit(EXIT_FAILURE);
index 6a8df1e..efed4d4 100644 (file)
--- a/src/apc.h
+++ b/src/apc.h
@@ -1,6 +1,5 @@
-#include <stdint.h>
-#include <unitypes.h>
-#include <limits.h>
+#ifndef _APC_H_
+#define _APC_H_
 
 //ir.h
 #define BUF_SIZE 256
 
 //ir.h
 #define BUF_SIZE 256
@@ -26,8 +25,4 @@
 #define FNAME_MAX 1024
 #define FPATH_MAX 8192
 
 #define FNAME_MAX 1024
 #define FPATH_MAX 8192
 
-
-struct name
-{
-  uint8_t name[MAX_NAME_LEN];
-};
+#endif //_APC_H_
index 4325813..49480ab 100644 (file)
--- a/src/ir.c
+++ b/src/ir.c
   \author  Jordan Lavatai\r
   \date    Aug 2016\r
   ----------------------------------------------------------------------------*/\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
+/* Standard */\r
+#include <stdlib.h> //exit, malloc\r
+#include <stdio.h>  //print\r
+#include <stdarg.h> //va_args\r
 #include <stdint.h> //uint64_t\r
 #include <stdint.h> //uint64_t\r
-#include <string.h> //memset\r
-#include <unistd.h> //u8_* functions\r
+#include <string.h> //memset, str*\r
+/* Unicode */\r
+#include <unistd.h>   //u8_* functions\r
+#include <unitypes.h> //uint8_t as a char\r
+#include <unistr.h>   //u32_cpy\r
+/* Local */\r
 #include "apc.h"\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(void);\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_refid(int);\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
-\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
-\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
-struct set {\r
-  int cdat_idx;\r
-  int num_sets;\r
-  struct set* set_list[MAX_SETS];\r
-};\r
-\r
-struct ref {\r
-  struct ref* nextref;\r
-  struct ref* lastref;\r
-  struct odat* odatp;\r
-  int refid; //0xFFFFFF->digit\r
-};\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
+#include "ir.h"\r
+/* Public */\r
+int      ir_init(void);\r
+int      ir_linker(void);\r
+int      ir_condenser(void);\r
+#if 0\r
+ir_class ir_class_findchild(ir_class, uint8_t*);\r
+ir_set   ir_class_rootset(ir_class);\r
+ir_class ir_class_nextsib(ir_class);\r
+ir_class ir_class_nextchild(ir_class);\r
+uint8_t* ir_class_name(ir_class);\r
+ir_set   ir_class_findset(ir_class,uint8_t*);\r
+ir_set   ir_set_findchild(ir_set, uint8_t*);\r
+ir_set   ir_set_nextsib(ir_set);\r
+ir_set   ir_set_nextchild(ir_set);\r
+ir_set   ir_set_findref(long long);\r
+uint8_t* ir_set_name(ir_set);\r
+#endif\r
+/* Private */\r
+static inline\r
+uint8_t bytes_identical(uint8_t*,uint8_t*);\r
+\r
+/* Enumerated types */\r
+enum dtype { FSDAT, MSDAT, ADAT, LDAT };\r
+enum ltype { OLINK, MLINK, VLINK, ALINK };\r
+/* Set data mem */\r
+struct sdat_header_t\r
+{ enum dtype type;\r
+  uint8_t* src_file_name;\r
+  uint8_t* data_name;\r
 };\r
 };\r
-\r
-union link_t {\r
-  struct vlink vlink;\r
-  struct mlink mlink;\r
-  struct olink olink;\r
+struct frameinfo_t\r
+{ int facing, w, h;\r
 };\r
 };\r
-\r
-\r
-/* Links are a mechanism for designers to indicate in the grammar that a odat, vdat, or map \r
-   is defined elsewhere and that the link should be replaced with the specified odat/vdat/map */ \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
+struct framedata_t\r
+{ struct sdat_header_t header;\r
+  struct frameinfo_t   frameinfo;\r
+} **framedatas;\r
+struct framebox_t\r
+{ struct framedata_t framesheets[FACE_MAX];\r
+  struct framedata_t mapsheets[FACE_MAX];\r
+  uint8_t            *data_name;\r
+} **frameboxes;\r
+struct simplex_t\r
+{ struct sdat_header_t header;\r
+} **simplexes;\r
+struct link_t\r
+{ struct sdat_header_t header;\r
+  struct set_t         *src, *trg;\r
+  enum ltype           type;\r
+} **links;\r
+union sdat_t\r
+{ struct sdat_header_t header;\r
+  struct framedata_t   framesheet;\r
+  struct framedata_t   mapsheet;\r
+  struct simplex_t     audio;\r
+  struct link_t        link;\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; /* null if parent is a cdat */\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 a single direction (N,W,S,E, etc.). Framesheets\r
-   also hold the framesheet dimensions and the filepath to the png of the framesheet so the file can be opened\r
-   and the png data can be extracted. */\r
-struct framesheet {\r
-  int width;\r
-  int height;\r
-  uint8_t filepath[FPATH_MAX];\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). Currently, users can only define\r
-   framesheets in the APC grammar, which are inserted into the current model*/\r
-struct model {\r
-  struct name name;\r
-    struct framesheet spritesheet[8]; //one for each\r
-};\r
-\r
-/* Vdat: Vdats are the video data of each object. 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
-  struct model model_list[MAX_MODELS];\r
-};\r
-\r
-/* An entry on the set_stack that describes the namelist and relevant information for \r
-   the current set that is being processed in the parser. For each set name,\r
-   there is a corresponding set/odat that is created when set names are encountered. */\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
-/*  Stores the last defined set at every depth */\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
-/* 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
-struct cdat* cdat_stack[MAX_CLASSES];\r
-struct cdat** cdat_stackp;\r
-\r
-\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
-\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
-struct set*\r
-curr_cdat_set \r
-()\r
-{\r
-  return CURRENT_SET();\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
-( 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
-\r
-void\r
-insert_set_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
-/* Called at the last name of a sets namelist. Inserts the set namelist \r
-   onto the set_stack at the appropriate depth i.e. the number of names in\r
-   the namelist. If each name in the namelist at every depth matches, nothing happens. For every\r
-   name on the namelist that doesnt match what is currently on the set_stack,\r
-   a new set/odat is created at the depth that it describes. E.g. a set name\r
-   of A_B_C is a depth of 3 and is represented in the set_stack as A, A_B and A_B_C. \r
-   If a new set namelist is defined, X_Y, the new set_stack will become X, X_Y. */\r
-\r
-void\r
-insert_set_namelist\r
-( struct name* name )\r
-{ int depth, nameidx, i;\r
-\r
-  insert_set_name(name);\r
-\r
\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
-             /* Every set has a vdat, but some won't be populated because the namelist that instantiated */\r
-              /* the set might not have a SS statement that populates the models of the vdat. This is ok */\r
-             /* because 1) IR is supposed to be bloated so that binary out isnt 2) this functionality */\r
-             /* preserves the assumptions that insert_framesheet() makes when it calls curr_vdat() */\r
-             alloc_vdat();\r
-           }\r
-         \r
-       }\r
-     \r
-    }\r
-\r
-  /* Set to 0 to reset for next set_namelist */\r
-  set_numnames = 0;\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 odats that 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
-( struct name* name, int direction, int height, int width, int refid, uint8_t* filepath )\r
-{ int i;\r
-  struct odat* curr_map_odatp; //pointer to odat in odat_buf\r
-  struct set* curr_map_setp; //pointer to set in set_buf\r
-  struct link* linkp;\r
-\r
-  curr_map_odatp = alloc_odat();\r
-  curr_map_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_map_odatp->parent_odatp = CURR_SS_ODATP(); \r
-\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_map_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_map_odatp->ismap = 1;\r
-  /* set odat and set name */\r
-  name_u8_cpy(&curr_map_odatp->name, name);\r
-\r
-  /* set cdat idx values for both set and odat */\r
-  curr_map_setp->cdat_idx = num_cdats;\r
-\r
-  /* Insert map information into the odats map */\r
-  curr_map_odatp->map.height = height;\r
-  curr_map_odatp->map.width = width;\r
-  u8_stpncpy(curr_map_odatp->map.filepath, filepath, FPATH_MAX);\r
-\r
-\r
-  /* Generate refid if needed, put into ref_buf */\r
-  if(!refid)\r
-    refid = ss_refid++;\r
-\r
-  insert_ref(curr_map_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
-    { 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_map_odatp->vdat_idx = CURR_SS_ODATP()->vdat_idx;\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
-   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
-( struct name* model_name, int direction, int height, int width, int refid, uint8_t* filepath )\r
-{ struct vdat* curr_vdatp;\r
-  struct model* curr_modelp;\r
-  static struct name last_model_name[32];\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
-    }  \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
-  u8_stpncpy(curr_modelp->spritesheet[direction].filepath, filepath, FPATH_MAX);\r
-\r
-  name_u8_cpy(last_model_name, model_name);\r
-  \r
-}\r
-\r
-\r
-void\r
-insert_mlink\r
-( struct name* src_mapname, 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
-  \r
-  /* Copy the entire namelist of the link, if it exists */\r
-  for(i = 0; i < link_numnames; i--) \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
-\r
-void\r
-insert_link_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
-\r
-/* Nearly identical to mlink */\r
-void\r
-insert_vlink\r
-( struct name* src_animname, 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++) \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
-  link_numnames = 0;\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
-( struct odat* odatp, 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
-void\r
-insert_refid\r
-( int refid )\r
-{ CURR_SS_ODATP()->refid = refid;\r
-}\r
-\r
-\r
-void\r
-insert_vdat\r
-()\r
-{ struct vdat* curr_vdatp;\r
-\r
-  curr_vdatp = curr_vdat();\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
+struct ir_class\r
+{ struct class_t *parent, *nextchild, *nextsib;\r
+  struct set_t   *root_set;\r
+  uint8_t        *name;\r
+} **classes;\r
+struct ir_set\r
+{ struct set_t      *parent, *nextchild, *nextsib;\r
+  struct class_t    *class;\r
+  uint8_t           *name;\r
+  struct framebox_t **sprites;\r
+  struct framebox_t **maps;\r
+  struct simplex_t  **audio;\r
+  struct link_t     **links;\r
+} **sets;\r
+/* Function-Like Macros */\r
+#define do_warn() do {                         \\r
+  } while (0)\r
+#define wprint(str) do {                       \\r
+    fprintf(stderr, str);                      \\r
+    do_warn();                                 \\r
+  } while (0)\r
+#define wprintf(fmt,...) do {                  \\r
+    fprintf(stderr, fmt, __VA_ARGS__);         \\r
+    do_warn();                                 \\r
+  } while (0)\r
+#define do_error() do {                                \\r
+    exit(-1);                                  \\r
+  } while (0)\r
+#define eprint(str) do {                       \\r
+    fprintf(stderr, str);                      \\r
+    do_error();                                        \\r
+  } while (0)\r
+#define eprintf(fmt,...) do {                  \\r
+    fprintf(stderr, fmt, __VA_ARGS__);         \\r
+    do_error();                                        \\r
+  } while (0)\r
+\r
+static\r
+struct ir_class root_class = { .name = &"." };\r
+\r
+/* Init */\r
+int ir_init\r
+( void )\r
+{ return 0; }\r
+\r
+/* Return a pointer to the root class */\r
+struct ir_class_t* ir_class_root\r
+( void )\r
+{ return &root_class; }\r
+\r
+/* Add a subclass to a class\r
+   Attempts to create a new subclass in the provided class, exiting with an\r
+   error if the class already exists\r
+*/\r
+#define ERR_DUPECLASS "Subclass %s of class %s already exists!", name, *class.name\r
+struct ir_class_t* ir_class_addchild\r
+( struct ir_class_t* class,\r
+  uint8_t*           name\r
+)\r
+{ struct ir_class_t* iter = *class.nextchild;\r
+  if (iter == NULL)\r
+    return *class.nextchild = class_alloc(name);\r
+ iterate:\r
+  if (bytes_identical(*iter.name, name))\r
+    { fprintf(stderr, ERR_DUPECLASS);\r
+      exit(-1);\r
+    }\r
+  if (*iter.nextsib != NULL)\r
+    { iter = *iter.nextsib;\r
+      goto iterate;\r
+    }\r
+  return *iter.nextsib = class_alloc(name);\r
+\r
+}\r
+\r
+/* Return a pointer to the parent of the provided class */\r
+struct ir_class_t* ir_class_parent\r
+( struct ir_class_t* class )\r
+{ return class.parent; }\r
+\r
+/* Add a set to a class\r
+   Attempts to create a new root set in the specified class, exiting with an\r
+   error if the set already exists\r
+*/\r
+#define ERR_DUPESET "Root set %s of class %s already exists!", name, *class.name\r
+struct ir_set_t* ir_class_addset\r
+( struct ir_class_t* class,\r
+  uint8_t*           name\r
+)\r
+{ struct ir_set_t* iter = *class.root_set;\r
+  if (iter == NULL)\r
+    return *class.root_set = set_alloc(name);\r
+ iterate:\r
+  if (bytes_identical(*iter.name, name))\r
+    { fprintf(stderr, ERR_DUPSET);\r
+      exit(-1);\r
+    }\r
+  if (*iter.nextsib != NULL)\r
+    { iter = *iter.nextsib;\r
+      goto iterate;\r
+    }\r
+  return *iter.nextsib = set_alloc(name);\r
+}\r
+\r
+struct ir_set_t* ir_set_addchild\r
+( struct ir_set_t* set,\r
+  uint8_t*         name\r
+)\r
+{ }\r
+\r
+/* Match two null-terminated bytestrings\r
+   Return 1 if the two bytestrings are identical, else 0\r
+*/\r
+static inline\r
+uint8_t bytes_identical\r
+( uint8_t* stra,\r
+  uint8_t* strb\r
+)\r
+{ while (*stra && *strb)\r
+    if (*stra++ != *strb++)\r
+      return 0;\r
+  return *stra == *strb;\r
 }\r
 }\r
index 0d271b1..1a7d1a7 100644 (file)
--- a/src/ir.h
+++ b/src/ir.h
@@ -1,16 +1,89 @@
+/*!@file\r
 \r
 \r
+\brief Intermediate Representation (IR) between Directory Structure and Engine\r
+       Input\r
 \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
 \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
+         output as the input for the engine. In this file we describe the\r
+         semantic actions that are called at each step, and the memory buffers\r
+         that they populate.  See parser.y for the description on how the input\r
+         grammar is constructed, and where/when semantic actions are called.\r
+\r
+         All input values are duplicated internally and their memory may be\r
+         freed.\r
+\r
 \author  Jordan Lavatai\r
 \date    Aug 2016\r
 ----------------------------------------------------------------------------*/\r
 \author  Jordan Lavatai\r
 \date    Aug 2016\r
 ----------------------------------------------------------------------------*/\r
+#ifndef _IR_H_\r
+#define _IR_H_\r
+#include <unitypes.h>\r
+enum frame_facing { SFACE, SWFACE, WFACE, NWFACE, NFACE, NEFACE, EFACE, SEFACE, FACING_MAX };\r
+typedef enum frame_facing    ir_facing;\r
+typedef union ir_set_data_t* ir_setdata;\r
+typedef struct ir_set_t*     ir_set;\r
+typedef struct ir_class_t*   ir_class;\r
+typedef struct ir_setld_t*   ir_setld;\r
+typedef struct ir_classld_t* ir_classld;\r
+/* Classes and Sets\r
+   Classes are rooted at a special root class, representing the current working\r
+   directory at scan-time, named ".".  The root class can always be identified\r
+   with ir_class_root, and children may be added to it.  The add series of\r
+   functions will return a reference to the newly created object, which may also\r
+   be used the root for further add functions.\r
+\r
+   E.G.\r
+   ir_class x = ir_class_root();\r
+   x = ir_class_addchild(x, "mychild");\r
+   x = ir_class_addchild(x, "child of mychild");\r
 \r
 \r
+   Sets, like classes, must be rooted.  Unlike classes, sets may be rooted on\r
+   other sets, in addition to classes.  ir_class_addset will return a set rooted\r
+   on the class specified, while ir_set_addchild will return a set rooted on the\r
+   specified set.\r
+*/\r
+ir_class   ir_class_root(void);\r
+ir_class   ir_class_addchild(ir_class, uint8_t*);\r
+ir_set     ir_class_addset(ir_class,uint8_t*);\r
+ir_set     ir_set_addchild(ir_set,uint8_t*);\r
+/* Set Data\r
+   Each set can contain up to FACING_MAX each of framesheets and mapsheets, one\r
+   sheet for each facing, per label.  Each set can contain any number of audio\r
+   objects, supplied by label.  Repeat assignment of conflicting data (e.g. two\r
+   SFACE framesheets assigned to the same set and label, or two audio objects\r
+   with the same label) causes an internal error.\r
+   Each set may also contain any number of link objects, which will be linked in\r
+   the order that they are encountered.  At link time, repeated assignments of\r
+   conflicting data cause data to be silently overwritten for those sets.  This\r
+   is an intentional side-effect of the linker.\r
+   Each setdata may have a path associated with it.  If the data depends on the\r
+   data of an associated file at that path and no path is provided, the data\r
+   will be entered null.\r
+*/\r
+void       ir_set_assign_data(ir_set,ir_setdata);\r
+void       ir_set_assign_ref(ir_set,long long);\r
+void       ir_data_assign_path(ir_setdata,uint8_t*);\r
+ir_setdata ir_framesheet(uint8_t*,ir_facing,int,int);\r
+ir_setdata ir_mapsheet(uint8_t*,ir_facing,int,int);\r
+ir_setdata ir_audio(uint8_t*);\r
+ir_setdata ir_link_odat(ir_setld);\r
+ir_setdata ir_link_vdat(ir_setld,uint8_t*);\r
+ir_setdata ir_link_mdat(ir_setld,uint8_t*);\r
+ir_setdata ir_link_adat(ir_setld,uint8_t*);\r
+/* Reference Linking Data \r
+   Create linking data to sets or classes that will be resolved at a later\r
+   stage.  Class references can be created from an ir_class object, if\r
+   available, or from the root class.  Set references can be created from a\r
+   64-bit integer ID, or from a class linking data and a child name.  Once\r
+   created, both Class and Set link data can traverse children, specified by\r
+   name, which will be resolved at the linking stage as well.\r
+*/\r
+ir_classld ir_classld_from_class(ir_class);\r
+ir_classld ir_classld_from_root(void);\r
+ir_classld ir_classld_addchild(ir_classld,uint8_t*);\r
+ir_setld   ir_setld_from_ref(long long);\r
+ir_setld   ir_setld_from_classld(ir_classld,uint8_t*);\r
+ir_setld   ir_setld_addchild(ir_setld,uint8_t*);\r
+#endif //_IR_H_\r
index 95a47cf..c1f15f4 100644 (file)
   #include <string.h>
   #include <dirent.h>
   #include <unitypes.h>
   #include <string.h>
   #include <dirent.h>
   #include <unitypes.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(uint8_t*,int, int, int, int, uint8_t*);
-  extern void insert_mlink(uint8_t*, int);
-  extern void insert_vlink(uint8_t*, int);
-  extern void insert_framesheet(uint8_t* ,int, int, int,int, uint8_t*);
-  
-  #define yylex lexer
-
-
-  void yyerror();
+  #include "ir.h"
+
+  struct frame_spec_t { enum facing d; int w, h; };
+
+  extern long     sys_pagesize;
+  extern int      lexer();
+  static void     yyerror(char const*);
+  /* Stack-based class handler */
+  static ir_class *class_stack, *csp;
+  static size_t   class_stack_size;
+  static ir_class class_stack_init(void);
+  #define         class_stack_pop() (*--csp)
+  static ir_class class_stack_push(ir_class);
+
+  #define yylex     lexer
+  #define yyclass   (*csp)
+  #define yyclassld (ir_classld_from_class(yyclass))
 %}
 %define parse.error verbose
 %define lr.type ielr
 %}
 %define parse.error verbose
 %define lr.type ielr
-
+%define api.pure full
+%define api.push-pull push
 %union {
 %union {
-  long long ref;
-  int val;
-  uint8_t* str;
-  void *voidp;
+  long long   ref;
+  int         val;
+  enum facing face;
+  uint8_t*    str;
+  ir_class    class;
+  ir_set      set;
+  ir_setld    ld;
+  ir_setdata  data;
+  struct frame_spec_t frame_spec;
 }
 }
-
- //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 <str> NAME
- /* Syntax Directed Translation Scheme of the APC grammar */
-
-/* Rules */
+/* Operators */
+%token        CLOPEN    //(
+%token        CLCLOSE   //)
+%token        MAP       //~
+%token        AUDIO     //AUDIO
+%token        SS        //SS
+%token        LINK      //#
+/* Terminals */
+%token <val>  NUM
+%token <str>  PATH
+%token <ref>  REF
+%token <face> FACING
+%token <str>  NAME
+/* Types */
+%type<data>       data_spec
+%type<set>        set_spec
+%type<ld>         set_ld set_link
+%type<frame_spec> frame_spec
+/* Init */
+%initial-action { class_stack_init(); }
 %%
 %%
-cdat_buf:
-class_block
-;
-
-class:
-NAME CLOPEN {push_cdat($1);} class_block CLCLOSE              {pop_cdat();};
+/* Syntax Directed Translation Scheme of the APC grammar */
+progn:
+  class_list 
+| class_list statement_list
+| statement_list
 ;
 
 class_list:
 ;
 
 class_list:
-class_list class
+  class_list class
 | class
 ;
 
 | class
 ;
 
-class_block:
-class_list
-| class_list statement_list
-| statement_list
+class:
+  NAME CLOPEN   { class_stack_push(ir_class_addchild(yyclass, $1)); }
+  progn
+  CLCLOSE       { class_stack_pop(); }
 ;
 
 statement_list:
 ;
 
 statement_list:
-statement_list statement
-| statement
+  statement_list statement
+| statement    
 ;
 
 statement:
 ;
 
 statement:
-vdat_statement
-| map_statement
-| ref_statement
-| olink
-;
-
-ref_statement:
-set_namelist REF                                  {insert_refid($2);};
+  set_spec data_spec REF PATH { ir_data_assign_path($2,$4); ir_set_assign_data($1,$2); ir_set_assign_ref($1,$3); }
+| set_spec data_spec PATH     { ir_data_assign_path($2,$3); ir_set_assign_data($1,$2); }
+| set_spec REF PATH           { ir_set_assign_ref($1,$2); }
 ;
 
 ;
 
-link_namelist:
-link_namelist NAME                                {insert_link_name($2);};
-| NAME                                            {};
+data_spec:
+  SS NAME frame_spec     { $$ = ir_framesheet($2,$3.d,$3.w,$3.h); }
+| MAP NAME frame_spec    { $$ = ir_mapsheet($2,$3.d,$3.w,$3.h); }
+| AUDIO NAME             { $$ = ir_audio($2); }
+| LINK set_ld            { $$ = ir_link_odat($2); }
+| LINK set_ld MAP        { $$ = ir_link_mdat($2,NULL); }
+| LINK set_ld MAP NAME   { $$ = ir_link_mdat($2,$4); }
+| LINK set_ld SS         { $$ = ir_link_vdat($2,NULL); }
+| LINK set_ld SS NAME    { $$ = ir_link_vdat($2,$4); }
+| LINK set_ld AUDIO      { $$ = ir_link_adat($2,NULL); }
+| LINK set_ld AUDIO NAME { $$ = ir_link_adat($2,$4); }
 ;
 
 ;
 
-
-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,  0,  0,  $4);};
-| 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 PATH                   {insert_map($1,  0, $2, $3, $4,  $5);};
-| NAME REF PATH                           {insert_map($1,  0,  0,  0, $2,  $3);};
-| NAME D REF PATH                         {insert_map($1, $2,  0,  0, $3,  $4);};
-| NAME D NUM NUM REF 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($3, 0);     };
-| MOPEN LINK link_namelist PATH            {insert_mlink(NULL, 0);   };    
-| MOPEN LINK REF PATH                      {insert_mlink(NULL, $3);  };
-| MOPEN LINK NAME LINK REF PATH            {insert_mlink($3,$5);     };
-;
-
-//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
+set_spec:
+  set_spec NAME          { $$ = ir_set_addchild($1,$2);      }
+| NAME                   { $$ = ir_class_addset(yyclass,$1); }
 ;
 
 ;
 
-
-olink:
-set_namelist MOPEN REF 
+set_link:
+  set_link NAME          { $$ = ir_setld_addchild($1,$2); }
+| NAME                   { $$ = ir_setld_from_classld(yyclassld,$1) }
 ;
 
 ;
 
-vdat_statement:
-set_namelist SS spritesheet_statement
-| set_namelist SS vlink                   
+set_ld:
+  set_link               { $$ = $1; }
+| REF                    { $$ = ir_setld_from_ref($1); }
 ;
 
 ;
 
-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 PATH            {insert_framesheet($1, $2, $3, $4, $5, $6);};
-| NAME D REF PATH                         {insert_framesheet($1, $2, 0, 0, $3, $4);};
-| NAME HEIGHT WIDTH REF PATH              {insert_framesheet($1, 0, $2, $3, $4, $5);};
-| NAME REF PATH                           {insert_framesheet($1, 0, 0, 0, $2, $3);};
+frame_spec:
+  NUM NUM                { $$ = (struct frame_spec_t) {SFACE,$1,$2}; }
+| FACING                 { $$ = (struct frame_spec_t) {$1,0,0}; }
+| FACING NUM NUM         { $$ = (struct frame_spec_t) {$1,$2,$3}; }
 ;
 
 %%
 
 ;
 
 %%
 
-void
-yyerror (char const *s)
-{ fprintf(stderr, "%s\n", s);
+#define ERR_ALLOC "memory allocation error\n"
+
+/* print to stderr */
+static
+void yyerror
+( char const *s )
+{ fprintf(stderr, "%s\n", s); }
+
+/* Initialize the class stack
+   If the class_stack hasn't been allocated yet, allocates a page for pointers
+   to be stored in.  Initializes class stack pointer, and inserts the root class
+   from IR
+   Returns the root class given by IR.
+*/
+static
+ir_class class_stack_init
+( void )
+{ if (class_stack == NULL)
+    { class_stack_size = (size_t) sys_pagesize;
+      class_stack = (ir_class*) malloc(class_stack_size);
+      if (class_stack == NULL)
+       { yyerror(ERR_MEM);
+         exit(1);
+       }
+    }
+  csp = class_stack;
+  return class_stack_push(ir_class_root());
+}
+
+/* Add a Class to the Stack
+   Allocated in page-sized chunks, potentially infinite depth is supported.
+   Returns the input class.
+*/
+static
+ir_class class_stack_push
+#define  class_size (sizeof(*class_stack))
+( ir_class class )
+{ size_t class_stack_len = csp - class_stack;
+  ir_class* new_class_stack;
+  if ((class_stack_len * class_size + class_size) > class_stack_size)
+    { class_stack_size += (size_t) sys_pagesize;
+      new_class_stack = (ir_class*) realloc(class_stack, class_stack_size);
+      if (new_class_stack == NULL)
+       { free(class_stack); //realloc failure does not free class_stack
+         yyerror("realloc " ERR_MEM);
+         exit(1);
+       }
+      class_stack = new_class_stack;
+      csp = class_stack + class_stack_len;
+    }
+  return (*csp++ = class);
 }
 }
index 5c06a4e..14266ca 100644 (file)
@@ -223,7 +223,11 @@ int dredge_current_depth
   struct dirent* direntp;
   DL_CD_INIT();
  scan_next:
   struct dirent* direntp;
   DL_CD_INIT();
  scan_next:
-  if ((direntp = readdir(cwd)) != NULL)
+  errno = 0;
+  direntp = readdir(cwd);
+  if (errno)
+    return -1;
+  if (direntp != NULL)
     { switch (direntp->d_type)
         { case DT_REG:
             DPS_PUSH(direntp);
     { switch (direntp->d_type)
         { case DT_REG:
             DPS_PUSH(direntp);
@@ -239,8 +243,6 @@ int dredge_current_depth
             goto scan_next;
         }
     }
             goto scan_next;
         }
     }
-  if (errno)
-    return -1;
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }