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