8030755872443ffb3c1319d4aad0596bede8407b
[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
16 /* functions needed from irmem.c */
17 extern
18 void
19 ir_init(void);
20
21 extern
22 struct cdat*
23 alloc_cdat(void);
24
25 extern
26 struct odat*
27 alloc_odat(void);
28
29 extern
30 void
31 alloc_vdat(void);
32
33 extern
34 struct link*
35 alloc_link(void);
36
37 extern
38 struct ref*
39 alloc_ref(void);
40
41 extern
42 struct cdat*
43 curr_cdat(void);
44
45 extern
46 struct odat*
47 curr_odat(void);
48
49 extern
50 struct vdat*
51 curr_vdat(void);
52
53 extern
54 struct set*
55 curr_set(void);
56
57 extern
58 struct ref*
59 prev_ref(void);
60
61 extern
62 struct quad*
63 curr_quad(void);
64
65 extern
66 struct model*
67 curr_model(void);
68
69 /* struct definitions needed from irmem.c */
70 extern int num_cdats;
71 extern struct cdat** cdat_stackp;
72 extern struct odat* curr_set_odatp;
73 extern uint64_t ss_ref_id;
74
75 extern int num_vdats;
76 /* Dynamically allocate memory for a class data structure,
77 or cdat, after a class has been identified in a grammar.
78 We also create a stack of class pointers so that
79 we can access the cdat during processing of that
80 cdats sets and elements, a requirement because the
81 nature of recursive classes prevents us from accessing
82 the cdat based on the previous index into cdat_buf,
83 which is a list of all allocated cdats*/
84 void
85 push_cdat
86 ( char* name
87 )
88 {
89 struct cdat* curr_cdatp;
90
91 curr_cdatp = alloc_cdat();
92
93 memmove(curr_cdatp->name, name, 32);
94 curr_cdatp->idx = num_cdats;
95
96 /* Set the cdat as a subclass of the previous cdat */
97 (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes] = curr_cdatp;
98 /* Push the cdat onto the cdat_stack */
99 *++cdat_stackp = curr_cdatp;
100
101 }
102
103 void
104 pop_cdat
105 ()
106 {
107 *cdat_stackp = NULL;
108 cdat_stackp--;
109 }
110
111 /* Called in the reduction of a set. While both odats (eles and sets)
112 have identical label terminals, we are unable to give a single grammatical rule
113 for both due to how we allocate odats in the odat buf. Due to the
114 nature of bottom up parsing, the set label is recognized first, and then the
115 sets elements are recognized. This means that after we have processed the sets elemenets,
116 the curr_odat is going to be the last element and NOT the set that was first allocated.
117 To get around this, we create a global variable set_odatp that will store the pointer
118 to the odat when it is first allocated (in insert_set_label()) so that insert_set() can
119 have access to it. */
120
121 void
122 insert_set_label
123 ( char* name,
124 uint64_t ref_id
125 )
126 {
127 struct set* curr_setp;
128
129 curr_setp = curr_set();
130 curr_set_odatp = alloc_odat();
131
132 memmove(curr_set_odatp->name, name, 32);
133 memmove(curr_setp->name, name, 32);
134 curr_setp->ref_id = ref_id;
135
136 }
137 void
138 insert_set_olink
139 ( uint64_t ref_id
140 )
141 {
142 struct set* curr_setp;
143 struct cdat* curr_cdatp;
144 struct link* curr_linkp;
145
146 curr_setp = curr_set();
147 curr_cdatp = curr_cdat();
148 curr_linkp = alloc_link();
149
150 curr_setp->cdat_idx = curr_cdatp->idx;
151 curr_setp->ref_id = ref_id; /* Will be resolved to offset
152 when link is processed */
153 curr_linkp->type = 1;
154 curr_linkp->link_t.olink.ref_id = ref_id;
155 curr_linkp->cdat_idx = curr_cdatp->idx;
156 curr_linkp->set_idx = curr_cdatp->num_sets++;
157 curr_linkp->ele_idx = -1;
158
159 }
160
161 void
162 insert_set_vlink
163 ( uint64_t ref_id,
164 char* anim_name
165 )
166 {
167 struct cdat* curr_cdatp;
168 struct link* curr_linkp;
169
170 curr_cdatp = curr_cdat();
171 curr_linkp = alloc_link();
172
173 /* Insert vlink into link_stack so that it gets processed at
174 output time */
175 curr_linkp->type = 2;
176 curr_linkp->link_t.vlink.ref_id = ref_id;
177 curr_linkp->cdat_idx = curr_cdatp->idx;
178 curr_linkp->set_idx = curr_cdatp->num_sets;
179 curr_linkp->ele_idx = -1;
180 memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);
181
182 }
183
184 /* Svlinks dont have animation names */
185 void
186 insert_set_svlink
187 ( uint64_t ref_id
188 )
189 {
190 struct cdat* curr_cdatp;
191 struct link* curr_linkp;
192
193 curr_cdatp = curr_cdat();
194 curr_linkp = alloc_link();
195
196 /* Insert svlink into link_stack so that it gets processed at
197 output time */
198 curr_linkp->type = 3;
199 curr_linkp->cdat_idx = curr_cdatp->idx;
200 curr_linkp->set_idx = curr_cdatp->num_sets;
201 curr_linkp->ele_idx = -1;
202 curr_linkp->link_t.svlink.ref_id = ref_id;
203
204 }
205
206 /* At the point of reducing to a set, most of the
207 sets odat information has already been populated
208 during the reduction of its right hand side
209 non terminals (hitbox, root, quad_list). */
210 void
211 insert_set
212 ()
213 { uint64_t ref_id;
214 struct odat* curr_odatp;
215 struct cdat* curr_cdatp;
216 struct set* curr_setp;
217 struct ref* prev_refp;
218 struct ref* curr_refp;
219 struct vdat* curr_vdatp;
220
221 curr_odatp = curr_set_odatp; //allocated at insert_set_label, preserved in global space
222 curr_cdatp = curr_cdat();
223 curr_setp = curr_set();
224 prev_refp = prev_ref();
225 curr_refp = alloc_ref();
226 curr_vdatp = curr_vdat();
227
228 curr_vdatp->creator = curr_set_odatp;
229
230 curr_setp->cdat_idx = curr_cdatp->idx; //does a set need its class idx?
231 memmove(curr_setp->name, curr_odatp->name, 32);
232 curr_cdatp->num_sets++;
233
234 curr_odatp->cdat_idx = curr_cdatp->idx;
235 curr_odatp->refp = curr_refp;
236
237 ref_id = curr_setp->ref_id; // ref_id set by insert_set_label(name, ref_id)
238
239 if(ref_id == -1) /* user did not define a ref_id */
240 { ref_id = ss_ref_id;
241 ss_ref_id++;
242 }
243
244 curr_refp->ref_id = ref_id;
245 curr_refp->lastref = prev_refp;
246 curr_refp->odatp = curr_odatp;
247 prev_refp->nextref = curr_refp;
248
249
250
251 }
252 /* Created as a seperate function, instead of setting the ODATS vdat_id and
253 calling inc_vdat() inside of insert_set(), to account for the set reduction
254 where a vdat is not created (o/v/svlinks). */
255 void
256 insert_set_vdatid
257 ()
258 {
259 curr_set_odatp->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks
260 curr_set_odatp = NULL; //So this sets odat cant be modified after (which would be a bug)
261 }
262
263 /* Populates both the odat name and ref_id
264 for odat and ele */
265 void
266 insert_ele_label
267 ( char* name,
268 uint64_t ref_id
269 )
270 {
271 struct odat* curr_odatp;
272
273 curr_odatp = alloc_odat();
274
275 memmove(curr_odatp->name, name, 32);
276 curr_odatp->ref_id = ref_id;
277
278 }
279
280 /* We don't make an odat here, at output time we will resolve
281 the ref_id to the corresponding odat. */
282 void
283 insert_ele_olink
284 ( uint64_t ref_id
285 )
286 {
287 struct cdat* curr_cdatp;
288 struct set* curr_setp;
289 struct ele* curr_elep;
290 struct link* curr_linkp;
291
292 curr_cdatp = curr_cdat();
293 //curr_elep = curr_ele();
294 curr_linkp = alloc_link();
295
296 //curr_elep->cdat_idx = curr_cdatp->idx;
297 //curr_elep->ref_id = ref_id;
298
299 curr_linkp->type = 1;
300 curr_linkp->link_t.olink.ref_id = ref_id;
301 curr_linkp->cdat_idx = curr_cdatp->idx;
302 curr_linkp->set_idx = curr_cdatp->num_sets++;
303 //curr_linkp->ele_idx = curr_setp->num_ele++;
304
305 }
306
307 void
308 insert_ele_vlink
309 ( uint64_t ref_id,
310 char* anim_name
311 )
312 {
313 struct cdat* curr_cdatp;
314 struct set* curr_setp;
315 struct link* curr_linkp;
316
317 curr_cdatp = curr_cdat();
318 curr_setp = curr_set();
319 curr_linkp = alloc_link();
320
321 /* Insert vlink into link_stack so that it gets processed at
322 output time */
323 curr_linkp->cdat_idx = curr_cdatp->idx;
324 curr_linkp->type = 2;
325 curr_linkp->set_idx = curr_cdatp->num_sets;
326 //curr_linkp->ele_idx = curr_setp->num_ele;
327 curr_linkp->link_t.vlink.ref_id = ref_id;
328 memmove(curr_linkp->link_t.vlink.anim_name, anim_name, 32);
329
330 }
331
332 void
333 insert_ele_svlink
334 ( uint64_t ref_id
335 )
336 {
337 struct cdat* curr_cdatp;
338 struct set* curr_setp;
339 struct link* curr_linkp;
340
341 curr_cdatp = curr_cdat();
342 curr_setp = curr_set();
343 curr_linkp = alloc_link();
344
345 curr_linkp->cdat_idx = curr_cdatp->idx;
346 curr_linkp->type = 3;
347
348 //curr_linkp->ele_idx = curr_setp->num_ele;
349 curr_linkp->link_t.svlink.ref_id = ref_id;
350
351
352 }
353
354 //Insert element into odat_buf and cdatpages
355 void
356 insert_ele()
357 {
358 uint64_t ref_id;
359 struct cdat* curr_cdatp;
360 struct odat* curr_odatp;
361 struct vdat* curr_vdatp;
362 struct set* curr_setp;
363 struct ele* curr_elep;
364 struct ref* curr_refp;
365 struct ref* prev_refp;
366
367
368 curr_odatp = curr_odat(); //malloced @ insert_ele_label
369 curr_vdatp = curr_vdat();
370 curr_setp = curr_set();
371 curr_refp = alloc_ref();
372 prev_refp = prev_ref();
373
374 curr_vdatp->creator = curr_odatp;
375
376 /* Populate odat for ele */
377 curr_odatp->cdat_idx = curr_cdatp->idx;
378 curr_odatp->refp = curr_refp;
379
380 ref_id = curr_odatp->ref_id;
381
382
383 if(ref_id == -1) /* user did not define a ref_id so */
384 { ref_id = ss_ref_id;
385 ss_ref_id++;
386 }
387
388 curr_refp->ref_id = ref_id;
389 curr_refp->lastref = prev_refp;
390 curr_refp->odatp = curr_odatp;
391 prev_refp->nextref = curr_refp;
392
393 }
394
395 void
396 insert_ele_vdatid
397 ()
398 { struct odat* curr_odatp;
399 curr_odatp = curr_odat();
400 curr_odatp->vdat_id = num_vdats;
401 }
402
403 void
404 insert_quad
405 ( void* quad_filep
406 )
407 {
408
409 /* struct quad* curr_quadp; */
410 /* struct odat* curr_odatp; */
411
412 /* curr_quadp = curr_quad(); */
413 /* curr_odatp = curr_odat(); */
414
415 /* curr_quadp->x = x; */
416 /* curr_quadp->y = y; */
417 /* curr_quadp->z = z; */
418 /* curr_quadp->ref_id = ref_id; */
419 /* curr_odatp->num_quads++; */
420 struct odat* curr_odatp;
421
422 curr_odatp->quad_filep = quad_filep;
423 }
424
425 /* Inserting the hitbox into the set
426 odat. Elements that don't have
427 a hitbox will use the sets root. */
428 void
429 insert_hitbox
430 ( int hitbox
431 )
432 { struct odat* curr_odatp;
433
434 curr_odatp = curr_odat();
435 curr_odatp->hitbox = hitbox;
436 }
437
438 /* Inserting the root into the set
439 odat. Elements that don't have
440 a root will use the sets root. */
441 void
442 insert_root
443 ( int x,
444 int y,
445 int z
446 )
447 { struct odat* curr_odatp;
448
449 curr_odatp = curr_odat();
450 curr_odatp->root.x = x;
451 curr_odatp->root.y = y;
452 curr_odatp->root.z = z;
453 }
454
455
456 void
457 insert_framesheet
458 ( char direction,
459 char* name,
460 uint64_t ref_id,
461 int height ,
462 int width,
463 int num_frames
464 )
465 { struct vdat* curr_vdatp;
466 struct model* curr_modelp;
467
468 curr_vdatp = curr_vdat();
469 curr_modelp = curr_model();
470
471 curr_modelp->spritesheet[(int)direction].height = height;
472 curr_modelp->spritesheet[(int)direction].width = width;
473 curr_modelp->spritesheet[(int)direction].num_frames = num_frames;
474 curr_vdatp->num_models++;
475 }
476
477 void
478 insert_frame_pointer
479 ( char direction,
480 void* frame
481 )
482 { struct model* curr_modelp;
483
484 curr_modelp = curr_model();
485
486 curr_modelp->spritesheet[(int)direction].frames[curr_modelp->spritesheet[(int)direction].num_frames++] = frame;
487 }
488