forgot to commit ir.c
[henge/webcc.git] / src / apc / ir.c
1 /*!@file
2 \brief IR Memory Implementation
3 \details Intermediary memory management
4 \author Jordan Lavatai
5 \date Aug 2016
6 ----------------------------------------------------------------------------*/
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdint.h> //uint64_t
10 #include <string.h> //memmove
11 #include <stdlib.h> //malloc
12 #include <apc/ir.h>
13
14
15 void
16 ir_init(void);
17 void
18 malloc_cdat(void);
19
20
21
22 /* The initalization function of the IR. Mallocs the
23 first c/v/odat and the first links and refs and
24 inits the cdat_stack */
25 void
26 ir_init()
27 {
28
29 /* Init root cdat and stack */
30 char root[4] = "root";
31
32 cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof(struct cdat) );
33 cdat_buf[num_cdats]->idx = 0;
34 memmove(cdat_buf[num_cdats]->name, root, 4);
35
36 cdat_stackp = cdat_stack;
37 *cdat_stackp = cdat_buf[num_cdats++];
38
39 }
40
41 //TODO: FREE MEMORY!
42 void
43 malloc_cdat()
44 {
45 if(curr_max_cdats <= num_cdats)
46 { if( (realloc((void*) cdat_buf, PTRS_IN_PAGE * 4)) == NULL)
47 perror("realloc cdat_buf failed");
48 curr_max_cdats += PTRS_IN_PAGE;
49 if( (realloc( (void*) cdat_stack, PTRS_IN_PAGE * 4)) == NULL) //increase cdat_stack also
50 perror("realloc cdat_stack failed");
51 }
52 if( (cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof (struct cdat)) ) == NULL )
53 perror("malloc cdat failed");
54
55
56 }
57
58 /* Dynamically allocate memory for a class data structure,
59 or cdat, after a class has been identified in a grammar.
60 We also create a stack of class pointers so that
61 we can access the cdat during processing of that
62 cdats sets and elements, a requirement because the
63 nature of recursive classes prevents us from accessing
64 the cdat based on the previous index into cdat_buf,
65 which is a list of all allocated cdats*/
66 void
67 push_cdat
68 ( char* name
69 )
70 {
71 malloc_cdat();
72
73 memmove(cdat_buf[num_cdats]->name, name, 32);
74 cdat_buf[num_cdats]->idx = num_cdats;
75
76 /* Set the cdat as a class of the previous cdat */
77 (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes++] = cdat_buf[num_cdats];
78
79 /* Push the cdat onto the cdat_stack */
80 *++cdat_stackp = cdat_buf[num_cdats++];
81
82 }
83
84 void
85 pop_cdat
86 ()
87 {
88 *cdat_stackp = NULL;
89 cdat_stackp--;
90 }
91
92 /* Called in the reduction of a set. While both odats (eles and sets)
93 have identical label terminals, we are unable to give a single grammatical rule
94 for both due to how we allocate odats in the odat buf. Due to the
95 nature of bottom up parsing, all the elements will be inserted into the
96 odat_buf first, and then the set that contains these element is inserted. Since
97 the sets label comes before the element list in the grammar, we would be giving an element
98 a set label in its respective odat, which would then be replaced by the
99 elements label. Instead, we store the label in the sets representation inside
100 CURR_CDAT and after we are done parsing the element_list and know that the CURR_ODAT
101 is the set, we populate the sets label members in CURR_ODAT with the values we stored
102 previously in CURR_CDAT. */
103
104 void
105 insert_set_label
106 ( char* name,
107 uint64_t ref_id
108 )
109 {
110 struct set* curr_set;
111
112 curr_set = curr_set();
113 memmove(curr_set.name,name,32);
114 curr_set.ref_id = ref_id;
115
116 }
117 void
118 insert_set_olink
119 ( uint64_t ref_id
120 )
121 {
122 struct set* curr_set;
123 struct cdat* curr_cdat;
124 struct link* curr_link;
125
126 curr_set = curr_set();
127 curr_cdat = curr_cdat();
128 curr_link = alloc_link();
129
130 curr_set.cdat_idx = curr_cdat->idx;
131 curr_set.ref_id = ref_id; /* Will be resolved to offset
132 when link is processed */
133 curr_link->type = 1;
134 curr_link->link_t.olink.ref_id = ref_id;
135 curr_link->cdat_idx = curr_cdat->idx;
136 curr_link->set_idx = curr_cdat->num_sets++;
137 curr_link->ele_idx = -1;
138
139 }
140
141 void
142 insert_set_vlink
143 ( uint64_t ref_id,
144 char* anim_name
145 )
146 {
147 struct cdat* curr_cdat;
148 struct link* curr_link;
149
150 curr_cdat = curr_cdat();
151 curr_link = alloc_link();
152
153 /* Insert vlink into link_stack so that it gets processed at
154 output time */
155 curr_link->type = 2;
156 curr_link->cdat_idx = curr_cdat->idx;
157 curr_link->set_idx = curr_cdat->num_sets;
158 curr_link->link_t.vlink.ref_id = ref_id;
159 memmove(curr_link->link_t.vlink.anim_name, anim_name, 32);
160
161 }
162
163 /* Svlinks dont have animation names */
164 void
165 insert_set_svlink
166 ( uint64_t ref_id
167 )
168 {
169 struct cdat* curr_cdat;
170 struct link* curr_link;
171
172 curr_cdat = curr_cdat();
173 curr_link = alloc_link();
174
175 /* Insert vlink into link_stack so that it gets processed at
176 output time */
177 curr_link->type = 3;
178 curr_link->cdat_idx = curr_cdat->idx;
179 curr_link->set_idx = curr_cdat->num_sets;
180 curr_link->link_t.svlink.ref_id = ref_id;
181
182 }
183
184 /* At the point of reducing to a set, most of the
185 sets odat information has already been populated
186 during the reduction of its right hand side
187 non terminals (hitbox, root, quad_list). */
188 void
189 insert_set
190 ()
191 {
192 struct odat* curr_odat;
193 struct cdat* curr_cdat;
194 struct ref* prev_ref;
195 struct ref* curr_ref;
196
197 curr_odat = alloc_odat();
198 curr_cdat = curr_cdat();
199 curr_set = curr_set();
200 prev_ref = prev_ref();
201 curr_ref = alloc_ref();
202
203 ref_id = curr_set.ref_id; // ref_id set by insert_set_label(name, ref_id)
204
205 curr_set.cdat_idx = curr_cdat->idx;
206 memmove(curr_odat->name, curr_set.name, 32);
207 curr_cdat.num_sets++;
208
209 curr_odat->cdat_idx = curr_cdaat->idx;
210 curr_odat->refp = curr_ref;
211
212
213 curr_ref->lastref = prev_ref;
214 prev_ref->nextref = curr_ref;
215 curr_ref->odatp = curr_odat;
216
217
218 if(ref_id == -1) /* user did not define a ref_id so */
219 { ref_id = ss_ref_id;
220 ss_ref_id++;
221 }
222
223 curr_ref->ref_id = ref_id;
224
225 }
226 /* Created as a seperate function, instead of setting the ODATS vdat_id and
227 calling inc_vdat() inside of insert_set(), to account for the set reduction
228 where a vdat is not created (o/v/svlinks). */
229
230 void
231 insert_vdat_id
232 ()
233 {
234 struct odat* curr_odat;
235 curr_odat = curr_odat();
236 curr_odat->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks
237 }
238
239 /* Populates both the odat name and ref_id
240 for element. */
241 void
242 insert_ele_label
243 ( char* name,
244 uint64_t ref_id
245 )
246 {
247 struct ele* curr_ele;
248
249 curr_ele = curr_ele();
250
251 memmove(curr_ele.name, name, 32);
252 curr_ele.ref_id = ref_id;
253 }
254
255 void
256 insert_ele_olink
257 ( uint64_t ref_id
258 )
259 {
260 CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
261 CURR_CDAT->CURR_SET.CURR_ELE.ref_id = ref_id; /* Will be resolved to offset
262 when link is processed */
263 CURR_LINK->type = 1;
264 CURR_LINK->link_t.olink.ref_id = ref_id;
265 CURR_LINK->cdat_idx = CURR_CDAT->idx;
266 CURR_LINK->set_idx = CURR_CDAT->num_sets++;
267 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele++;
268
269 }
270
271 void
272 insert_ele_vlink
273 ( uint64_t ref_id,
274 char* anim_name
275 )
276 {
277
278 /* Insert vlink into link_stack so that it gets processed at
279 output time */
280 CURR_LINK->cdat_idx = CURR_CDAT->idx;
281 CURR_LINK->type = 2;
282 CURR_LINK->set_idx = CURR_CDAT->num_sets;
283 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
284 CURR_LINK->link_t.vlink.ref_id = ref_id;
285 memmove(CURR_LINK->link_t.vlink.anim_name, anim_name, 32);
286
287 }
288
289 void
290 insert_ele_svlink
291 ( uint64_t ref_id
292 )
293 {
294
295 CURR_LINK->cdat_idx = CURR_CDAT->idx;
296 CURR_LINK->type = 3;
297 CURR_LINK->set_idx = CURR_CDAT->num_sets;
298 CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele;
299 CURR_LINK->link_t.svlink.ref_id = ref_id;
300
301
302 }
303
304 //Insert element into odat_buf and cdatpages
305 void
306 insert_ele()
307 {
308 uint64_t ref_id;
309
310 ref_id = CURR_CDAT->CURR_SET.CURR_ELE.ref_id;
311
312 CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx;
313 memmove(CURR_ODAT->name,CURR_CDAT->CURR_SET.CURR_ELE.name, 32);
314 CURR_CDAT->CURR_SET.num_ele++;
315
316 CURR_ODAT->cdat_idx = CURR_CDAT->idx;
317 CURR_ODAT->refp = CURR_REF;
318
319 if(ref_id == -1) /* user did not define a ref_id so */
320 { ref_id = ss_ref_id;
321 ss_ref_id++;
322 }
323
324 CURR_REF->ref_id = ref_id;
325
326 inc_odat();
327 inc_ref();
328
329 }
330
331 void
332 insert_framesheet
333 ( char direction,
334 char* name,
335 uint64_t ref_id,
336 int height ,
337 int width,
338 int num_frames
339 )
340 {
341 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].height = height;
342 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].width = width;
343 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames = num_frames;
344 CURR_VDAT->num_models++;
345 }
346
347 void
348 insert_quad
349 ( int x,
350 int y,
351 int z,
352 uint64_t ref_id
353 )
354 #define CURR_QUAD (CURR_ODAT->quad_list[CURR_ODAT->num_quads])
355 {
356 CURR_QUAD.x = x;
357 CURR_QUAD.y = y;
358 CURR_QUAD.z = z;
359 CURR_QUAD.ref_id = ref_id;
360 CURR_ODAT->num_quads++;
361 }
362
363 /* Inserting the hitbox into the set
364 odat. Elements that don't have
365 a hitbox will use the sets root. */
366 void
367 insert_hitbox
368 ( int hitbox
369 )
370 {
371 CURR_ODAT->hitbox = hitbox;
372 }
373
374 /* Inserting the root into the set
375 odat. Elements that don't have
376 a root will use the sets root. */
377 void
378 insert_root
379 ( int x,
380 int y,
381 int z
382 )
383 {
384
385 CURR_ODAT->root.x = x;
386 CURR_ODAT->root.y = y;
387 CURR_ODAT->root.z = z;
388 }
389
390 void
391 insert_frame_pointer
392 ( char direction,
393 void* frame
394 )
395 {
396 CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].frames[CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames++] = frame;
397 }
398