--- /dev/null
+/*!@file
+ \brief IR Memory Implementation
+ \details Intermediary memory management
+ \author Jordan Lavatai
+ \date Aug 2016
+ ----------------------------------------------------------------------------*/
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h> //uint64_t
+#include <string.h> //memmove
+#include <stdlib.h> //malloc
+#include <apc/ir.h>
+
+
+void
+ir_init(void);
+void
+malloc_cdat(void);
+
+
+
+/* The initalization function of the IR. Mallocs the
+ first c/v/odat and the first links and refs and
+ inits the cdat_stack */
+void
+ir_init()
+{
+
+ /* Init root cdat and stack */
+ char root[4] = "root";
+
+ cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof(struct cdat) );
+ cdat_buf[num_cdats]->idx = 0;
+ memmove(cdat_buf[num_cdats]->name, root, 4);
+
+ cdat_stackp = cdat_stack;
+ *cdat_stackp = cdat_buf[num_cdats++];
+
+}
+
+//TODO: FREE MEMORY!
+void
+malloc_cdat()
+{
+ if(curr_max_cdats <= num_cdats)
+ { if( (realloc((void*) cdat_buf, PTRS_IN_PAGE * 4)) == NULL)
+ perror("realloc cdat_buf failed");
+ curr_max_cdats += PTRS_IN_PAGE;
+ if( (realloc( (void*) cdat_stack, PTRS_IN_PAGE * 4)) == NULL) //increase cdat_stack also
+ perror("realloc cdat_stack failed");
+ }
+ if( (cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof (struct cdat)) ) == NULL )
+ perror("malloc cdat failed");
+
+
+}
+
+/* Dynamically allocate memory for a class data structure,
+ or cdat, after a class has been identified in a grammar.
+ We also create a stack of class pointers so that
+ we can access the cdat during processing of that
+ cdats sets and elements, a requirement because the
+ nature of recursive classes prevents us from accessing
+ the cdat based on the previous index into cdat_buf,
+ which is a list of all allocated cdats*/
+void
+push_cdat
+( char* name
+)
+{
+ malloc_cdat();
+
+ memmove(cdat_buf[num_cdats]->name, name, 32);
+ cdat_buf[num_cdats]->idx = num_cdats;
+
+ /* Set the cdat as a class of the previous cdat */
+ (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes++] = cdat_buf[num_cdats];
+
+ /* Push the cdat onto the cdat_stack */
+ *++cdat_stackp = cdat_buf[num_cdats++];
+
+}
+
+void
+pop_cdat
+()
+{
+ *cdat_stackp = NULL;
+ cdat_stackp--;
+}
+
+/* Called in the reduction of a set. While both odats (eles and sets)
+ have identical label terminals, we are unable to give a single grammatical rule
+ for both due to how we allocate odats in the odat buf. Due to the
+ nature of bottom up parsing, all the elements will be inserted into the
+ odat_buf first, and then the set that contains these element is inserted. Since
+ the sets label comes before the element list in the grammar, we would be giving an element
+ a set label in its respective odat, which would then be replaced by the
+ elements label. Instead, we store the label in the sets representation inside
+ CURR_CDAT and after we are done parsing the element_list and know that the CURR_ODAT
+ is the set, we populate the sets label members in CURR_ODAT with the values we stored
+ previously in CURR_CDAT. */
+
+void
+insert_set_label
+( char* name,
+ uint64_t ref_id
+)
+{
+ struct set* curr_set;
+
+ curr_set = curr_set();
+ memmove(curr_set.name,name,32);
+ curr_set.ref_id = ref_id;
+
+}
+void
+insert_set_olink
+( uint64_t ref_id
+)
+{
+ struct set* curr_set;
+ struct cdat* curr_cdat;
+ struct link* curr_link;
+
+ curr_set = curr_set();
+ curr_cdat = curr_cdat();
+ curr_link = alloc_link();
+
+ curr_set.cdat_idx = curr_cdat->idx;
+ curr_set.ref_id = ref_id; /* Will be resolved to offset
+ when link is processed */
+ curr_link->type = 1;
+ curr_link->link_t.olink.ref_id = ref_id;
+ curr_link->cdat_idx = curr_cdat->idx;
+ curr_link->set_idx = curr_cdat->num_sets++;
+ curr_link->ele_idx = -1;
+
+}
+
+void
+insert_set_vlink
+( uint64_t ref_id,
+ char* anim_name
+)
+{
+ struct cdat* curr_cdat;
+ struct link* curr_link;
+
+ curr_cdat = curr_cdat();
+ curr_link = alloc_link();
+
+ /* Insert vlink into link_stack so that it gets processed at
+ output time */
+ curr_link->type = 2;
+ curr_link->cdat_idx = curr_cdat->idx;
+ curr_link->set_idx = curr_cdat->num_sets;
+ curr_link->link_t.vlink.ref_id = ref_id;
+ memmove(curr_link->link_t.vlink.anim_name, anim_name, 32);
+
+}
+
+/* Svlinks dont have animation names */
+void
+insert_set_svlink
+( uint64_t ref_id
+)
+{
+ struct cdat* curr_cdat;
+ struct link* curr_link;
+
+ curr_cdat = curr_cdat();
+ curr_link = alloc_link();
+
+ /* Insert vlink into link_stack so that it gets processed at
+ output time */
+ curr_link->type = 3;
+ curr_link->cdat_idx = curr_cdat->idx;
+ curr_link->set_idx = curr_cdat->num_sets;
+ curr_link->link_t.svlink.ref_id = ref_id;
+
+}
+
+/* At the point of reducing to a set, most of the
+ sets odat information has already been populated
+ during the reduction of its right hand side
+ non terminals (hitbox, root, quad_list). */
+void
+insert_set
+()
+{
+ struct odat* curr_odat;
+ struct cdat* curr_cdat;
+ struct ref* prev_ref;
+ struct ref* curr_ref;
+
+ curr_odat = alloc_odat();
+ curr_cdat = curr_cdat();
+ curr_set = curr_set();
+ prev_ref = prev_ref();
+ curr_ref = alloc_ref();
+
+ ref_id = curr_set.ref_id; // ref_id set by insert_set_label(name, ref_id)
+
+ curr_set.cdat_idx = curr_cdat->idx;
+ memmove(curr_odat->name, curr_set.name, 32);
+ curr_cdat.num_sets++;
+
+ curr_odat->cdat_idx = curr_cdaat->idx;
+ curr_odat->refp = curr_ref;
+
+
+ curr_ref->lastref = prev_ref;
+ prev_ref->nextref = curr_ref;
+ curr_ref->odatp = curr_odat;
+
+
+ if(ref_id == -1) /* user did not define a ref_id so */
+ { ref_id = ss_ref_id;
+ ss_ref_id++;
+ }
+
+ curr_ref->ref_id = ref_id;
+
+}
+/* Created as a seperate function, instead of setting the ODATS vdat_id and
+ calling inc_vdat() inside of insert_set(), to account for the set reduction
+ where a vdat is not created (o/v/svlinks). */
+
+void
+insert_vdat_id
+()
+{
+ struct odat* curr_odat;
+ curr_odat = curr_odat();
+ curr_odat->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks
+}
+
+/* Populates both the odat name and ref_id
+ for element. */
+void
+insert_ele_label
+( char* name,
+ uint64_t ref_id
+)
+{
+ struct ele* curr_ele;
+
+ curr_ele = curr_ele();
+
+ memmove(curr_ele.name, name, 32);
+ curr_ele.ref_id = ref_id;
+}
+
+void
+insert_ele_olink
+( uint64_t ref_id
+)
+{
+ CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
+ CURR_CDAT->CURR_SET.CURR_ELE.ref_id = ref_id; /* Will be resolved to offset
+ when link is processed */
+ CURR_LINK->type = 1;
+ CURR_LINK->link_t.olink.ref_id = ref_id;
+ CURR_LINK->cdat_idx = CURR_CDAT->idx;
+ CURR_LINK->set_idx = CURR_CDAT->num_sets++;
+ CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele++;
+
+}
+
+void
+insert_ele_vlink
+( uint64_t ref_id,
+ char* anim_name
+)
+{
+
+ /* Insert vlink into link_stack so that it gets processed at
+ output time */
+ CURR_LINK->cdat_idx = CURR_CDAT->idx;
+ CURR_LINK->type = 2;
+ CURR_LINK->set_idx = CURR_CDAT->num_sets;
+ CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
+ CURR_LINK->link_t.vlink.ref_id = ref_id;
+ memmove(CURR_LINK->link_t.vlink.anim_name, anim_name, 32);
+
+}
+
+void
+insert_ele_svlink
+( uint64_t ref_id
+)
+{
+
+ CURR_LINK->cdat_idx = CURR_CDAT->idx;
+ CURR_LINK->type = 3;
+ CURR_LINK->set_idx = CURR_CDAT->num_sets;
+ CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
+ CURR_LINK->link_t.svlink.ref_id = ref_id;
+
+
+}
+
+//Insert element into odat_buf and cdatpages
+void
+insert_ele()
+{
+ uint64_t ref_id;
+
+ ref_id = CURR_CDAT->CURR_SET.CURR_ELE.ref_id;
+
+ CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
+ memmove(CURR_ODAT->name,CURR_CDAT->CURR_SET.CURR_ELE.name, 32);
+ CURR_CDAT->CURR_SET.num_ele++;
+
+ CURR_ODAT->cdat_idx = CURR_CDAT->idx;
+ CURR_ODAT->refp = CURR_REF;
+
+ if(ref_id == -1) /* user did not define a ref_id so */
+ { ref_id = ss_ref_id;
+ ss_ref_id++;
+ }
+
+ CURR_REF->ref_id = ref_id;
+
+ inc_odat();
+ inc_ref();
+
+}
+
+void
+insert_framesheet
+( char direction,
+ char* name,
+ uint64_t ref_id,
+ int height ,
+ int width,
+ int num_frames
+)
+{
+ CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].height = height;
+ CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].width = width;
+ CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames = num_frames;
+ CURR_VDAT->num_models++;
+}
+
+void
+insert_quad
+( int x,
+ int y,
+ int z,
+ uint64_t ref_id
+)
+#define CURR_QUAD (CURR_ODAT->quad_list[CURR_ODAT->num_quads])
+{
+ CURR_QUAD.x = x;
+ CURR_QUAD.y = y;
+ CURR_QUAD.z = z;
+ CURR_QUAD.ref_id = ref_id;
+ CURR_ODAT->num_quads++;
+}
+
+/* Inserting the hitbox into the set
+ odat. Elements that don't have
+ a hitbox will use the sets root. */
+void
+insert_hitbox
+( int hitbox
+)
+{
+ CURR_ODAT->hitbox = hitbox;
+}
+
+/* Inserting the root into the set
+ odat. Elements that don't have
+ a root will use the sets root. */
+void
+insert_root
+( int x,
+ int y,
+ int z
+)
+{
+
+ CURR_ODAT->root.x = x;
+ CURR_ODAT->root.y = y;
+ CURR_ODAT->root.z = z;
+}
+
+void
+insert_frame_pointer
+( char direction,
+ void* frame
+)
+{
+ CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].frames[CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames++] = frame;
+}
+