233 lines
5.0 KiB
C
233 lines
5.0 KiB
C
#include "stdlib.h"
|
|
#include "string.h"
|
|
#include "stddef.h"
|
|
#include "stdio.h"
|
|
#include "ctype.h"
|
|
|
|
#define ALIGNMENT 8
|
|
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
|
|
|
|
#define HEAP_SIZE 1024 * 1024 * 512
|
|
static unsigned char heap[HEAP_SIZE] __attribute__((aligned(ALIGNMENT)));
|
|
static size_t heap_top = ALIGNMENT;
|
|
|
|
typedef struct block {
|
|
size_t size;
|
|
struct block *next;
|
|
} block_t;
|
|
static block_t *free_list = NULL;
|
|
|
|
#ifdef IRON_WASM
|
|
__attribute__((export_name("wasm_malloc")))
|
|
#endif
|
|
void *
|
|
malloc(size_t size) {
|
|
size = ALIGN(size);
|
|
block_t **link = &free_list;
|
|
block_t *curr = free_list;
|
|
while (curr) {
|
|
if (curr->size >= size) {
|
|
if (curr->size >= size + sizeof(block_t) + ALIGNMENT) {
|
|
block_t *remainder = (block_t *)((unsigned char *)curr + sizeof(block_t) + size);
|
|
remainder->size = curr->size - size - sizeof(block_t);
|
|
remainder->next = curr->next;
|
|
*link = remainder;
|
|
curr->size = size;
|
|
}
|
|
else {
|
|
*link = curr->next;
|
|
}
|
|
return (void *)(curr + 1);
|
|
}
|
|
link = &curr->next;
|
|
curr = curr->next;
|
|
}
|
|
if (heap_top + sizeof(block_t) + size > HEAP_SIZE) {
|
|
printf("malloc: out of memory");
|
|
return NULL;
|
|
}
|
|
block_t *ptr = (block_t *)&heap[heap_top];
|
|
ptr->size = size;
|
|
heap_top += sizeof(block_t) + size;
|
|
return (void *)(ptr + 1);
|
|
}
|
|
|
|
void free(void *mem) {
|
|
if (!mem) {
|
|
return;
|
|
}
|
|
block_t *block = (block_t *)mem - 1;
|
|
block_t *curr = free_list;
|
|
block_t *prev = NULL;
|
|
while (curr && curr < block) {
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
if (prev) {
|
|
prev->next = block;
|
|
}
|
|
else {
|
|
free_list = block;
|
|
}
|
|
block->next = curr;
|
|
if (curr && (unsigned char *)(block + 1) + block->size == (unsigned char *)curr) {
|
|
block->size += sizeof(block_t) + curr->size;
|
|
block->next = curr->next;
|
|
}
|
|
if (prev && (unsigned char *)(prev + 1) + prev->size == (unsigned char *)block) {
|
|
prev->size += sizeof(block_t) + block->size;
|
|
prev->next = block->next;
|
|
}
|
|
}
|
|
|
|
void *calloc(size_t num, size_t size) {
|
|
size_t total = num * size;
|
|
void *ptr = malloc(total);
|
|
if (ptr) {
|
|
memset(ptr, 0, total);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
void *realloc(void *mem, size_t size) {
|
|
if (!mem) {
|
|
return malloc(size);
|
|
}
|
|
block_t *b = (block_t *)mem - 1;
|
|
if (b->size >= size) {
|
|
return mem;
|
|
}
|
|
void *ptr = malloc(size);
|
|
if (ptr) {
|
|
memcpy(ptr, mem, b->size);
|
|
free(mem);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
void *aligned_alloc(size_t align, size_t size) {
|
|
heap_top = (heap_top + align - 1) & ~(align - 1);
|
|
return malloc(size);
|
|
}
|
|
|
|
int system(const char *string) {
|
|
return 0;
|
|
}
|
|
|
|
void exit(int code) {
|
|
exit(code);
|
|
}
|
|
|
|
long int strtol(const char *str, char **endptr, int base) {
|
|
while (isspace(*str)) {
|
|
str++;
|
|
}
|
|
int sign = (*str == '-') ? (str++, -1) : (*str == '+') ? (str++, 1) : 1;
|
|
if (base == 0) {
|
|
base = (*str == '0') ? (str[1] == 'x' || str[1] == 'X') ? (str += 2, 16) : (str++, 8) : 10;
|
|
}
|
|
if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
|
|
str += 2;
|
|
}
|
|
long val = 0;
|
|
for (; *str; str++) {
|
|
int digit = isdigit(*str) ? *str - '0' : (*str >= 'a' && *str <= 'z') ? *str - 'a' + 10 : (*str >= 'A' && *str <= 'Z') ? *str - 'A' + 10 : 999;
|
|
if (digit >= base) {
|
|
break;
|
|
}
|
|
val = val * base + digit;
|
|
}
|
|
if (endptr) {
|
|
*endptr = (char *)str;
|
|
}
|
|
return sign * val;
|
|
}
|
|
|
|
float strtof(const char *str, char **endptr) {
|
|
return (float)strtod(str, endptr);
|
|
}
|
|
|
|
double strtod(const char *str, char **endptr) {
|
|
while (isspace(*str)) {
|
|
str++;
|
|
}
|
|
int sign = (*str == '-') ? (str++, -1) : (*str == '+') ? (str++, 1) : 1;
|
|
double val = 0;
|
|
while (isdigit(*str)) {
|
|
val = val * 10.0 + (*str++ - '0');
|
|
}
|
|
if (*str == '.') {
|
|
double divisor = 10.0;
|
|
for (str++; isdigit(*str); str++) {
|
|
val += (*str - '0') / divisor;
|
|
divisor *= 10.0;
|
|
}
|
|
}
|
|
if (endptr) {
|
|
*endptr = (char *)str;
|
|
}
|
|
return sign * val;
|
|
}
|
|
|
|
double atof(const char *str) {
|
|
return strtod(str, NULL);
|
|
}
|
|
|
|
int abs(int n) {
|
|
return n < 0 ? -n : n;
|
|
}
|
|
|
|
long long int llabs(long long int n) {
|
|
return n < 0 ? -n : n;
|
|
}
|
|
|
|
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
|
|
if (num < 2) {
|
|
return;
|
|
}
|
|
char *b = base;
|
|
char tmp[size];
|
|
char *pivot = b + (num / 2) * size;
|
|
size_t i = 0;
|
|
size_t j = num - 1;
|
|
memcpy(tmp, pivot, size);
|
|
while (i <= j) {
|
|
while (compar(b + i * size, tmp) < 0) {
|
|
i++;
|
|
}
|
|
while (j > 0 && compar(b + j * size, tmp) > 0) {
|
|
j--;
|
|
}
|
|
if (i <= j) {
|
|
if (i != j) {
|
|
char t[size];
|
|
memcpy(t, b + i * size, size);
|
|
memcpy(b + i * size, b + j * size, size);
|
|
memcpy(b + j * size, t, size);
|
|
}
|
|
i++;
|
|
if (j == 0) {
|
|
break;
|
|
}
|
|
j--;
|
|
}
|
|
}
|
|
if (j > 0) {
|
|
qsort(b, j + 1, size, compar);
|
|
}
|
|
if (i < num) {
|
|
qsort(b + i * size, num - i, size, compar);
|
|
}
|
|
}
|
|
|
|
static unsigned int seed = 1;
|
|
|
|
void srand(unsigned int s) {
|
|
seed = s;
|
|
}
|
|
|
|
int rand() {
|
|
seed = seed * 1103515245 + 12345;
|
|
return (seed >> 16) & 0x7FFF;
|
|
}
|