adding org file
authorJordan <jordanlavatai@gmail.com>
Thu, 13 Oct 2016 23:06:15 +0000 (16:06 -0700)
committerJordan <jordanlavatai@gmail.com>
Thu, 13 Oct 2016 23:06:15 +0000 (16:06 -0700)
.org/data/2d/ec5876-7b81-4b9c-97fe-03b152fa276a/scanner.c [new file with mode: 0755]
.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer.c [new file with mode: 0755]
.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer_lex.rl [new file with mode: 0755]
.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.c [new file with mode: 0755]
.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.h [new file with mode: 0755]
.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/irmem.c [new file with mode: 0644]
.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/parser.y [new file with mode: 0644]
.org/schedule.org [new file with mode: 0644]

diff --git a/.org/data/2d/ec5876-7b81-4b9c-97fe-03b152fa276a/scanner.c b/.org/data/2d/ec5876-7b81-4b9c-97fe-03b152fa276a/scanner.c
new file mode 100755 (executable)
index 0000000..f982cf2
--- /dev/null
@@ -0,0 +1,210 @@
+/*!@file\r
+  \brief   APC Directory Scanner\r
+  \details This hand-written parser/scanner traverses a directory tree and\r
+           tokenizes elements of the structure which correspond to APC grammar.\r
+           The parser is implemented as a 2D stack which populates a list of\r
+           child directories at each depth, handling only the leaf nodes\r
+           (regular files) of the directory open at the current depth to\r
+           conserve memory and speed up traversal.\r
+           The scanner works with the lexer to lexically analyze text, and\r
+           assumes the existence of an external 'lex' function\r
+  \author  Jordan Lavatai\r
+  \date    Aug 2016\r
+  ----------------------------------------------------------------------------*/\r
+/* Standard */\r
+#include <stdio.h>  //print\r
+#include <errno.h>  //errno\r
+/* Posix */\r
+#include <err.h>    //warnx\r
+#include <stdlib.h> //exit\r
+#include <unistd.h> //chdir\r
+#include <dirent.h> //opendir\r
+\r
+#include "parser.tab.h"\r
+/* Public */\r
+int  scanner_init(void);\r
+void scanner_quit(void);\r
+int  scanner(void);\r
+/* Private */\r
+#ifndef DL_STACKSIZE\r
+#define DL_STACKSIZE     64\r
+#endif\r
+#ifndef DL_CD_STACKSIZE\r
+#define DL_CD_STACKSIZE  DL_STACKSIZE //square tree\r
+#endif\r
+extern //lexer.c\r
+int  lexer_lex(const char*);\r
+extern //lexer.c\r
+void lexer_pushtok(int, int);\r
+static\r
+int  dredge_current_depth(void);\r
+extern //lexer.c\r
+struct dirent* lexer_direntpa[], **lexer_direntpp;\r
+extern //SRC_DIR/bin/tools/apc.c\r
+const char* cargs['Z'];\r
+\r
+struct dirlist\r
+{ DIR*           dirp;\r
+  struct dirent* child_directory_stack[DL_CD_STACKSIZE],** cds;\r
+} directory_list_stack[DL_STACKSIZE + 1],* dls; //+1 for the root dir\r
+\r
+/* Directory Listing Stack\r
+   FILO Stack for keeping an open DIR* at each directory depth for treewalk.\r
+   This stack is depth-safe, checking its depth during push operations, but not\r
+   during pop operations, to ensure the thread doesn't open too many files at\r
+   once (512 in c runtime), or traverse too far through symbolic links.\r
+   A directory listing includes a DIR* and all DIR-typed entity in the directory\r
+   as recognized by dirent, populated externally (and optionally).\r
+   This stack behaves abnormally by incrementing its PUSH operation prior to\r
+   evaluation, and the POP operations after evaluation.  This behavior allows\r
+   the 'DL_CURDEPTH' operation to map to the current element in the 'dl_stack'\r
+   array, and it is always treated as the "current depth". This also allows us\r
+   to init the root directory to 'directory_list_stack'[0] and pop it in a safe\r
+   and explicit manner.\r
+*/\r
+#define DL_STACK        (directory_list_stack)\r
+#define DL_STACKP       (dls)\r
+#define DL_CD_STACK     ((*DL_STACKP).child_directory_stack)\r
+#define DL_CD_STACKP    ((*DL_STACKP).cds)\r
+#define DL_CURDIR()     ((*DL_STACKP).dirp)\r
+#define DL_LEN()        (DL_STACKP - DL_STACK)\r
+#define DL_CD_LEN()     (DL_CD_STACKP - DL_CD_STACK)\r
+#define DL_INIT()       (DL_STACKP = DL_STACK)\r
+#define DL_CD_INIT()    (DL_CD_STACKP = DL_CD_STACK)\r
+#define DL_POP()        ((*DL_STACKP--).dirp)\r
+#define DL_CD_POP()     (*--DL_CD_STACKP)\r
+#define DL_PUSH(D)      ((*++DL_STACKP).dirp = D)\r
+#define DL_CD_PUSH(E)   (*DL_CD_STACKP++ = E)\r
+\r
+\r
+/* Initializer\r
+   Initializer expects a function pointer to its lexical analysis function.\r
+   Sets up stack pointers and returns boolean true if 'opendir' encounters an\r
+   error, or if dredge_current_depth returns boolean true.\r
+*/\r
+int scanner_init\r
+#define CWDSTR  "./"\r
+#define ROOTDIR (cargs['d'] ? cargs['d'] : CWDSTR)\r
+()\r
+{ DL_INIT();\r
+  DL_STACK[0].dirp = opendir(ROOTDIR);\r
+  printf("Root dir %s\n",ROOTDIR);\r
+  return !chdir(ROOTDIR) && (DL_STACK[0].dirp == NULL || dredge_current_depth() == -1);\r
+}\r
+\r
+/* Quit */\r
+void scanner_quit\r
+()\r
+{ if (DL_CURDIR())\r
+    closedir(DL_CURDIR());\r
+}\r
+\r
+/* Scanner\r
+   The main driver of the scanner will advance the current treewalk state and\r
+   tokenize tree-based push/pop operations.  It will call 'lexer_lex' to\r
+   tokenize directory names prior to making a push operation. safe checking for\r
+   all returns from the filesystem handler will exit on serious system errors.\r
+\r
+   after pushing a new directory to the directory list, the scanner will dredge\r
+   the directory and alphabetically sort all file entries into the lexer's file\r
+   array, while placing all subdirectory entries in the current depth's child\r
+   directory stack to be scanned later.\r
+\r
+   Returns the number of elements added to the lexer's file array, or -1 on\r
+   error\r
+*/\r
+int scanner\r
+#define $($)#$ //stringifier\r
+#define ERR_CHILD  "Fatal: Maximum of " $(DL_CD_STACKSIZE)      \\r
+  " child directories exceeded for directory at depth %i\n"     \\r
+  ,DL_LEN()\r
+#define ERR_DEPTH  "Fatal: Maximum directory depth of " $(DL_STACKSIZE) \\r
+  " exceeded during directory scan\n"\r
+#define ERR_DL     "Fatal: Directory List Stack Corruption %x\n", DL_LEN()\r
+#define TOK_CLOPEN  0x55, 1 //TODO\r
+#define TOK_CLCLOSE 0x56, 1 //TODO\r
+()\r
+{ struct dirent* direntp;\r
+  struct DIR* DIRp;\r
+ parse:\r
+  if (DL_CD_LEN() >= DL_CD_STACKSIZE)//fail if maxchildren exceeded\r
+    { fprintf(stderr, ERR_CHILD);\r
+      goto fail;\r
+    }\r
+  if (DL_CD_LEN() > 0)               //There are entities to process\r
+    { if ((direntp = DL_CD_POP()) == NULL)//If the dirent is null, the library\r
+        goto libfail;                     //function in dirent has failed\r
+      lexer_lex(direntp->d_name);         //lex the directory name\r
+      if (DL_LEN() >= DL_STACKSIZE)       //fail if maxdepth exceeded\r
+        { fprintf(stderr, ERR_DEPTH);\r
+          goto fail;\r
+        }\r
+      if (chdir(direntp->d_name))         //move into the new directory\r
+       goto libfail;\r
+      DL_PUSH(opendir(CWDSTR));\r
+      if (DL_CURDIR() == NULL)            //open the cwd\r
+       goto libfail;\r
+      lexer_pushtok(TOK_CLOPEN);          //Push "Open Directory" token\r
+      return dredge_current_depth();      //Filter and sort the current depth\r
+    }\r
+  else if (DL_LEN() >= 0)            //Any dirs left? (Including root)\r
+    { if (closedir(DL_POP()))             //close the directory we just left\r
+        goto libfail;\r
+      if (DL_LEN() == -1)                 //If we just popped root,\r
+        return 0;                         //we're done\r
+      lexer_pushtok(TOK_CLCLOSE);         //Else push "Close Directory" token,\r
+      if (!chdir(".."))                   //move up a directory and\r
+        goto parse;                       //start over\r
+    }\r
+  fprintf(stderr, ERR_DL);\r
+ libfail:\r
+  perror("parsedir");\r
+ fail:\r
+  exit(EXIT_FAILURE);\r
+}\r
+\r
+/* Directory Entity Sort and Filter (Dredge)\r
+   This filter removes all unhandled file types, and places any 'DT_DIR' type\r
+   files in the current Directory List's directory stack.  Upon finishing,\r
+   the 'CE_STACK' is sorted alphabetically, and the current 'DL_CD_STACK' is\r
+   populated.  Prints warnings for unhandled files.\r
+\r
+   Returns -1 if 'readdir' encounters an error, otherwise returns the number of\r
+   directory entries sent to the external 'lexer_direntpa' array.\r
+*/\r
+typedef\r
+int (*qcomp)(const void*, const void*);\r
+static inline\r
+int dredge_current_depth\r
+#define READDIR_ERROR (-1)\r
+#define READDIR_DONE  (0)\r
+#define DPS_LEN()     (lexer_direntpp - lexer_direntpa)\r
+#define DPS_PUSH(E)   (*lexer_direntpp++ = E)\r
+()\r
+{ struct dirent**  direntpp = lexer_direntpa;\r
+  DIR*             cwd      = DL_CURDIR();\r
+  struct dirent*   direntp;\r
+  DL_CD_INIT();\r
+ scan_next:\r
+  if ((direntp = readdir(cwd)) != NULL)\r
+    { switch (direntp->d_type)\r
+        { case DT_REG:\r
+            DPS_PUSH(direntp);\r
+            goto scan_next;\r
+          case DT_DIR:\r
+           if (*(direntp->d_name) == '.') //skip hidden files and relative dirs\r
+              goto scan_next;\r
+           DL_CD_PUSH(direntp);\r
+            goto scan_next;\r
+          case DT_UNKNOWN:\r
+            warnx("unknown file %s: ignoring", direntp->d_name);\r
+          default:\r
+            goto scan_next;\r
+        }\r
+    }\r
+  if (errno)\r
+    return -1;\r
+  qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);\r
+  return DPS_LEN();\r
+}\r
+\r
diff --git a/.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer.c b/.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer.c
new file mode 100755 (executable)
index 0000000..2252a37
--- /dev/null
@@ -0,0 +1,180 @@
+/*!@file\r
+  \brief   lexical analyzer implementation for APC\r
+  \details The lexer manages two FIFO stacks.  One for maintaining tokens, the\r
+           other for maintaining a list of files to be scanned.  During\r
+           execution, the lexer will return a token from its token queue if any\r
+           are present.  If not, the lexer will will pop an element from its\r
+           file queue to 'scanner' to be tokenized.  If the file queue is empty,\r
+           the lexer will instead call 'parsedir' to traverse the directory tree\r
+           and tokenize the results.  If 'parsedir' does not generate any new\r
+           tokens, we are done.\r
+  \author  Jordan Lavatai\r
+  \date    Aug 2016\r
+  ----------------------------------------------------------------------------*/\r
+/* Standard */\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+/* Posix */\r
+#include <unistd.h>\r
+#include <stdlib.h>\r
+#include <dirent.h>\r
+/* Local */\r
+#include "parser.tab.h"\r
+#ifndef DE_STACKSIZE\r
+#define DE_STACKSIZE 1024\r
+#endif\r
+#ifndef TK_STACKSIZE\r
+#define TK_STACKSIZE 1024\r
+#endif\r
+/* Public */\r
+int  lexer_init(void);\r
+int  lexer(void);\r
+int  lexer_lexfile(const char*);\r
+void lexer_pushtok(int, YYSTYPE);\r
+extern //lexer_lex.rl\r
+int lexer_lex(const char*);\r
+struct dirent* lexer_direntpa[DE_STACKSIZE], **lexer_direntpp;\r
+/* Private */\r
+extern //scanner.c\r
+int scanner_init(void);\r
+extern //scanner.c\r
+int scanner(void);\r
+static inline\r
+int dredge_current_depth(void);\r
+extern //bison\r
+YYSTYPE yylval;\r
+static\r
+struct tok\r
+{ YYSTYPE lval;  //token val\r
+  int     tok_t; //token type\r
+} token_stack[TK_STACKSIZE];\r
+static\r
+union tokp\r
+{ int*        tpt; //token pointer type\r
+  struct tok* tok;\r
+  YYSTYPE*    tvp; //token value pointer\r
+} tks, tkx;\r
+\r
+/* Directory Entity Array/Stack\r
+   Simple array for keeping track of dirents yet to be processed by the scanner.\r
+   If this list is empty and there are no tokens, the lexer is done.\r
+   This array is populated by the scanner as an array, and popped locally by the\r
+   lexer as a stack.\r
+*/\r
+#define DE_STACK    (lexer_direntpa)\r
+#define DE_STACKP   (lexer_direntpp)\r
+#define DE_LEN()    (DE_STACKP - DE_STACK)\r
+#define DE_INIT()   (DE_STACKP = DE_STACK)\r
+#define DE_POP()    (*--DE_STACKP)\r
+\r
+/* Token Stack\r
+   This is a FIFO stack whose pointers are a union of either a pointer to an\r
+   integer, or a pointer to two integers (a struct tok).  This way, integers may\r
+   be added or removed from the stack either singularly (IPUSH/IPOP), or as a\r
+   full token of two integers (PUSH/POP).\r
+   An alignment error will occur if IPOP or IPUSH are used a non-even number of\r
+   times in a sequence!\r
+*/\r
+#define TK_STACK     (token_stack)\r
+#define TK_STACKP    (tks.tok)\r
+#define TK_STACKPI   (tks.tpt)\r
+#define TK_STACKPL   (tks.tvp)\r
+#define TK_STACKX    (tkx.tok)\r
+#define TK_STACKXI   (tkx.tpt)\r
+#define TK_LEN()     (TK_STACKX - TK_STACKP)\r
+#define TK_INIT()    (TK_STACKP = TK_STACKX = TK_STACK)\r
+#define TK_POP()     (*TK_STACKP++)\r
+#define TK_POPI()    (*TK_STACKPI++);\r
+#define TK_POPL()    (*TK_STACKPL++);\r
+#define TK_PUSH(T,L) (*TK_STACKX++ = (struct tok){L,T})\r
+\r
+/* Initializer\r
+   The initializer returns boolean true if an error occurs, which may be handled   with standard errno.\r
+*/\r
+int lexer_init\r
+()\r
+{ TK_INIT();\r
+  DE_INIT();\r
+  return scanner_init();\r
+}\r
+\r
+/* Lexer\r
+   If the token buffer is empty, 'lexer' will initialize the token buffer and\r
+   call 'lexer_scandir'.  If SCAN_ERROR is returned, an error is printed\r
+   before sending a null return to bison.  If 0 tokens are generated, the error\r
+   printing is skipped.  In all other cases, 'yylval' is set, and the token's\r
+   integer representation is returned.\r
+*/\r
+int lexer\r
+#define $($)#$\r
+#define SCAN_ERROR -1\r
+#define TK_EMPTY   (TK_STACKP == TK_STACKX)\r
+#define FAIL(...)                              \\r
+  do {                                         \\r
+    fprintf(stderr,__VA_ARGS__);               \\r
+    goto done;                                 \\r
+  } while (0)\r
+()\r
+{start:\r
+  while (DE_LEN() > 0)    //lex any directory entries in our stack\r
+    if (lexer_lexfile(DE_POP()->d_name) == 0)\r
+      FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKP)->d_name);\r
+  if (TK_EMPTY)           //if there are no tokens,\r
+    { TK_INIT();            //initialize the token stack back to 0\r
+      switch (scanner())\r
+        { case SCAN_ERROR:    //if an error occurred,\r
+           FAIL("Scanner error\n");\r
+         case 0:             //if the the scanner finds no dirents,\r
+           goto done;        //then we are done\r
+          default:            //if we found some elements to scan,\r
+           goto start;       //start over and lex them\r
+        }\r
+    }\r
+  yylval = TK_POPL();\r
+  return TK_POPI();\r
+ done:\r
+  yylval.val = 0;\r
+  return 0;\r
+}\r
+\r
+\r
+/* Token Receiver\r
+   This receiver takes a struct tok and pushes it to the FIFO stack.\r
+*/\r
+void lexer_pushtok\r
+#define $($)#$ //stringifier\r
+#define ERR_TK "Fatal: Generated over " $(TK_STACKSIZE) " tokens in one pass."\r
+( int tok, YYSTYPE lval )\r
+{ if (TK_LEN() >= TK_STACKSIZE)\r
+    { fprintf(stderr, ERR_TK);\r
+      exit(EXIT_FAILURE);\r
+    }\r
+  TK_PUSH(tok, lval);\r
+  printf("Pushed Token  %i | %i\n", TK_STACK[TK_LEN() - 1].tok_t, TK_STACK[TK_LEN() - 1].lval.val);\r
+}\r
+\r
+/* Lexical analysis of a file\r
+   Strips a filename to its base name, then sends it to lexer_lex\r
+*/\r
+int lexer_lexfile\r
+#define MAX_FNAME 2048\r
+#define HIDDEN_WARNING "%s is hidden and will not be parsed!\n", filename\r
+( const char  *filename\r
+)\r
+{ static char fname[MAX_FNAME];\r
+  char        *last_period = NULL, *iter;\r
+\r
+  if (*filename == '.')\r
+    { fprintf (stderr, HIDDEN_WARNING);\r
+      return 0;\r
+    }\r
+  strncpy(fname,filename,MAX_FNAME);\r
+  last_period = NULL;\r
+  for (iter = fname; *iter; iter++)\r
+    if (*iter == '.')\r
+      last_period = iter;\r
+  if (last_period)\r
+    *last_period = '\0';\r
+  return lexer_lex(fname);\r
+}\r
diff --git a/.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer_lex.rl b/.org/data/fa/f3ff67-f8e9-41fe-9a32-2ced4bbf5b99/lexer_lex.rl
new file mode 100755 (executable)
index 0000000..0224bb8
--- /dev/null
@@ -0,0 +1,115 @@
+/* Ragel State Machine for tokenizing text */\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <apc/parser.tab.h>\r
+\r
+extern void lexer_pushtok(int, YYSTYPE);\r
+\r
+int lexer_lex(const char*);\r
+int ipow(int, int);\r
+int ttov(const char* str, int);\r
+uint64_t ttor(const char* str, int);\r
+char* ttos(const char* str, 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
+#define $($)#$\r
+#define PUSHTOK(TOK,LFUNC,UTYPE)                       \\r
+  do {                                                 \\r
+    printf("PUSHTOK(" $(TOK) $(LFUNC) $(UTYPE) ")\n"); \\r
+    tok_t = TOK;                                       \\r
+    yylval.UTYPE = LFUNC(ts, p-ts);                    \\r
+    lexer_pushtok(tok_t, yylval);                      \\r
+    ++ntok;                                            \\r
+  } while (0)\r
+\r
+%%{\r
+  machine token_matcher;\r
+\r
+  # set up yylval and tok_t to be pushed to stack\r
+  action set_ref  { PUSHTOK(REF, ttor, ref); }\r
+  action set_val  { PUSHTOK(NUM, ttov, val); }\r
+  action set_name { PUSHTOK(NAME, ttos, str); }\r
+  action set_ts   { ts = p; }\r
+  action lex_error {printf("input error: character %c in filename %s is invalid\n", fc, str);}\r
+\r
+  # instantiate machines for each possible token\r
+  ref = '0x' xdigit+ %set_ref;\r
+  val = digit+ %set_val;\r
+  name = alpha+ %set_name;\r
+  tok = ref | val | name;\r
+  segment = (tok . '_') %set_ts;\r
+\r
+ main := segment* . tok $lerr(lex_error);\r
+}%%\r
+\r
+\r
+%%write data;\r
+\r
+/* Scan filename and push the its tokens\r
+   onto the stack */\r
+int lexer_lex (const char* str)\r
+{\r
+  const char *p, *pe, *ts, *eof;\r
+  int  cs, tok_t, ntok = 0;\r
+  printf ("Lexing: %s\n",str);\r
+  p = ts = str;\r
+  pe = p + strlen(str);\r
+  %%write init;\r
+  %%write exec;\r
+  printf ("Lexed %i tokens\n",ntok);\r
+  return ntok;\r
+}\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 char* 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 char* 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
+char* ttos(const char* str, int len)\r
+{\r
+  int i;\r
+  char token_buf[MAX_TOK_LEN];\r
+\r
+  memmove(token_buf, str, len);\r
+  token_buf[len+1] = '\0';\r
+\r
+  return strdup(token_buf);\r
+}\r
diff --git a/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.c b/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.c
new file mode 100755 (executable)
index 0000000..421f6e5
--- /dev/null
@@ -0,0 +1,465 @@
+/*!@file\r
+  \brief   IR Memory Implementation\r
+  \details Intermediary memory management\r
+  \author  Jordan Lavatai\r
+  \date    Aug 2016\r
+  ----------------------------------------------------------------------------*/\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <stdint.h> //uint64_t\r
+#include <string.h> //memmove\r
+#include <stdlib.h> //malloc\r
+#include <apc/ir.h>\r
+\r
+\r
+\r
+/* functions needed from irmem.c */\r
+extern\r
+void\r
+ir_init(void);\r
+\r
+extern\r
+struct cdat*\r
+alloc_cdat(void);\r
+\r
+extern\r
+struct odat*\r
+alloc_odat(void);\r
+\r
+extern\r
+void\r
+alloc_vdat(void);\r
+\r
+extern\r
+struct link*\r
+alloc_link(void);\r
+\r
+extern\r
+struct ref*\r
+alloc_ref(void);\r
+\r
+extern\r
+struct cdat*\r
+curr_cdat(void);\r
+\r
+extern\r
+struct odat*\r
+curr_odat(void);\r
+\r
+extern\r
+struct vdat*\r
+curr_vdat(void);\r
+\r
+extern\r
+struct set*\r
+curr_set(void);\r
+\r
+extern\r
+struct ref*\r
+curr_ref(void);\r
+\r
+extern\r
+struct quad*\r
+curr_quad(void);\r
+\r
+extern\r
+struct model*\r
+curr_model(void);\r
+\r
+/* struct definitions needed from irmem.c */\r
+extern int num_cdats;\r
+extern struct cdat** cdat_stackp;\r
+extern struct odat* curr_set_odatp;\r
+extern uint64_t ss_ref_id;\r
+\r
+extern int num_vdats;\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
+void\r
+push_cdat\r
+( char* name\r
+)\r
+{\r
+  struct cdat* curr_cdatp;\r
+\r
+  curr_cdatp = alloc_cdat();\r
+\r
+  memmove(curr_cdatp->name, name, 32);\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
+/* 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
+void\r
+insert_set_label\r
+( char* name,\r
+  uint64_t ref_id\r
+)\r
+{\r
+\r
+  struct set* curr_setp;\r
+\r
+  curr_setp = curr_set();\r
+  curr_set_odatp = alloc_odat();\r
+\r
+  memmove(curr_set_odatp->name, name, 32);\r
+  memmove(curr_setp->name, name, 32);\r
+\r
+  if(ref_id != -1)\r
+    { curr_set_odatp->ref_id = ref_id;\r
+      curr_setp->ref_id = ref_id;\r
+    }\r
+  else\r
+    { curr_setp->ref_id = ss_ref_id;\r
+      curr_set_odatp->ref_id = ss_ref_id++;\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
+( uint64_t ref_id\r
+)\r
+{\r
+  struct set* curr_setp;\r
+\r
+  curr_setp = curr_set();\r
+\r
+  curr_setp->ref_id = ref_id;\r
+\r
+}\r
+\r
+void\r
+insert_set_vlink\r
+( uint64_t ref_id,\r
+  char* 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.ref_id = ref_id;\r
+  memmove(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
+( uint64_t ref_id \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.ref_id = ref_id;\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
+{ uint64_t ref_id;\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, preserved in global space\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
+  memmove(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
+  ref_id = curr_setp->ref_id; // ref_id set by insert_set_label(name, ref_id)\r
+\r
+  curr_refp->ref_id = ref_id;\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 ref_id 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
+( char* name,\r
+  uint64_t ref_id\r
+)\r
+{\r
+  struct odat* curr_odatp;\r
+\r
+  curr_odatp = alloc_odat();\r
+\r
+  memmove(curr_odatp->name, name, 32);\r
+\r
+  if(ref_id != -1)\r
+    curr_odatp->ref_id = ref_id;\r
+  else\r
+    curr_odatp->ref_id = ss_ref_id++;\r
+\r
+}\r
+\r
+/* We don't make an odat here, at output time we will resolve\r
+   the ref_id to the corresponding odat. */\r
+void\r
+insert_ele_olink\r
+( uint64_t ref_id\r
+)\r
+{\r
+  /* Do nothing because we already know the ref_id that\r
+     the odat needs for this element (in the quad_file) */\r
+}\r
+\r
+void\r
+insert_ele_vlink\r
+( uint64_t ref_id,\r
+  char* 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.ref_id = ref_id;\r
+  memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);\r
+\r
+}\r
+\r
+void\r
+insert_ele_svlink\r
+( uint64_t ref_id\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.ref_id = ref_id;\r
+\r
+\r
+}\r
+\r
+//Insert element into odat_buf and cdatpages\r
+void\r
+insert_ele()\r
+{\r
+  uint64_t ref_id;\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
+\r
+  ref_id = curr_odatp->ref_id;\r
+\r
+  curr_refp->ref_id = ref_id;\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
+void\r
+insert_quad\r
+( void* quad_filep\r
+)\r
+{\r
+  struct odat* curr_odatp;\r
+\r
+  curr_odatp->quad_filep = quad_filep;\r
+}\r
+\r
+/* Inserting 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
+void\r
+insert_framesheet\r
+( char direction,\r
+  char* name,\r
+  uint64_t ref_id,\r
+  int height ,\r
+  int width,\r
+  int num_frames\r
+)\r
+{ struct vdat* curr_vdatp;\r
+  struct model* curr_modelp;\r
+\r
+  curr_vdatp = curr_vdat();\r
+  curr_modelp = curr_model();\r
+\r
+  curr_modelp->spritesheet[(int)direction].height = height;\r
+  curr_modelp->spritesheet[(int)direction].width = width;\r
+  curr_modelp->spritesheet[(int)direction].num_frames = num_frames;\r
+  curr_vdatp->num_models++;\r
+}\r
+\r
+void\r
+insert_frame_pointer\r
+( char 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/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.h b/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/ir.h
new file mode 100755 (executable)
index 0000000..3b1d75c
--- /dev/null
@@ -0,0 +1,271 @@
+/*!@file\r
+  \brief   Intermediate Representation (IR) between Directory Structure and Engine Grammar\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 Engine Grammar. 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
+\r
+#include <stdint.h>\r
+\r
+#define BUF_SIZE 256\r
+#define MAX_SETS 256\r
+#define MAX_ELES 256\r
+#define MAX_QUADS 256\r
+#define MAX_MODELS 256\r
+#define MAX_POSTS 256\r
+#define MAX_CLASS_DEPTH 256\r
+#define MAX_CLASSES 256\r
+#define MAX_FRAMES 256\r
+#define PTRS_IN_PAGE 1024\r
+#define MAX_CHUNKS 256\r
+#define PAGES_PER_CHUNK 16\r
+\r
+/*  Sets: elements. The set is populated at parse time AFTER the\r
+    elements are populated, due to the nature of bottom up parsing.          */\r
+\r
+struct set {\r
+  char name[32];\r
+  uint64_t ref_id;\r
+  int cdat_idx;\r
+};\r
+\r
+/*  Cdats: A cdat is a class data structure. Cdats serve as the central       */\r
+/*  data types of the IR. For each cdat, sets and element                     */\r
+/*  ref_ids must be dereferenced to determine the odat information. Cdats     */\r
+/*  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
+\r
+struct cdat {\r
+  char name[32];\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
+/* 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
+/* Refs: Each set/ele has a reference to its object data (odat) through a ref_id.\r
+   Ref_ids 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;\r
+  struct ref* nextref;\r
+  struct ref* lastref;\r
+  struct odat* odatp;\r
+  uint64_t ref_id; //0xFFFFFF->digit\r
+};\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 ref_id 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 ref_id that was stored for some object (if the ref_id exists),\r
+   and creating a relative pointer from the original object to the data that\r
+   was linked */\r
+\r
+/* Svlinks stand for short vlink, which is a link to a vdat. svlinks\r
+   differ from vlinks because they do not have a name */\r
+\r
+struct svlink {\r
+  uint64_t ref_id;\r
+};\r
+\r
+/* A vlink is what it sounds like, a link to a vdat */\r
+struct vlink {\r
+  uint64_t ref_id;\r
+  char anim_name[32];\r
+};\r
+\r
+union link_t {\r
+  struct vlink vlink;\r
+  struct svlink svlink;\r
+};\r
+\r
+/* From: src odat ()To: dest odat (ref_id)*/\r
+struct link {\r
+  int type; //1 = olink, 2 = vlink, 3 = svlink\r
+  union link_t link_t;\r
+  struct cdat* classp;\r
+  struct odat* odatp;\r
+  int set_idx;\r
+  int ele_idx;\r
+};\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
+\r
+struct root {\r
+  int x, y, z;\r
+};\r
+\r
+struct odat {\r
+  char name[32];\r
+  struct vdat* vdatp;\r
+  int vdat_id; //\r
+  int cdat_idx;\r
+  int hitbox;\r
+  uint64_t ref_id;\r
+  struct root root;\r
+  struct ref* refp; /* pointer to it's ref on ref_list */\r
+  void* quad_filep;\r
+};\r
+\r
+struct odat* curr_set_odatp; //when a set has elements, insert_set() can no longer\r
+                            //refer to its odat via curr_odat, so save the set odat. \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
+  void* frames[MAX_FRAMES];\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
+  char name[32];\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 skeleton on 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
+  struct model model_list[MAX_MODELS];\r
+};\r
+\r
+/* Called after the cdat open operator has been recognized in grammar. Allocates\r
+   the space for a cdat on the cdat_buf, pushes that pointer onto\r
+   the cdat_stack */\r
+void\r
+push_cdat(char*);\r
+\r
+/* Called after a cdat end operator has been recognized in grammar. Sets\r
+   top stack cdat ** to null and decrements stack pointer */\r
+void\r
+pop_cdat(void);\r
+\r
+/* Called after an odat has been populated. Allocates memory for\r
+   the next odat. */\r
+\r
+void\r
+insert_set_label(char*, uint64_t);\r
+\r
+/* Populate the sets representation in CURR_CDAT with a ref_id and insert a link\r
+   into the link_buf that will resolve the ref_id to an actual odat after parse time. */\r
+void\r
+insert_set_olink(uint64_t);\r
+\r
+/* Put the vlink in the link_buf to be processed after parsetime */\r
+void\r
+insert_set_vlink(uint64_t, char*);\r
+\r
+/* Put svlink in the link_buf to be processed after parsetime */\r
+void\r
+insert_set_svlink(uint64_t);\r
+\r
+/* Called for every set reduction except for sets with olinks. Populates the\r
+   set data structures in the CDAT and in the ODAT. Uses the name and ref_id\r
+   from insert_set_label. Also inserts a ref into the ref_buf with the CURR_ODAT\r
+   pointer so that we can also resolve the odat from its ref_id. */\r
+void\r
+insert_set(void);\r
+\r
+/* Insertion of eles is practically equivalent to how sets are inserted because both\r
+   share the same data type (ODAT). Like sets, eles have links, labels\r
+   and odats. Eles have the added notion of a parent set, and so must be inserted\r
+   into said parent set, but this is the only place they truly differ from sets. */\r
+\r
+void\r
+insert_set_vdatid(void);\r
+\r
+void\r
+insert_ele_label(char*, uint64_t);\r
+\r
+/* Insert an ele olink into the CURR_ODAT */\r
+void\r
+insert_ele_olink(uint64_t);\r
+\r
+/* Insert a ele vlink  into CURR_ODAT*/\r
+void\r
+insert_ele_vlink(uint64_t, char*);\r
+\r
+/* Inserts an ele short vlink into CURR_ODAT*/\r
+void\r
+insert_ele_svlink(uint64_t);\r
+\r
+/* inserts ele into CURR_CLASS and CURR_ODAT */\r
+void\r
+insert_ele(void);\r
+\r
+void\r
+insert_ele_vdatid(void);\r
+\r
+/* Inserts the hitbox into the CURR_ODAT */\r
+void\r
+insert_hitbox(int);\r
+\r
+/* Inserts the root into the CURR_ODAT */\r
+void\r
+insert_root(int, int, int);\r
+\r
+/* Inserts a quad into the CURR_ODAT */\r
+void\r
+insert_quad(void*);\r
+\r
+void\r
+insert_model(void);\r
+\r
+void\r
+insert_framesheet(char, char*, uint64_t, int, int, int);\r
+\r
+void\r
+insert_frame_pointer(char, void*);\r
+\r
+void\r
+alloc_vdat(void);\r
diff --git a/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/irmem.c b/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/irmem.c
new file mode 100644 (file)
index 0000000..3716d59
--- /dev/null
@@ -0,0 +1,330 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <apc/ir.h>
+#include <unistd.h>
+
+struct cdat*
+alloc_cdat(void);
+struct odat*
+alloc_odat(void);
+void
+alloc_vdat(void);
+struct link*
+alloc_link(void);
+struct ref*
+alloc_ref(void);
+struct cdat*
+curr_cdat(void);
+struct odat*
+curr_odat(void);
+struct vdat*
+curr_vdat(void);
+struct set*
+curr_set(void);
+struct ref*
+curr_ref(void);
+struct model*
+curr_model(void);
+void
+inc_posts(void);
+
+#define PAGES_PER_CHUNK 16
+
+//"type free" chunk stacking
+struct chunk_stack
+{ void* chunks[MAX_CHUNKS];
+  void* *csp;            //chunk stack pointer
+  void* dsp[MAX_CHUNKS]; //dat stack pointer (per chunk)
+  int   chunk_size;      //size of a chunk (including its forfeited page)
+  int   max_dats;        //number of dats per chunk for this stack
+} ocs, vcs, ccs, rcs, lcs, pcs; //odat, vdat, and cdat, ref, link, post stacks
+
+//type safety handled by macro expansion (do not call these directly from code, make dependent macros for access to these)
+#define CHUNKS_LEN(STACK)         ((STACK).csp - (STACK).chunks)
+#define CURRENT_CHUNK(STACK)      ((STACK).chunks[CHUNKS_LEN(STACK) - 1])
+#define CHUNKS_FULL(STACK)        ( (STACK).csp >= \
+                                    (STACK).chunks + MAX_CHUNKS * (STACK).chunk_size)
+#define CURRENT_DSP(STACK,TYPE)   ((TYPE*) ((STACK).dsp[CHUNKS_LEN(STACK) - 1]))
+#define DATA_FULL(STACK,TYPE)     ((void*) CURRENT_DSP(STACK,TYPE) >=  \
+                                  (CURRENT_CHUNK(STACK) + (STACK).chunk_size))
+#define CSP_PUSH(STACK)           (*(++(STACK).csp) = malloc((STACK).chunk_size))
+#define CURRENT_DATP(STACK,TYPE)  (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 1])
+#define PREVIOUS_DATP(STACK,TYPE) (((TYPE**)(STACK).dsp)[CHUNKS_LEN(STACK) - 2])
+#define ALLOC_DAT(STACK,TYPE)     (++CURRENT_DATP(STACK,TYPE))
+#define INIT_STACK(STACK,TYPE) \
+  { int i; \
+    (STACK).chunk_size = PAGES_PER_CHUNK * pagesize;            \
+    (STACK).max_dats = (STACK).chunk_size / sizeof (TYPE);     \
+    CSP_PUSH(STACK); \
+    for( i = 0; i < MAX_CHUNKS; i++){ \
+      (STACK).dsp[i] += pagesize; \
+    } \
+  }
+//Stack-specific macros (called directly from code (safety enforcement)
+#define INIT_ODAT()     (INIT_STACK(ocs, struct odat))
+#define CURRENT_ODAT()  (CURRENT_DATP(ocs,struct odat))
+#define ODAT_FULL()     (DATA_FULL(ocs,struct odat))
+#define ODAT_ALLOC()    (ALLOC_DAT(ocs,struct odat))
+#define OCS_FULL()      (CHUNKS_FULL(ocs))
+#define INIT_VDAT()     (INIT_STACK(vcs, struct vdat))
+#define CURRENT_VDAT()  (CURRENT_DATP(vcs,struct vdat))
+#define VDAT_FULL()     (DATA_FULL(vcs,struct vdat))
+#define VDAT_ALLOC()    (ALLOC_DAT(vcs,struct vdat))
+#define VCS_FULL()      (CHUNKS_FULL(vcs))
+#define INIT_CDAT()     (INIT_STACK(ccs, struct cdat))
+#define CURRENT_CDAT()  (CURRENT_DATP(ccs,struct cdat))
+#define CDAT_FULL()     (DATA_FULL(ccs, struct cdat))
+#define CDAT_ALLOC()    (ALLOC_DAT(ccs, struct cdat))
+#define CCS_FULL()      (CHUNKS_FULL(ccs))
+#define INIT_LINK()     (INIT_STACK(lcs, struct link))
+#define CURRENT_LINK()  (CURRENT_DATP(lcs,struct link))
+#define LDAT_FULL()     (DATA_FULL(lcs, struct link))
+#define LDAT_ALLOC()    (ALLOC_DAT(lcs, struct link))
+#define LCS_FULL()      (CHUNKS_FULL(lcs))
+#define INIT_POST()     (INIT_STACK(rcs, struct ref))
+#define CURRENT_POST()  (CURRENT_DATP(pcs,struct ref))
+#define POST_FULL()     (DATA_FULL(pcs,struct ref))
+#define POST_ALLOC()    (ALLOC_DAT(pcs,struct ref))
+#define PCS_FULL()      (CHUNKS_FULL(pcs))
+#define INIT_REF()      (INIT_STACK(rcs, struct ref))
+#define CURRENT_REF()   (CURRENT_DATP(rcs,struct ref))
+#define PREVIOUS_REF()  (PREVIOUS_DATP(rcs, struct ref))
+#define REF_FULL()      (DATA_FULL(rcs,struct ref))
+#define REF_ALLOC()     (ALLOC_DAT(rcs,struct ref))
+#define RCS_FULL()      (CHUNKS_FULL(rcs))
+//Metadata
+#define CURRENT_SET()   (CURRENT_CDAT()->set_list[CURRENT_CDAT()->num_sets])
+#define CURRENT_MODEL() (CURRENT_VDAT()->model_list[CURRENT_VDAT()->num_models])
+
+
+#define CURR_QUAD  (CURR_ODAT->quad_file)
+
+long pagesize;
+
+int num_cdats = 0;
+
+struct cdat* cdat_stack[MAX_CLASSES];
+struct cdat** cdat_stackp;
+
+int num_odats = 0;
+
+int num_vdats = 0;
+
+int num_refs = 0;
+uint64_t ss_ref_id = 0x00FFFFFF; /* system space for ref_ids */
+
+int num_posts = 0;
+
+int num_links = 0;
+
+
+/* The initalization function of the IR. */
+int
+ir_init()
+{
+
+  char root[4] = "root";
+
+  pagesize = sysconf(_SC_PAGESIZE);
+
+  INIT_CDAT();
+  *cdat_stackp = CURRENT_CDAT();
+  memmove((*cdat_stackp)->name, root, 32);
+
+  INIT_ODAT();
+  INIT_VDAT();
+  INIT_LINK();
+  INIT_REF();
+  INIT_POST();
+
+
+  return 0;
+
+}
+
+void
+ir_quit()
+{
+  int i;
+
+  for(i = 0; i < CHUNKS_LEN(ccs) ; i++)
+    {
+      free(ccs.chunks[i]);
+    }
+  for(i = 0; i < CHUNKS_LEN(ocs); i++)
+    {
+      free(ocs.chunks[i]);
+    }
+  for(i = 0; i < CHUNKS_LEN(vcs) ; i++)
+    {
+      free(vcs.chunks[i]);
+    }
+  for(i = 0; i < CHUNKS_LEN(rcs); i++)
+    {
+      free(rcs.chunks[i]);
+    }
+  for(i = 0; i < CHUNKS_LEN(lcs); i++)
+    {
+      free(lcs.chunks[i]);
+    }
+  for(i = 0; i < CHUNKS_LEN(pcs); i++)
+    {
+      free(pcs.chunks[i]);
+    }
+
+}
+
+struct cdat*
+alloc_cdat()
+{
+  num_cdats++;
+  if(CDAT_FULL())
+    { if(CCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) cdats ", num_cdats);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(ccs);
+    }
+  else
+    CDAT_ALLOC();
+
+  return CURRENT_CDAT();
+}
+
+//these should probably be inline
+struct odat*
+alloc_odat
+()
+{
+  num_odats++;
+  if(ODAT_FULL())
+    { if(!OCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) odats ", num_odats);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(ocs);
+    }
+  else
+    ODAT_ALLOC();
+
+  return CURRENT_ODAT();
+}
+
+void
+alloc_vdat
+()
+{ num_vdats++;
+  if(VDAT_FULL())
+    { if(!VCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) vdats ", num_vdats);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(vcs);
+    }
+  else
+    VDAT_ALLOC();
+}
+
+struct link*
+alloc_link
+()
+{ num_links++;
+  if(LDAT_FULL())
+    { if(!LCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) links ", num_links);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(lcs);
+    }
+  else
+    LDAT_ALLOC();
+
+  return CURRENT_LINK();
+
+}
+
+struct ref*
+alloc_ref
+()
+{ num_refs++;
+  if(REF_FULL())
+    { if(!RCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) refs ", num_refs);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(rcs);
+    }
+  else
+    REF_ALLOC();
+
+
+  if(num_refs % 16 == 0)
+    { CURRENT_POST() = CURRENT_REF();
+      inc_posts();
+    }
+
+  return CURRENT_REF();
+}
+
+void
+inc_posts()
+{ num_posts++;
+  if(POST_FULL())
+    { if(!PCS_FULL())
+        { fprintf(stderr, "You have allocated to many (%d) refs ", num_posts);
+          exit(EXIT_FAILURE);
+        }
+      else
+        CSP_PUSH(pcs);
+    }
+  else
+    POST_ALLOC();
+
+}
+
+struct cdat*
+curr_cdat
+()
+{
+  return (*cdat_stackp);
+}
+
+struct odat*
+curr_odat
+()
+{
+  return CURRENT_ODAT();
+}
+struct vdat*
+curr_vdat
+()
+{
+  return CURRENT_VDAT();
+}
+struct set*
+curr_set
+()
+{
+  return &CURRENT_SET();
+}
+struct ref*
+curr_ref
+()
+{
+  return CURRENT_REF();
+}
+struct model*
+curr_model
+()
+{
+  return &CURRENT_MODEL();
+}
diff --git a/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/parser.y b/.org/data/fb/24c302-4743-4a45-845a-4249d2b1a378/parser.y
new file mode 100644 (file)
index 0000000..e6d145c
--- /dev/null
@@ -0,0 +1,206 @@
+/* Asset Package Compiler */
+%code requires{
+  #include <stdint.h>
+}
+%{
+  #include <stdio.h>
+  #include <string.h>
+  #include <dirent.h>
+  #include <png.h>
+  #include <apc/ir.h>
+
+  extern int lexer_init();
+  extern int lexer();
+  #define yylex lexer
+
+
+  void yyerror();
+%}
+%define parse.error verbose
+%define lr.type ielr
+
+%union {
+  uint64_t ref;
+  int val;
+  char *str;
+  void *voidp;
+
+}
+
+ //operators
+%token         CLOPEN    // (
+%token         CLCLOSE   // )
+%token         SOPEN     // {
+%token         SCLOSE    // }
+%token         EOPEN     // [
+%token         ECLOSE    // ]
+%token         VOPEN     // /
+%token         VCLOSE    // \
+
+%token         QOPEN     // !
+%token         QCLOSE    // @
+%token         RT        // &
+%token         HB        // #
+//nonterminal types
+%type <ref> olink
+%type <ref> ele_svlink
+%type <ref> set_svlink
+//terminals
+%token <val> NUM
+%token <str> STR
+%token <val> SS
+%token <str> NAME
+%token <ref> REF
+%token <val> SSD
+%token <voidp> FPTR
+%token <voidp> QPTR
+// Change width, height, num_ptrs to NUM because
+// when scanning, we can't determine which NUM
+// is which. 
+%token <val> WIDTH
+%token <val> HEIGHT
+%token <val> NUM_PTRS
+//precedence
+%precedence LP
+%precedence MP
+%precedence HP
+
+ /* Syntax Directed Translation Scheme of the APC grammar */
+
+/* Rules */
+%%
+cdat_buf:
+class_list
+;
+
+class_list:
+class_list class
+| class
+;
+
+class:
+ CLOPEN NAME {push_cdat($2);} class_block CLCLOSE              {pop_cdat();};
+;
+
+class_block:
+class_list
+| class_list set_list
+| set_list
+;
+
+set_list:
+set_list set
+| set
+;
+
+root:
+RT NUM NUM NUM                                      {insert_root($2, $3, $4);};
+;
+
+quad_file:
+QOPEN QPTR  QCLOSE                                  {insert_quad($2);};
+
+hitbox:
+HB NUM                                              {insert_hitbox($2);}
+;
+
+set_map_data:
+quad_file
+| quad_file hitbox
+| quad_file hitbox root
+| hitbox root
+| hitbox
+| root
+;
+
+set:
+SOPEN set_label set_map_data element_list {alloc_vdat();} vdat SCLOSE           {insert_set(); insert_set_vdatid();};
+| SOPEN set_label set_map_data element_list set_vlink SCLOSE                    {insert_set();};
+| SOPEN set_label set_map_data element_list set_svlink SCLOSE                   {insert_set_svlink($5); insert_set(); };
+| SOPEN set_label element_list {alloc_vdat();} vdat SCLOSE                      {insert_set(); insert_set_vdatid();};
+| SOPEN set_label element_list set_vlink SCLOSE                                 {insert_set(); }
+| SOPEN set_label element_list set_svlink  SCLOSE                               {insert_set_svlink($4); insert_set();};
+| SOPEN olink SCLOSE                                                            {insert_set_olink($2);};
+;
+
+
+set_label:
+HP NAME REF                                          {insert_set_label($2,$3);};
+| LP NAME                                            {insert_set_label($2, -1);};
+;
+
+set_svlink:
+REF
+
+;
+
+set_vlink:
+REF NAME                                             {insert_set_vlink($1, $2);};
+;
+
+olink:
+REF
+;
+
+//parent_id is the set_index of the subclass_index.
+element_list:
+element_list element MP
+| element LP
+;
+
+ele_label:
+HP NAME REF                                          {insert_ele_label($2, $3);};
+| LP NAME                                            {insert_ele_label($2, -1);};
+;
+
+ele_vlink:
+REF NAME                                             {insert_ele_vlink($1, $2);};
+;
+
+ele_svlink:
+REF
+;
+
+element:
+EOPEN ele_label hitbox root {alloc_vdat();} vdat ECLOSE                        {insert_ele(); insert_ele_vdatid();};
+| EOPEN ele_label hitbox root ele_vlink ECLOSE                                 {insert_ele(); };
+| EOPEN ele_label hitbox root ele_svlink ECLOSE                                {insert_ele_svlink($5);insert_ele(); };
+| EOPEN ele_label root {alloc_vdat();} vdat ECLOSE                             {insert_ele(); insert_ele_vdatid();};
+| EOPEN ele_label root ele_vlink ECLOSE                                        {insert_ele(); };
+| EOPEN ele_label root ele_svlink ECLOSE                                       {insert_ele_svlink($4); insert_ele(); };
+| EOPEN olink ECLOSE                                                           {insert_ele_olink($2);};
+;
+
+vdat:
+VOPEN model_list VCLOSE
+;
+
+model_list:
+model_list model
+|  model
+ ;
+
+model:
+spritesheet LP
+;
+
+spritesheet:
+spritesheet HP framesheet
+| framesheet
+;
+
+framesheet:
+SSD NAME REF HEIGHT WIDTH NUM_PTRS frame_pointers LP                     {insert_framesheet($1, $2, $3, $4, $5, $6);};
+;
+
+frame_pointers:
+frame_pointers SSD HP FPTR                                              {insert_frame_pointer($2, $4);};
+| SSD FPTR                                                              {insert_frame_pointer($1, $2);};
+;
+
+%%
+
+void
+yyerror (char const *s)
+{ fprintf(stderr, "%s\n", s);
+}
diff --git a/.org/schedule.org b/.org/schedule.org
new file mode 100644 (file)
index 0000000..b398d1a
--- /dev/null
@@ -0,0 +1,95 @@
+* Project Deadlines
+
+** October
+*** TODO APC
+    :PROPERTIES:
+    :ATTACH_DIR: ~/proj/the_march/src/apc
+    :END:
+**** TODO Scanner   :ATTACH:
+     :PROPERTIES:
+     :Attachments: scanner.c
+     :ID:       2dec5876-7b81-4b9c-97fe-03b152fa276a
+     :END:
+**** TODO Lexer     :ATTACH:
+     :PROPERTIES:
+     :Attachments: lexer.c lexer_lex.rl
+     :ID:       faf3ff67-f8e9-41fe-9a32-2ced4bbf5b99
+     :END:
+**** TODO Parser/IR   :ATTACH:
+     :PROPERTIES:
+     :Attachments: parser.y irmem.c ir.c ir.h
+     :ID:       fb24c302-4743-4a45-845a-4249d2b1a378
+     :END:
+**** TODO Output
+   DEADLINE: <2016-10-20 Thu>
+*** TODO Test Suite for APC
+   DEADLINE: <2016-10-20 Thu>
+*** TODO Animation Viewer
+   DEADLINE: <2016-10-31 Mon>
+
+** November
+*** TODO Core State Machine
+    DEADLINE: <2016-11-10 Thu>
+*** TODO Renderer
+    DEADLINE: <2016-11-10 Thu>
+*** TODO World Generator - Beta
+    DEADLINE: <2016-11-20 Sun>
+*** TODO Core Improvements
+    DEADLINE: <2016-11-20 Sun>
+*** TODO Front-end Hooks
+    DEADLINE: <2016-11-20 Sun>
+*** TODO World Generator - Stable
+    DEADLINE: <2016-11-30 Wed>
+*** TODO Physics Engine
+    SCHEDULED: <2016-11-30 Wed>
+    DEADLINE: <2016-12-20 Tue> 
+*** TODO Actors
+    DEADLINE: <2016-11-30 Wed>
+*** TODO Audio Backend
+    DEADLINE: <2016-11-30 Wed>
+
+** December
+*** TODO Account Management
+    DEADLINE: <2016-12-10 Sat>
+*** TODO User Management
+    DEADLINE: <2016-12-10 Sat>
+*** TODO Controllers - Beta
+    DEADLINE: <2016-12-10 Sat>
+*** TODO Internal Data Handling
+    DEADLINE: <2016-12-10 Sat>
+*** TODO Network Skeleton
+    DEADLINE: <2016-12-10 Sat>
+*** TODO Social Media
+    SCHEDULED: <2016-12-10 Sat>
+*** TODO Core Gameplay
+    SCHEDULED: <2016-12-20 Tue>
+*** TODO Account Management - Stable
+    DEADLINE: <2016-12-20 Tue>
+*** TODO Controllers - Stable
+    DEADLINE: <2016-12-20 Tue>
+    
+** Christmas Holiday (December 21 - January 5)
+*** TODO Gameplay Developments
+*** TODO Front-End Improvements (remote)
+*** TODO AI Start
+*** TODO Website Beta
+
+** January
+*** TODO Gameplay - Win Conditions
+    DEADLINE: <2017-01-10 Tue>
+*** TODO Social Media Integration
+    DEADLINE: <2017-01-10 Tue>
+*** TODO Viable AI (Lua ^ JS)
+    DEADLINE: <2017-01-20 Fri>
+
+** February 
+*** TODO Beta Deployment
+    DEADLINE: <2017-02-01 Wed>
+*** TODO Multiplay Beta
+    DEADLINE: <2017-02-01 Wed>
+*** TODO Early Access for Marketing
+    DEADLINE: <2017-02-01 Wed>
+
+
+
+