mirror of https://github.com/flysand7/ciabatta.git
Memory allocation functions (untested)
This commit is contained in:
parent
4b8d8692e5
commit
04555ac1db
|
@ -1,9 +1,15 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set PLATFORM=win32
|
||||
set CIABATTA_OPTIONS=-Iinc -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
for /R %%F in (*.c) do (
|
||||
for /R code %%F in (*.c) do (
|
||||
echo %%F
|
||||
clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS%
|
||||
)
|
||||
for /R platform\%PLATFORM% %%F in (*.c) do (
|
||||
echo %%F
|
||||
clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS%
|
||||
)
|
||||
llvm-ar rc ciabatta.lib build\*.obj
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
// TODO: strto*: locale-based parsing for integers
|
||||
// TODO: i made a function that parses longs and i'm fucken
|
||||
// tired. someone make float parsing :kekw:
|
||||
|
||||
#define inrange(start, c, end) ((start) <= (c) && (c) <= (end))
|
||||
|
||||
static bool isbase(int c, int base) {
|
||||
int val;
|
||||
if(isdigit(c)) {
|
||||
val = c-'0';
|
||||
}
|
||||
else if(islower(c)) {
|
||||
val = c-'a'+10;
|
||||
}
|
||||
else if(isupper(c)) {
|
||||
val = c-'A'+10;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return val < base;
|
||||
}
|
||||
|
||||
// Called only when isbase(c, base) for some base in range
|
||||
static long todigitl(int c) {
|
||||
int val;
|
||||
if(isdigit(c)) {
|
||||
val = c-'0';
|
||||
}
|
||||
else if(islower(c)) {
|
||||
val = c-'a'+10;
|
||||
}
|
||||
else if(isupper(c)) {
|
||||
val = c-'A'+10;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
long
|
||||
strtol(const char *restrict nptr, char **restrict endptr, int inbase) {
|
||||
if(!inrange(0, inbase, 36)) {
|
||||
*endptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
// Skip space on the beginning
|
||||
while(isspace(*nptr)) {
|
||||
++nptr;
|
||||
}
|
||||
// Parse sign
|
||||
long coef = 1;
|
||||
if(*nptr == '-') {
|
||||
coef = -1;
|
||||
++nptr;
|
||||
}
|
||||
if(*nptr == '+') {
|
||||
++nptr;
|
||||
}
|
||||
unsigned long base = (unsigned long)inbase;
|
||||
unsigned long value = 0;
|
||||
// See if we need to parse base in C-like format
|
||||
if(*nptr == '0' && *(nptr+1) == 'x') {
|
||||
++nptr;
|
||||
if(base == 16 || base == 0) {
|
||||
++nptr;
|
||||
base = 16;
|
||||
}
|
||||
else {
|
||||
value = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if(*nptr == '0') {
|
||||
++nptr;
|
||||
if(base == 8 || base == 0) {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
while(isbase(*nptr, (int)base)) {
|
||||
unsigned long digit = (unsigned long)todigitl(*nptr);
|
||||
if(value > (ULONG_MAX - digit)/base) {
|
||||
errno = ERANGE;
|
||||
value = 0;
|
||||
goto end;
|
||||
}
|
||||
value = base*value + digit;
|
||||
++nptr;
|
||||
}
|
||||
unsigned long max_modulo = (unsigned long)LONG_MAX+1;
|
||||
if(value > max_modulo) {
|
||||
errno = ERANGE;
|
||||
value = 0;
|
||||
goto end;
|
||||
}
|
||||
if(value == max_modulo) {
|
||||
if(coef == 1) {
|
||||
errno = ERANGE;
|
||||
value = 0;
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
value = LONG_MIN;
|
||||
coef = 1;
|
||||
}
|
||||
}
|
||||
end:
|
||||
if(endptr != NULL) {
|
||||
*endptr = (char *)nptr;
|
||||
}
|
||||
return coef*(long)value;
|
||||
}
|
||||
|
||||
long long
|
||||
strtoll(const char *restrict nptr, char **restrict endptr, int base) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
strtoul(const char *restrict nptr, char **restrict endptr, int base) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long long
|
||||
strtoull(const char *restrict nptr, char **restrict endptr, int base) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double atof(const char *nptr) {
|
||||
return strtod(nptr, (char **)NULL);
|
||||
}
|
||||
|
||||
int atoi(const char *nptr) {
|
||||
return (int)strtol(nptr, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
long int atol(const char *nptr) {
|
||||
return strtol(nptr, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
long long int atoll(const char *nptr) {
|
||||
return strtoll(nptr, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
double strtod(const char *restrict nptr, char **restrict endptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float strtof(const char *restrict nptr, char **restrict endptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long double strtold(const char *restrict nptr, char **restrict endptr) {
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// TODO: the code for rand/srand was shamelessly copied
|
||||
// from C11 standard's example and is a simple LCG.
|
||||
// gotta implement a better random function, or no idc
|
||||
|
||||
static int last_random_number;
|
||||
|
||||
int rand(void) {
|
||||
last_random_number = last_random_number * 1103515245 + 12345;
|
||||
return (unsigned int)(last_random_number/65536) % RAND_MAX;
|
||||
}
|
||||
|
||||
void srand(unsigned int seed) {
|
||||
last_random_number = seed;
|
||||
}
|
|
@ -51,3 +51,4 @@
|
|||
typedef int errno_t;
|
||||
typedef size_t rsize_t;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
#define EILSEQ 2
|
||||
#define ERANGE 3
|
||||
|
||||
// TODO:
|
||||
//_Thread_local int errno;
|
||||
// TODO: make it thread-local
|
||||
int errno;
|
||||
|
|
49
inc/stdlib.h
49
inc/stdlib.h
|
@ -1,4 +1,9 @@
|
|||
#include "_platform.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(NULL)
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
// typedef struct div_t {
|
||||
// int quot;
|
||||
|
@ -18,27 +23,31 @@
|
|||
// #define EXIT_FAILURE 1
|
||||
// #define EXIT_SUCCESS 0
|
||||
|
||||
// #define RAND_MAX 65536
|
||||
#define RAND_MAX 65536
|
||||
// #define MB_CUR_MAX 5
|
||||
|
||||
// double atof(const char *nptr);
|
||||
// int atoi(const char *nptr);
|
||||
// long int atol(const char *nptr);
|
||||
// long long int atoll(const char *nptr);
|
||||
// double strtod(const char * restrict nptr, char ** restrict endptr);
|
||||
// float strtof(const char * restrict nptr, char ** restrict endptr);
|
||||
// long double strtold(const char * restrict nptr, char ** restrict endptr);
|
||||
// long int strtol(const char * restrict nptr, char ** restrict endptr, int base);
|
||||
// long long int strtoll(const char * restrict nptr, char ** restrict endptr, int base);
|
||||
// unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr, int base);
|
||||
// unsigned long long int strtoull(const char * restrict nptr, char ** restrict endptr, int base);
|
||||
// int rand(void);
|
||||
// void srand(unsigned int seed);
|
||||
// void *aligned_alloc(size_t alignment, size_t size);
|
||||
// void *calloc(size_t nmemb, size_t size);
|
||||
// void free(void *ptr);
|
||||
// void *malloc(size_t size);
|
||||
// void *realloc(void *ptr, size_t size);
|
||||
double atof(const char *nptr);
|
||||
int atoi(const char *nptr);
|
||||
long int atol(const char *nptr);
|
||||
long long int atoll(const char *nptr);
|
||||
double strtod(const char * restrict nptr, char ** restrict endptr);
|
||||
float strtof(const char * restrict nptr, char ** restrict endptr);
|
||||
long double strtold(const char * restrict nptr, char ** restrict endptr);
|
||||
long int strtol(const char *restrict nptr, char **restrict endptr, int base);
|
||||
long long int strtoll(const char *restrict nptr, char **restrict endptr, int base);
|
||||
unsigned long int strtoul(const char *restrict nptr, char **restrict endptr, int base);
|
||||
unsigned long long int strtoull(const char *restrict nptr, char **restrict endptr, int base);
|
||||
int rand(void);
|
||||
void srand(unsigned int seed);
|
||||
|
||||
typedef struct _os_heap _os_heap;
|
||||
void _heap_setup(_os_heap *heap);
|
||||
void *aligned_alloc(size_t alignment, size_t size);
|
||||
void *calloc(size_t nmemb, size_t size);
|
||||
void free(void *ptr);
|
||||
void *malloc(size_t size);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
|
||||
// _Noreturn void abort(void);
|
||||
// int atexit(void (*func)(void));
|
||||
// int at_quick_exit(void (*func)(void));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include <_platform.h>
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include "win32.h"
|
||||
|
||||
extern int main(int argc, char** argv);
|
||||
|
||||
|
@ -58,8 +58,18 @@ void mainCRTStartup() {
|
|||
convert_wide_chars_to_ansi(args[i], args_wide[i], wide_len);
|
||||
}
|
||||
|
||||
_os_heap heap_data = {
|
||||
.handle = heap,
|
||||
};
|
||||
_heap_setup(&heap_data);
|
||||
|
||||
srand(0);
|
||||
setlocale(LC_ALL, "C");
|
||||
int exit_code = main(arg_count, args);
|
||||
|
||||
ExitProcess(exit_code);
|
||||
}
|
||||
|
||||
// This symbol is required to be present if we're using floating-point
|
||||
// numbers
|
||||
int _fltused=0;
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "win32.h"
|
||||
|
||||
// TODO: lock the heap before allocation (?)
|
||||
|
||||
HANDLE _heap;
|
||||
|
||||
static bool is_power_of_two(size_t s) {
|
||||
return (s & (s-1)) == 0;
|
||||
}
|
||||
|
||||
static intptr_t align_forward(intptr_t p, size_t a) {
|
||||
return (p+a-1)&~(a-1);
|
||||
}
|
||||
|
||||
void _heap_setup(_os_heap *heap) {
|
||||
_heap = heap->handle;
|
||||
}
|
||||
|
||||
void *aligned_alloc(size_t alignment, size_t size) {
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if(alignment == 0) {
|
||||
alignment = 8;
|
||||
}
|
||||
if(!is_power_of_two(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
// HeapAlloc is guaranteed to return 8-byte aligned pointer,
|
||||
// so if our alignment is 8 or less we don't have to overallocate.
|
||||
// otherwise we'll reserve extra `alignment` bytes to later adjust our
|
||||
// memory buffer according to required alignment.
|
||||
size_t min_req_size = size;
|
||||
if(alignment > 8) {
|
||||
min_req_size += alignment;
|
||||
}
|
||||
void *block_start = HeapAlloc(_heap, HEAP_ZERO_MEMORY, size+alignment);
|
||||
intptr_t block_start_i = (intptr_t)block_start;
|
||||
intptr_t aligned_block_start_i = align_forward(block_start_i, alignment);
|
||||
void *aligned_block_start = (void *)aligned_block_start_i;
|
||||
return aligned_block_start;
|
||||
}
|
||||
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
if(nmemb == 0 || size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if(nmemb > SIZE_MAX/size) {
|
||||
return NULL;
|
||||
}
|
||||
void *block_start = HeapAlloc(_heap, HEAP_ZERO_MEMORY, size*nmemb);
|
||||
return block_start;
|
||||
}
|
||||
|
||||
void free(void *ptr) {
|
||||
if(ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
HeapFree(_heap, 0, ptr);
|
||||
}
|
||||
|
||||
void *malloc(size_t size) {
|
||||
return aligned_alloc(8, size);
|
||||
}
|
||||
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
void *buffer = HeapReAlloc(_heap, 0, ptr, size);
|
||||
return buffer;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
struct _os_heap {
|
||||
HANDLE handle;
|
||||
};
|
Loading…
Reference in New Issue