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
|
@echo off
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
set PLATFORM=win32
|
||||||
set CIABATTA_OPTIONS=-Iinc -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS
|
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%
|
clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS%
|
||||||
)
|
)
|
||||||
llvm-ar rc ciabatta.lib build\*.obj
|
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 int errno_t;
|
||||||
typedef size_t rsize_t;
|
typedef size_t rsize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
#define EILSEQ 2
|
#define EILSEQ 2
|
||||||
#define ERANGE 3
|
#define ERANGE 3
|
||||||
|
|
||||||
// TODO:
|
// TODO: make it thread-local
|
||||||
//_Thread_local int errno;
|
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 {
|
// typedef struct div_t {
|
||||||
// int quot;
|
// int quot;
|
||||||
|
@ -18,27 +23,31 @@
|
||||||
// #define EXIT_FAILURE 1
|
// #define EXIT_FAILURE 1
|
||||||
// #define EXIT_SUCCESS 0
|
// #define EXIT_SUCCESS 0
|
||||||
|
|
||||||
// #define RAND_MAX 65536
|
#define RAND_MAX 65536
|
||||||
// #define MB_CUR_MAX 5
|
// #define MB_CUR_MAX 5
|
||||||
|
|
||||||
// double atof(const char *nptr);
|
double atof(const char *nptr);
|
||||||
// int atoi(const char *nptr);
|
int atoi(const char *nptr);
|
||||||
// long int atol(const char *nptr);
|
long int atol(const char *nptr);
|
||||||
// long long int atoll(const char *nptr);
|
long long int atoll(const char *nptr);
|
||||||
// double strtod(const char * restrict nptr, char ** restrict endptr);
|
double strtod(const char * restrict nptr, char ** restrict endptr);
|
||||||
// float strtof(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 double strtold(const char * restrict nptr, char ** restrict endptr);
|
||||||
// long int strtol(const char * restrict nptr, char ** restrict endptr, int base);
|
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);
|
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 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);
|
unsigned long long int strtoull(const char *restrict nptr, char **restrict endptr, int base);
|
||||||
// int rand(void);
|
int rand(void);
|
||||||
// void srand(unsigned int seed);
|
void srand(unsigned int seed);
|
||||||
// void *aligned_alloc(size_t alignment, size_t size);
|
|
||||||
// void *calloc(size_t nmemb, size_t size);
|
typedef struct _os_heap _os_heap;
|
||||||
// void free(void *ptr);
|
void _heap_setup(_os_heap *heap);
|
||||||
// void *malloc(size_t size);
|
void *aligned_alloc(size_t alignment, size_t size);
|
||||||
// void *realloc(void *ptr, 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);
|
// _Noreturn void abort(void);
|
||||||
// int atexit(void (*func)(void));
|
// int atexit(void (*func)(void));
|
||||||
// int at_quick_exit(void (*func)(void));
|
// int at_quick_exit(void (*func)(void));
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include <_platform.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include "win32.h"
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
extern int main(int argc, char** argv);
|
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);
|
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");
|
setlocale(LC_ALL, "C");
|
||||||
int exit_code = main(arg_count, args);
|
int exit_code = main(arg_count, args);
|
||||||
|
|
||||||
ExitProcess(exit_code);
|
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