+++ /dev/null
-/*!@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
+++ /dev/null
-/*!@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
+++ /dev/null
-/* 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
+++ /dev/null
-/*!@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
+++ /dev/null
-/*!@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
+++ /dev/null
-#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();
-}
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-* 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>
-
-
-
-