ir compiling!
[henge/apc.git] / src / ir.c
1 /*!@file
2 \brief IR Memory Implementation
3 \details Intermediary memory management
4 \author Jordan Lavatai
5 \date Aug 2016
6 ----------------------------------------------------------------------------*/
7 /* Standard */
8 #include <stdlib.h> //exit, malloc
9 #include <stdio.h> //print
10 #include <stdarg.h> //va_args
11 #include <stdint.h> //uint64_t
12 #include <string.h> //memset, str*
13 /* Unicode */
14 #include <unistd.h> //u8_* functions
15 #include <unitypes.h> //uint8_t as a char
16 #include <unistr.h> //u32_cpy
17 /* Local */
18 #include "apc.h"
19 #include "ir.h"
20 /* Public */
21 int ir_init(void);
22 void ir_quit(void);
23 int ir_linker(void);
24 int ir_condenser(void);
25 /* Memory allocation structures */
26 struct pagenode_t;
27 struct pagenode_header_t {
28 struct pagenode_t* next;
29 char* head;
30 };
31 struct pagenode_t {
32 struct pagenode_header_t header;
33 char root[];
34 };
35 struct pagelist_t {
36 struct pagenode_t* root, * head;
37 size_t pagesize;
38 };
39 struct ir_namelist_t;
40 struct ir_namelist_t
41 { struct ir_namelist_t* nextsib;
42 uint8_t* name;
43 };
44 struct ir_classld_t
45 { struct ir_class_t* root_class;
46 struct ir_namelist_t* namelist, * namelist_head;
47 };
48 struct ir_setld_t
49 { struct ir_classld_t* classld;
50 long long ref;
51 struct ir_namelist_t* namelist, * namelist_head;
52 };
53 /* Set data mem */
54 struct ir_setdata_header_t
55 { enum dtype type;
56 uint8_t* src_filename, * data_name;
57 union ir_setdata_t* nextsib;
58 };
59 struct ir_frameinfo_t
60 { int facing, w, h; };
61 struct ir_framedata_t
62 { struct ir_setdata_header_t header;
63 struct ir_frameinfo_t frameinfo;
64 };
65 struct ir_framebox_t
66 { struct ir_setdata_header_t header;
67 struct ir_framedata_t framesheets[FACING_MAX];
68 struct ir_framedata_t mapsheets[FACING_MAX];
69 };
70 struct ir_simplex_t { struct ir_setdata_header_t header; };
71 struct ir_link_t
72 { struct ir_setdata_header_t header;
73 struct ir_classld_t* classld;
74 struct ir_setld_t* setld;
75 enum ltype type;
76 };
77 union ir_setdata_t
78 { struct ir_setdata_header_t header;
79 struct ir_framebox_t framebox;
80 struct ir_framedata_t framesheet;
81 struct ir_framedata_t mapsheet;
82 struct ir_simplex_t audio;
83 struct ir_link_t link;
84 };
85 struct ir_class_t
86 { struct ir_class_t* nextchild, * nextsib;
87 struct ir_set_t* root_set;
88 uint8_t* name;
89 };
90 struct ir_set_t
91 { struct ir_set_t* nextchild, * nextsib;
92 struct ir_class_t* class;
93 long long ref;
94 uint8_t* name;
95 struct ir_framebox_t* frameboxes;
96 struct ir_simplex_t* audio;
97 struct ir_link_t* links;
98 };
99 /* Functions */
100 static inline
101 int init_pagelist(struct pagelist_t*,size_t);
102 static inline
103 struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*, uint8_t*);
104 static
105 void ir_free_pagenodes(struct pagenode_t*);
106 static inline
107 int bytes_identical(uint8_t*,uint8_t*);
108 static
109 void* stack_alloc(size_t);
110 static
111 uint8_t* name_alloc(uint8_t*);
112 static inline
113 union ir_setdata_t* ir_framedata (enum dtype,uint8_t*,apc_facing,int,int);
114 /* Function-Like Macros */
115 #define do_warn() do { \
116 } while (0)
117 #define wprint(str) do { \
118 fprintf(stderr, str); \
119 do_warn(); \
120 } while (0)
121 #define wprintf(fmt,...) do { \
122 fprintf(stderr, fmt, __VA_ARGS__); \
123 do_warn(); \
124 } while (0)
125 #define do_error() do { \
126 exit(-1); \
127 } while (0)
128 #define eprint(str) do { \
129 fprintf(stderr, str); \
130 do_error(); \
131 } while (0)
132 #define eprintf(fmt,...) do { \
133 fprintf(stderr, fmt, __VA_ARGS__); \
134 do_error(); \
135 } while (0)
136 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
137 #define DATA_PAGESIZE (sys_pagesize)
138 #define NAME_PAGESIZE (APC_NAME_MAX * 1024)
139 #define PL_HEADERSIZE (sizeof(struct pagenode_header_t))
140 #define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
141 #define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
142 /* Memory */
143 extern //apc.c
144 long sys_pagesize;
145 static
146 struct pagelist_t datapages, namepages;
147 static
148 struct ir_class_t root_class = { .name = (uint8_t*)"." };
149
150 /* Init */
151 int ir_init
152 ( void )
153 { if (init_pagelist(&datapages, (size_t)DATA_PAGESIZE))
154 eprint("Memory allocation error\n");
155 if (init_pagelist(&namepages, (size_t)NAME_PAGESIZE))
156 eprint("Memory allocation error\n");
157 return 0;
158 }
159
160 static inline
161 int init_pagelist
162 ( struct pagelist_t* pl,
163 size_t size
164 )
165 { pl->pagesize = size;
166 pl->root = (struct pagenode_t*) calloc(size,1);
167 if (pl->root == NULL)
168 return -1;
169 pl->root->header.head = pl->root->root;
170 pl->head = pl->root;
171 return 0;
172 }
173
174 /* Quit/Cleanup
175 Recursively clean pagenode linked list
176 */
177 void ir_quit
178 ( void )
179 { ir_free_pagenodes(datapages.root);
180 ir_free_pagenodes(namepages.root);
181 }
182
183 static
184 void ir_free_pagenodes
185 ( struct pagenode_t* pagenode )
186 { if (pagenode->header.next != NULL)
187 ir_free_pagenodes(pagenode->header.next);
188 free(pagenode);
189 }
190
191 /* Link
192 */
193 int ir_linker
194 ( void )
195 { return 0; }
196
197 /* Condense
198 */
199 int ir_condenser
200 ( void )
201 { return 0; }
202
203 /* Return a pointer to the root class */
204 struct ir_class_t* ir_class_root
205 ( void )
206 { return &root_class; }
207
208 /* Add a subclass to a class
209 Attempts to create a new subclass in the provided class, returning
210 the class if it already exists
211 */
212 struct ir_class_t* ir_class_addchild
213 ( struct ir_class_t* class,
214 uint8_t* name
215 )
216 { struct ir_class_t* iter;
217 if (class->nextchild == NULL)
218 return class->nextchild = struct_alloc(ir_class_t);
219 iter = class->nextchild;
220 check:
221 if (bytes_identical(iter->name, name))
222 return iter;
223 if (iter->nextsib != NULL)
224 { iter = iter->nextsib;
225 goto check;
226 }
227 iter = struct_alloc(ir_class_t);
228 iter->nextsib = class->nextchild;
229 iter->name = name_alloc(name);
230 return class->nextchild = iter;
231 }
232
233 /* Add a set to a class
234 Attempts to create a new root set in the specified class, returning
235 the set if it already exists
236 */
237 struct ir_set_t* ir_class_addset
238 ( struct ir_class_t* class,
239 uint8_t* name
240 )
241 { struct ir_set_t* iter;
242 if (class->root_set == NULL)
243 return class->root_set = struct_alloc(ir_set_t);
244 iter = class->root_set;
245 check:
246 if (bytes_identical(iter->name, name))
247 return iter;
248 if (iter->nextsib != NULL)
249 { iter = iter->nextsib;
250 goto check;
251 }
252 iter = struct_alloc(ir_set_t);
253 iter->nextsib = class->root_set;
254 iter->name = name_alloc(name);
255 return class->root_set = iter;
256 }
257
258 /* Add a set to a set
259 Attempts to create a new subset of the specified set, returning the
260 child if it already exists
261 */
262 struct ir_set_t* ir_set_addchild
263 ( struct ir_set_t* set,
264 uint8_t* name
265 )
266 { struct ir_set_t* iter;
267 if (set->nextchild == NULL)
268 return set->nextchild = struct_alloc(ir_set_t);
269 iter = set->nextchild;
270 check:
271 if (bytes_identical(iter->name, name))
272 return iter;
273 if (iter->nextsib != NULL)
274 { iter = iter->nextsib;
275 goto check;
276 }
277 iter = struct_alloc(ir_set_t);
278 iter->nextsib = set->nextchild;
279 iter->name = name_alloc(name);
280 return set->nextchild = iter;
281 }
282
283 /* Add a framebox to a set
284 Attempts to create a new framebox of the specified set, returning
285 the framebox if it already exists
286 */
287 static inline
288 struct ir_framebox_t* ir_set_add_framebox
289 ( struct ir_set_t* set,
290 uint8_t* name
291 )
292 { struct ir_framebox_t* iter;
293 if (set->frameboxes == NULL)
294 return set->frameboxes = struct_alloc(ir_framebox_t);
295 iter = set->frameboxes;
296 check:
297 if (bytes_identical(iter->header.data_name, name))
298 return iter;
299 if (iter->header.nextsib != NULL)
300 { iter = (struct ir_framebox_t*) iter->header.nextsib;
301 goto check;
302 }
303 iter = struct_alloc(ir_framebox_t);
304 iter->header.nextsib = (union ir_setdata_t*) set->frameboxes;
305 iter->header.data_name = name_alloc(name);
306 return set->frameboxes = iter;
307 }
308
309 /* Match two null-terminated bytestrings
310 Return 1 if the two bytestrings are identical, else 0
311 */
312 static inline
313 int bytes_identical
314 ( uint8_t* stra,
315 uint8_t* strb
316 )
317 { int ca, cb;
318 do {
319 ca = *stra++;
320 cb = *strb++;
321 } while (ca && ca == cb);
322 return (ca == cb);
323 }
324
325 /* Assign Setdata to Set
326
327 */
328 void ir_set_assign_data
329 ( struct ir_set_t* set,
330 union ir_setdata_t* setdata
331 )
332 { struct ir_framebox_t* framebox;
333 struct ir_simplex_t* simplex;
334 switch (setdata->header.type)
335 { case FSDAT:
336 framebox = ir_set_add_framebox(set, setdata->header.data_name);
337 if (framebox->framesheets[setdata->framesheet.frameinfo.facing].header.data_name != NULL)
338 wprintf("Duplicate framesheet [%i] %s\n",
339 setdata->framesheet.frameinfo.facing, setdata->header.data_name);
340 framebox->framesheets[setdata->framesheet.frameinfo.facing] = setdata->framesheet;
341 break;
342 case MSDAT:
343 framebox = ir_set_add_framebox(set, setdata->header.data_name);
344 if (framebox->mapsheets[setdata->mapsheet.frameinfo.facing].header.data_name != NULL)
345 wprintf("Duplicate mapsheet [%i] %s\n",
346 setdata->mapsheet.frameinfo.facing, setdata->header.data_name);
347 framebox->mapsheets[setdata->mapsheet.frameinfo.facing] = setdata->mapsheet;
348 break;
349 case ADAT:
350 if (set->audio == NULL)
351 { set->audio = (struct ir_simplex_t*) setdata;
352 return;
353 }
354 simplex = set->audio;
355 while (simplex->header.nextsib != NULL)
356 if (bytes_identical(simplex->header.data_name, setdata->header.data_name))
357 { wprintf("Duplicate audio %s\n", setdata->header.data_name);
358 *simplex = setdata->audio;
359 //setdata is now a pointer to redundant, unused memory.
360 return;
361 }
362 else
363 simplex = (struct ir_simplex_t*) simplex->header.nextsib;
364 setdata->audio.header.nextsib = (union ir_setdata_t*) set->audio;
365 set->audio = (struct ir_simplex_t*) setdata;
366 break;
367 case LDAT:
368 setdata->link.header.nextsib = (union ir_setdata_t*) set->links;
369 set->links = (struct ir_link_t*) setdata;
370 break;
371 default:
372 fprintf(stderr, "Unknown setdata type %x\n", setdata->header.type);
373 exit(-1);
374 }
375 }
376
377 void ir_set_assign_ref
378 ( struct ir_set_t* set,
379 long long ref
380 )
381 { if (set->ref != 0)
382 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
383 (long unsigned) set->ref, (long unsigned) ref, set->name);
384 set->ref = ref;
385 //TODO: reflist_add(set);
386 }
387
388 void ir_data_assign_path
389 ( union ir_setdata_t* setdata,
390 uint8_t* path
391 )
392 { if (setdata->header.src_filename != NULL)
393 wprintf("Path override: %s -> %s for setdata %s\n",
394 setdata->header.src_filename, path, setdata->header.data_name);
395 setdata->header.src_filename = name_alloc(path);
396 }
397
398 union ir_setdata_t* ir_framesheet
399 ( uint8_t* name,
400 apc_facing d,
401 int width,
402 int height
403 )
404 { return ir_framedata(FSDAT, name, d, width, height); }
405
406 union ir_setdata_t* ir_mapsheet
407 ( uint8_t* name,
408 apc_facing d,
409 int width,
410 int height
411 )
412 { return ir_framedata(MSDAT, name, d, width, height); }
413
414 static inline
415 union ir_setdata_t* ir_framedata
416 ( enum dtype type,
417 uint8_t* name,
418 apc_facing d,
419 int width,
420 int height
421 )
422 { struct ir_framedata_t* framedata = struct_alloc(ir_framedata_t);
423 framedata->header.type = type;
424 framedata->header.data_name = name_alloc(name);
425 framedata->frameinfo.facing = d;
426 framedata->frameinfo.w = width;
427 framedata->frameinfo.h = height;
428 return (union ir_setdata_t*) framedata;
429 }
430
431 union ir_setdata_t* ir_audio
432 ( uint8_t* name )
433 { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t);
434 audio->header.type = ADAT;
435 audio->header.data_name = name_alloc(name);
436 return (union ir_setdata_t*) audio;
437 }
438
439
440 /* Create classld that points to a class */
441 struct ir_classld_t* ir_classld_from_class
442 ( struct ir_class_t* class )
443 { struct ir_classld_t* classld;
444 classld = struct_alloc(ir_classld_t);
445 classld->root_class = class;
446 return classld;
447 }
448
449 struct ir_setld_t* ir_setld_from_ref
450 ( long long ref )
451 { struct ir_setld_t* setld;
452 setld = struct_alloc(ir_setld_t);
453 setld->ref = ref;
454 return setld;
455 }
456
457 struct ir_setld_t* ir_setld_from_classld
458 ( struct ir_classld_t* classld,
459 uint8_t* name
460 )
461 { struct ir_setld_t* setld;
462 setld = struct_alloc(ir_setld_t);
463 setld->namelist = struct_alloc(ir_namelist_t);
464 setld->namelist_head = setld->namelist;
465 setld->namelist_head->name = name_alloc(name);
466 setld->classld = classld;
467 return setld;
468 }
469
470 struct ir_setld_t* ir_setld_addchild
471 ( struct ir_setld_t* setld,
472 uint8_t* name
473 )
474 { if (setld->namelist == NULL)
475 { setld->namelist = struct_alloc(ir_namelist_t);
476 setld->namelist_head = setld->namelist;
477 }
478 else
479 { setld->namelist_head->nextsib = struct_alloc(ir_namelist_t);
480 setld->namelist_head = setld->namelist_head->nextsib;
481 }
482 setld->namelist_head->name = name_alloc(name);
483 return setld;
484 }
485
486 union ir_setdata_t* ir_link
487 ( enum ltype link_type,
488 struct ir_setld_t* setld,
489 uint8_t* name
490 )
491 { struct ir_link_t* link;
492 link = struct_alloc(ir_link_t);
493 link->header.type = LDAT;
494 link->type = link_type;
495 link->classld = setld->classld;
496 link->setld = setld;
497 if (link_type != OLINK && name != NULL)
498 link->header.data_name = name_alloc(name);
499 return (union ir_setdata_t*) link;
500 }
501
502
503 static
504 void* stack_alloc
505 ( size_t bytes )
506 { if (!bytes) //valid behavior to attain current head
507 return datapages.head->header.head;
508 if (PL_HEADMEM(datapages) < bytes)
509 { datapages.head->header.next = (struct pagenode_t*) calloc(datapages.pagesize,1);
510 if (datapages.head->header.next == NULL)
511 eprint("Memory allocation error \n");
512 datapages.head = datapages.head->header.next;
513 datapages.head->header.head = datapages.head->root;
514 }
515 datapages.head->header.head += bytes;
516 return (void*) datapages.head->header.head - bytes;
517 }
518
519 static
520 uint8_t* name_alloc
521 ( uint8_t* name_src )
522 { uint8_t* iter, * name;
523 int head_mem;
524 copy:
525 name = (uint8_t*)namepages.head->header.head;
526 iter = name_src;
527 for (head_mem = PL_HEADMEM(namepages); *iter && head_mem; head_mem--)
528 *(namepages.head->header.head)++ = *iter++;
529 if (head_mem == 0) //not enough room
530 { namepages.head->header.next = (struct pagenode_t*) calloc(namepages.pagesize,1);
531 if (namepages.head->header.next == NULL)
532 eprint("Memory allocation error\n");
533 namepages.head = namepages.head->header.next;
534 namepages.head->header.head = namepages.head->root;
535 goto copy;
536 }
537 *(namepages.head->header.head)++ = '\0';
538 return name;
539 }