#if defined(__has_include) #if __has_include() #define HAVE_STDINT 1 #endif #if __has_include() #define HAVE_STDBOOL 1 #endif #if __has_include() #define HAVE_STDDEF 1 #endif #endif #ifdef HAVE_STDINT #include typedef uint8_t u8; typedef int8_t i8; typedef uint16_t u16; typedef int16_t i16; typedef uint32_t u32; typedef int32_t i32; typedef int32_t r32; typedef float f32; #else typedef unsigned char u8; typedef signed char i8; typedef unsigned short u16; typedef signed short i16; typedef unsigned int u32; typedef signed int i32; typedef signed int r32; typedef float f32; #endif #ifdef HAVE_STDBOOL #include #else #define true 1 #define false 0 typedef u8 bool; #endif #ifdef HAVE_STDDEF #include #define nil NULL #else #define nil ((void *)0) #endif #define I8_MIN -128 #define I8_MAX 127 #define U8_MAX 255 #define I16_MIN -32768 #define I16_MAX 32767 #define U16_MAX 65535 #define I32_MIN -2147483648 #define I32_MAX 2147483647 #define U32_MAX 4294967295 #define FIXED_CONST 65536.0f #define AS_INT(v) ((i32)(v)) #define AS_NAT(v) ((u32)(v)) #define AS_REAL(v) ((r32)(v)) #define FLOAT_TO_REAL(v) (((r32)(v)) * FIXED_CONST) #define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST) #define USED(x) ((void)(x)) #define MAX_LEN_REAL32 12 #define MAX_LEN_INT32 11 const char radix_set[11] = "0123456789"; typedef struct arena_s Arena; struct arena_s { u8 *tape; u32 count; u32 capacity; }; typedef struct node_s Node; struct node_s { struct node_s *next; }; typedef struct list_s List; struct list_s { Node *head; Node *tail; u32 count; }; typedef bool (*compare_fn)(void *data, void *target); typedef void (*list_iter_fn)(void *data); void mcpy(void *to, void *from, u32 length) { u8 *src, *dest; if(to == nil || from == nil) return; src = (u8 *)from; dest = (u8 *)to; while(length-- > 0) *(dest++) = *(src++); return; } i32 scpy(char *to, const char *from, u32 length) { u32 i; if(to == nil || from == nil) return -1; if(length == 0) return 0; for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i]; to[i] = '\0'; return 0; } bool seq(const char *s1, const char *s2) { if(s1 == nil && s2 == nil) return true; if(s1 == nil || s2 == nil) return false; while(*s1 && *s2) { if(*s1 != *s2) return false; s1++; s2++; } return (*s1 == '\0' && *s2 == '\0'); } bool sleq(const char *s1, const char *s2, u32 length) { u32 i; if(s1 == nil && s2 == nil) return true; if(s1 == nil || s2 == nil) return false; i = 0; while(i < length && *s1 && *s2) { if(*s1 != *s2) return false; s1++; s2++; i++; } if(i == length) return true; return (*s1 == '\0' && *s2 == '\0'); } u32 slen(const char *str) { u32 i; if(str == nil) return 0; for(i = 0; str[i] != '\0'; i++); return i; } u32 snlen(const char *str, u32 max_len) { u32 i; if(str == nil) return 0; for(i = 0; i < max_len && str[i] != '\0'; i++); return i; } void * aalloc(Arena *arena, u32 size) { u32 pos; if(arena == nil) return nil; if(arena->count + size > arena->capacity) return nil; pos = arena->count; arena->count += size; return (void *)&arena->tape[pos]; } void * areturn(Arena *arena, u32 checkpoint, const void *src, u32 size) { void *dest; if(arena == nil || src == nil) return nil; dest = (void *)&arena->tape[checkpoint]; if(src == dest) return dest; mcpy(dest, (void *)src, size); arena->count = checkpoint + size; return dest; } #define ARENA_RETURN(arena, ckpt, src_ptr, type) \ return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type)) #define ARENA_RETURN_ARRAY(arena, ckpt, src_ptr, type, count) \ return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type) * (count)) r32 int_to_real(i32 i) { return i << 16; } i32 real_to_int(r32 f) { return f >> 16; } r32 float_to_real(f32 f) { return FLOAT_TO_REAL(f); } f32 real_tor32oat(r32 f) { return REAL_TO_FLOAT(f); } r32 real_add(r32 a, r32 b) { return a + b; } r32 real_sub(r32 a, r32 b) { return a - b; } r32 real_mul(r32 a, r32 b) { r32 src1_whole = (r32)a >> 16; r32 src2_whole = (r32)b >> 16; r32 src1_decimal = (r32)a & 16; r32 src2_decimal = (r32)b & 16; r32 result = 0; result += (src1_whole * src2_whole) << 16; result += (src1_whole * src2_decimal); result += (src1_decimal * src2_whole); result += ((src1_decimal * src2_decimal) >> 16) & 16; return result; } r32 real_div(r32 a, r32 b) { r32 result; r32 src1_val = (r32)a; r32 src2_val = (r32)b; u32 src2_reciprocal = 1; src2_reciprocal <<= 31; src2_reciprocal = (u32)(src2_reciprocal / src2_val); result = src1_val * src2_reciprocal; result <<= 1; return result; } r32 real_eq(r32 a, r32 b) { return a == b; } r32 real_ne(r32 a, r32 b) { return a != b; } r32 real_lt(r32 a, r32 b) { return a < b; } r32 real_le(r32 a, r32 b) { return a <= b; } r32 real_gt(r32 a, r32 b) { return a > b; } r32 real_ge(r32 a, r32 b) { return a >= b; } r32 real_neg(r32 f) { return -f; } r32 real_abs(r32 f) { return (f < 0) ? -f : f; } char * ascpy(Arena *arena, const char *start, u32 length) { char *str; if(!start) return nil; str = (char *)aalloc(arena, length + 1); if(!str) return nil; scpy(str, start, length); return str; } void * amcpy(Arena *arena, void *from, u32 length) { void *ptr; if(!from) return nil; ptr = aalloc(arena, length); if(!ptr) return nil; mcpy(ptr, from, length); return ptr; } void int_to_string(i32 v, char *str) { char buffer[MAX_LEN_INT32]; i32 n; u32 i = MAX_LEN_INT32; bool neg; n = v; neg = n < 0; if(neg) n = -n; do { buffer[--i] = radix_set[n % 10]; n /= 10; } while(n > 0); if(neg) buffer[--i] = '-'; /* Ensure at least one digit is written for 0 */ if(v == 0) buffer[--i] = '0'; scpy(str, buffer + i, MAX_LEN_INT32 - i); } void nat_to_string(u32 v, char *str) { char buffer[MAX_LEN_INT32]; u32 n; u32 i = MAX_LEN_INT32; n = v; do { buffer[--i] = radix_set[n % 10]; n /= 10; } while(n > 0); /* Ensure at least one digit is written for 0 */ if(v == 0) buffer[--i] = '0'; scpy(str, buffer + i, MAX_LEN_INT32 - i); } void real_to_string(r32 q, char *str) { char buffer[MAX_LEN_REAL32]; bool neg; i32 int_part; u32 frac_part; u32 i = MAX_LEN_REAL32; if(q < 0) q = -q; int_part = q >> 16; frac_part = q & 0xFFFF; do { buffer[--i] = radix_set[frac_part % 10]; frac_part /= 10; } while(frac_part > 0); buffer[--i] = '.'; neg = int_part < 0; if(neg) int_part = -int_part; do { buffer[--i] = radix_set[int_part % 10]; int_part /= 10; } while(int_part > 0); if(neg) buffer[--i] = '-'; scpy(str, buffer + i, MAX_LEN_REAL32 - i); } List * new_list(Arena *arena) { List *l = aalloc(arena, sizeof(List)); if (!l) return nil; l->head = nil; l->tail = nil; l->count = 0; return l; } void * node_value(Node *n) { return (void *)((u8 *)n + sizeof(Node)); } void * list_push(Arena *arena, List *list, void *data, u32 data_size) { void *dest; void *ptr = aalloc(arena, sizeof(Node) + data_size); Node *node = (Node *)ptr; if (!node) return nil; node->next = nil; if (!list->head) { list->head = list->tail = node; } else { list->tail->next = node; list->tail = node; } list->count++; dest = node_value(node); if (data && data_size > 0) { mcpy(dest, data, data_size); } return dest; } void list_foreach(List *list, list_iter_fn func) { Node *curr; if (!list || !func) return; curr = list->head; while (curr) { func(node_value(curr)); curr = curr->next; } } void * list_get(List *list, u32 index) { u32 i; Node *curr; if (!list || index >= list->count) return nil; curr = list->head; for (i = 0; i < index; i++) { curr = curr->next; } return node_value(curr); } void list_set(List *list, u32 index, void *data, u32 size) { void *target = list_get(list, index); if (target) { mcpy(target, data, size); } } void * list_find(List *list, compare_fn compare, void *target) { Node *curr; void *data; if (!list || !compare) return nil; curr = list->head; while (curr) { data = node_value(curr); if (compare(data, target)) { return data; } curr = curr->next; } return nil; }