From 9458655faf7193150a3116e726befff6aa6a2294 Mon Sep 17 00:00:00 2001 From: NeGate Date: Tue, 7 Jun 2022 22:36:49 -0400 Subject: [PATCH] fixed realloc behavior, added getenv and reentrant strtok variant --- code/os/win/win_env.c | 30 ++++++++++++++++++++++++++++-- code/os/win/win_mem.c | 15 +++++++++++---- code/stdlib/env.c | 1 - code/string.c | 21 ++++++++++++--------- inc/stdlib.h | 2 +- inc/string.h | 39 +++++++++++++++++++++------------------ test/test.c | 7 +++++++ 7 files changed, 80 insertions(+), 35 deletions(-) diff --git a/code/os/win/win_env.c b/code/os/win/win_env.c index 76c3ecf..6154ea7 100644 --- a/code/os/win/win_env.c +++ b/code/os/win/win_env.c @@ -3,7 +3,33 @@ #include "win.h" -_Noreturn void _os_exit(int code) -{ +char* getenv(const char *name) { + // The string pointed to shall not be modified by the program, but may be + // overwritten by a subsequent call to the getenv function + static size_t env_string_cap; + static char* env_string; + + DWORD env_length = GetEnvironmentVariable(name, NULL, 0); + if (env_length == 0) { + return 0; + } + + // Upscale the internal string + if (env_length > env_string_cap) { + char* newstr = realloc(env_string, env_length); + if (newstr == NULL) { + free(env_string); + return 0; + } + + env_string = newstr; + env_string_cap = env_length; + } + + GetEnvironmentVariable(name, env_string, env_length); + return env_string; +} + +_Noreturn void _os_exit(int code) { ExitProcess(code); } diff --git a/code/os/win/win_mem.c b/code/os/win/win_mem.c index 6675287..eace9fc 100644 --- a/code/os/win/win_mem.c +++ b/code/os/win/win_mem.c @@ -39,7 +39,7 @@ void *aligned_alloc(size_t alignment, size_t size) { if(alignment > 8) { min_req_size += alignment; } - void *block_start = HeapAlloc(_heap, HEAP_ZERO_MEMORY, min_req_size); + void *block_start = HeapAlloc(_heap, 0, min_req_size); 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; @@ -69,7 +69,14 @@ void *malloc(size_t size) { } void *realloc(void *ptr, size_t size) { - void *buffer = HeapReAlloc(_heap, 0, ptr, size); - return buffer; -} + if (ptr == NULL) { + if (size == 0) return NULL; + return HeapAlloc(_heap, 0, size); + } else if (size == 0) { + HeapFree(_heap, 0, ptr); + return NULL; + } else { + return HeapReAlloc(_heap, 0, ptr, size); + } +} diff --git a/code/stdlib/env.c b/code/stdlib/env.c index fb35a06..d56f136 100644 --- a/code/stdlib/env.c +++ b/code/stdlib/env.c @@ -38,4 +38,3 @@ _Noreturn void _Exit(int status) { // doesn't run atexit routines _os_exit(status); } - diff --git a/code/string.c b/code/string.c index a2713fd..ec4fa49 100644 --- a/code/string.c +++ b/code/string.c @@ -179,27 +179,30 @@ char *strstr(const char *s1, const char *s2) { // TODO: there may be restrict-related UB char *strtok(char *restrict s1, const char *restrict s2) { - static char *restrict str; - if(s1 != NULL) str = s1; - if(str == NULL) return NULL; + static char *str; + return strtok_r(s1, s2, &str); +} - size_t junk_len = strspn(str, s2); - char *tok_start = str+junk_len; +char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx) { + if(s1 != NULL) *ctx = s1; + if(*ctx == NULL) return NULL; + + size_t junk_len = strspn(*ctx, s2); + char *tok_start = *ctx + junk_len; if(*tok_start == 0) { - str = NULL; + *ctx = NULL; return NULL; } - size_t tok_len = strcspn(str, s2); + size_t tok_len = strcspn(*ctx, s2); char *tok_end = tok_start + tok_len; *tok_end = 0; - str = tok_end+1; + *ctx = tok_end+1; return tok_start; } - char *strerror(int errnum) { switch(errnum) { case 0: return "No errors"; diff --git a/inc/stdlib.h b/inc/stdlib.h index 12f9761..749742b 100644 --- a/inc/stdlib.h +++ b/inc/stdlib.h @@ -68,7 +68,7 @@ int atexit(void (*func)(void)); // int at_quick_exit(void (*func)(void)); _Noreturn void exit(int status); _Noreturn void _Exit(int status); -// char *getenv(const char *name); +char *getenv(const char *name); // _Noreturn void quick_exit(int status); // int system(const char *string); // void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); diff --git a/inc/string.h b/inc/string.h index 774499a..d7185fa 100644 --- a/inc/string.h +++ b/inc/string.h @@ -7,19 +7,19 @@ #include #if !defined(NULL) - #define NULL ((void *)0) +#define NULL ((void *)0) #endif #if !defined(__STDC_LIB_EXT1__) - #define __STDC_LIB_EXT1__ - typedef int errno_t; - typedef size_t rsize_t; +#define __STDC_LIB_EXT1__ +typedef int errno_t; +typedef size_t rsize_t; #endif #if __STDC_WANT_SECURE_LIB__ == 1 - #if !defined(__STDC_WANT_LIB_EXT1__) - #define __STDC_WANT_LIB_EXT1__ 1 - #endif +#if !defined(__STDC_WANT_LIB_EXT1__) +#define __STDC_WANT_LIB_EXT1__ 1 +#endif #endif // int _wcsicmp(const wchar_t *string1, const wchar_t *string2); @@ -47,16 +47,19 @@ void *memset(void *s, int c, size_t n); char *strerror(int errnum); size_t strlen(const char *s); +// Linux extension: reentrant strtok +char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx); + #if __STDC_WANT_LIB_EXT1__ == 1 - errno_t memcpy_s(void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); - errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); - errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2); - errno_t strncpy_s(char *restrict s1, rsize_t s1max,const char *restrict s2, rsize_t n); - errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2); - errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); - char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); - errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); - errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); - size_t strerrorlen_s(errno_t errnum); - size_t strnlen_s(const char *str, size_t strsz); +errno_t memcpy_s(void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); +errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); +errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2); +errno_t strncpy_s(char *restrict s1, rsize_t s1max,const char *restrict s2, rsize_t n); +errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2); +errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); +char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); +errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); +errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); +size_t strerrorlen_s(errno_t errnum); +size_t strnlen_s(const char *str, size_t strsz); #endif diff --git a/test/test.c b/test/test.c index bdf2e73..1bc1dc9 100644 --- a/test/test.c +++ b/test/test.c @@ -23,6 +23,13 @@ void wack() { int main(int argc, char** argv) { atexit(wack); + char* path_env = getenv("PATH"); + char *ctx, *path_token = strtok_r(path_env, ";", &ctx); + while(path_token) { + printf("%s\n", path_token); + path_token = strtok_r(NULL, ";", &ctx); + } + test(); char input[] = "A bird came down the walk"; printf("Parsing the input string '%s'\n", input);