Compare commits

...

14 Commits

Author SHA1 Message Date
db8389f7d5 scratch arena thread safety 2025-06-28 01:29:22 +02:00
5e6291cdc6 Fix typo 2025-06-27 23:06:07 +02:00
596bb1ef76 RULE_ARRAY() to define deps with a static array 2025-06-27 20:10:38 +02:00
595b7d06f1 alias sb_read_file_alloc() 2025-06-25 13:54:52 +02:00
6db36114d5 Fix leak in sb_read_file_alloc() 2025-06-18 10:37:45 +02:00
c3be4ce8ee Allow RULE()s with 0 dependencies 2025-06-18 01:50:36 +02:00
d8e1d54f3d Typo 2025-06-16 00:51:00 +02:00
2f9ff2e757 add cmd_run_async() 2025-06-14 22:47:54 +02:00
61e59e6550 Implement cmd_run_XXX variants for running via a file descriptor 2025-06-09 20:10:46 +02:00
9582176638 nsl_join for default allocator 2025-06-09 14:32:12 +02:00
692358fd8a Cleanup after logging command 2025-06-09 14:29:38 +02:00
579c2f34d9 alias nil to NULL 2025-06-02 12:39:50 +02:00
5724c8ffa8 Add sb_read_file() 2025-06-01 23:34:31 +02:00
0ce4a1018e Add shorter types, use nil macro 2025-06-01 23:02:38 +02:00
3 changed files with 313 additions and 26 deletions

17
example/sb.c Normal file
View File

@ -0,0 +1,17 @@
#define GEBS_NO_PREFIX
#define GEBS_IMPLEMENTATION
#include "../gebs.h"
int main(int argc, char ** argv)
{
String_Builder sb_c;
if (!sb_read_file(&sb_c, "sb.c")) {
LOGE("Could not read sb.c. sb.c is in example/\n");
return 1;
}
sb_finish(&sb_c);
printf("%s\n", sb_c.items);
return 0;
}

10
gebs.c
View File

@ -11,15 +11,19 @@ int main(int argc, char ** argv)
} }
RULE("build/self_rebuild", "example/self_rebuild.c", "gebs.h") { RULE("build/self_rebuild", "example/self_rebuild.c", "gebs.h") {
CMD("gcc", "-ggdb", "-o", "build/self_rebuild", "example/self_rebuild.c"); CMD("cc", "-ggdb", "-o", "build/self_rebuild", "example/self_rebuild.c");
} }
RULE("build/arena", "example/arena.c", "gebs.h") { RULE("build/arena", "example/arena.c", "gebs.h") {
CMD("gcc", "-ggdb", "-o", "build/arena", "example/arena.c"); CMD("cc", "-ggdb", "-o", "build/arena", "example/arena.c");
} }
RULE("build/commands", "example/commands.c", "gebs.h") { RULE("build/commands", "example/commands.c", "gebs.h") {
CMD("gcc", "-ggdb", "-o", "build/commands", "example/commands.c"); CMD("cc", "-ggdb", "-o", "build/commands", "example/commands.c");
}
RULE("build/sb", "example/sb.c", "gebs.h") {
CMD("cc", "-ggdb", "-o", "build/sb", "example/sb.c");
} }
return 0; return 0;

312
gebs.h
View File

@ -88,6 +88,11 @@ int main(int argc, char ** argv)
#include <inttypes.h> #include <inttypes.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <limits.h>
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
# include <pthread.h>
#endif
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -95,6 +100,17 @@ int main(int argc, char ** argv)
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mman.h> #include <sys/mman.h>
// ----------------------------------------------------------------------------
// Types
// ----------------------------------------------------------------------------
#define nil NULL
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long long vlong;
#define discard __attribute__((unused)) #define discard __attribute__((unused))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -199,7 +215,7 @@ void gebs_arena_destroy_chunk(Gebs_Arena_Chunk *chunk);
#define gebs_list_append_alloc(alloc, list, item) \ #define gebs_list_append_alloc(alloc, list, item) \
do { \ do { \
if ((list)->items == NULL) { \ if ((list)->items == nil) { \
(list)->capacity = 1; \ (list)->capacity = 1; \
(list)->items = gebs_malloc((alloc), \ (list)->items = gebs_malloc((alloc), \
sizeof(*(list)->items) * (list)->capacity); \ sizeof(*(list)->items) * (list)->capacity); \
@ -220,9 +236,9 @@ void gebs_arena_destroy_chunk(Gebs_Arena_Chunk *chunk);
#define gebs_list_free_alloc(alloc, list) \ #define gebs_list_free_alloc(alloc, list) \
do { \ do { \
if ((list)->items != NULL) { \ if ((list)->items != nil) { \
gebs_free((alloc), (list)->items); \ gebs_free((alloc), (list)->items); \
(list)->items = NULL; \ (list)->items = nil; \
} \ } \
(list)->count = 0; \ (list)->count = 0; \
} while(0) } while(0)
@ -245,6 +261,9 @@ typedef struct {
} \ } \
} while(0) } while(0)
#define gebs_nsl_join(nsl, sb, sep) \
gebs_nsl_join_alloc(&gebs_default_allocator, (nsl), (sb), (sep))
typedef struct { typedef struct {
char *items; char *items;
size_t count, capacity; size_t count, capacity;
@ -272,6 +291,29 @@ typedef struct {
#define gebs_sb_append_nstr(sb, nstr) \ #define gebs_sb_append_nstr(sb, nstr) \
gebs_sb_append_nstr_alloc(&gebs_default_allocator, (sb), (nstr)) gebs_sb_append_nstr_alloc(&gebs_default_allocator, (sb), (nstr))
#define gebs_sb_read_file_alloc(alloc, sb, path) \
({ \
bool __ret = false; \
FILE *__f = fopen((path), "r"); \
if (__f != nil) { \
__ret = true; \
fseek(__f, 0L, SEEK_END); \
size_t __size = ftell(__f); \
rewind(__f); \
char *__buf = gebs_malloc((alloc), __size); \
fread(__buf, __size, 1, __f); \
fclose(__f); \
for (size_t __i = 0; __i < __size; __i++) { \
gebs_sb_append_char_alloc((alloc), (sb), __buf[__i]); \
} \
gebs_free((alloc), __buf); \
} \
__ret; \
})
#define gebs_sb_read_file(sb, path) \
gebs_sb_read_file_alloc(&default_allocator, (sb), (path))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Filesystem operations // Filesystem operations
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -293,10 +335,17 @@ typedef Gebs_NString_List Gebs_Cmd;
#define gebs_cmd_free gebs_list_free #define gebs_cmd_free gebs_list_free
#define gebs_cmd_run_alloc gebs_cmd_run_sync_alloc #define gebs_cmd_run_alloc gebs_cmd_run_sync_alloc
#define gebs_cmd_fd_run_alloc gebs_cmd_run_sync_alloc
#define gebs_cmd_run(cmd) gebs_cmd_run_alloc(&gebs_default_allocator, (cmd)) #define gebs_cmd_run(cmd) gebs_cmd_run_alloc(&gebs_default_allocator, (cmd))
#define gebs_cmd_fd_run(fd, cmd) gebs_cmd_fd_run_alloc(&gebs_default_allocator, fd, (cmd))
int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd); int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd);
int gebs_cmd_fd_run_sync_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd);
#define gebs_cmd_run_async(cmd) gebs_cmd_run_async_alloc(&gebs_default_allocator, (cmd))
pid_t gebs_cmd_run_async_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd);
#define GEBS_CMD(...) \ #define GEBS_CMD(...) \
({ \ ({ \
@ -312,11 +361,18 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd);
int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc,
Gebs_Cmd *cmd, Gebs_String_Builder *sb_out); Gebs_Cmd *cmd, Gebs_String_Builder *sb_out);
int gebs_cmd_fd_run_sync_collect_alloc(Gebs_Allocator *alloc, int fd,
Gebs_Cmd *cmd, Gebs_String_Builder *sb_out);
#define gebs_cmd_run_collect_alloc gebs_cmd_run_sync_collect_alloc #define gebs_cmd_run_collect_alloc gebs_cmd_run_sync_collect_alloc
#define gebs_cmd_fd_run_collect_alloc gebs_cmd_fd_run_sync_collect_alloc
#define gebs_cmd_run_collect(cmd, out) \ #define gebs_cmd_run_collect(cmd, out) \
gebs_cmd_run_collect_alloc(&gebs_default_allocator, (cmd), (out)) gebs_cmd_run_collect_alloc(&gebs_default_allocator, (cmd), (out))
#define gebs_cmd_fd_run_collect(fd, cmd, out) \
gebs_cmd_fd_run_collect_alloc(&gebs_default_allocator, (fd), (cmd), (out))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// The build system // The build system
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -336,6 +392,9 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
({ \ ({ \
const char *__deps[] = { __VA_ARGS__ }; \ const char *__deps[] = { __VA_ARGS__ }; \
bool __ok = false; \ bool __ok = false; \
if (sizeof(__deps)/sizeof(__deps[0]) == 0) { \
__ok = true; \
} \
for (size_t __i = 0; __i < sizeof(__deps)/sizeof(__deps[0]); __i++) { \ for (size_t __i = 0; __i < sizeof(__deps)/sizeof(__deps[0]); __i++) { \
if (gebs_needs_rebuild((out), __deps[__i])) { \ if (gebs_needs_rebuild((out), __deps[__i])) { \
__ok = true; \ __ok = true; \
@ -345,6 +404,21 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
__ok; \ __ok; \
}) })
#define gebs_needs_rebuild_many_array(out, array) \
({ \
bool __ok = false; \
if (sizeof((array))/sizeof((array)[0]) == 0) { \
__ok = true; \
} \
for (size_t __i = 0; __i < sizeof((array))/sizeof((array)[0]); __i++) { \
if (gebs_needs_rebuild((out), (array)[__i])) { \
__ok = true; \
break; \
} \
} \
__ok; \
})
#define gebs_make_compile_flags(...) \ #define gebs_make_compile_flags(...) \
do { \ do { \
if (gebs_needs_rebuild("compile_flags.txt", __FILE__)) { \ if (gebs_needs_rebuild("compile_flags.txt", __FILE__)) { \
@ -352,7 +426,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
const char *__flags[] = { __VA_ARGS__ }; \ const char *__flags[] = { __VA_ARGS__ }; \
FILE *__out = fopen("compile_flags.txt", "w"); \ FILE *__out = fopen("compile_flags.txt", "w"); \
char __nl = '\n'; \ char __nl = '\n'; \
if (__out != NULL) { \ if (__out != nil) { \
for (size_t __i = 0; __i < sizeof(__flags)/sizeof(__flags[0]); __i++) { \ for (size_t __i = 0; __i < sizeof(__flags)/sizeof(__flags[0]); __i++) { \
const char *__flag = __flags[__i]; \ const char *__flag = __flags[__i]; \
fwrite(__flag, strlen(__flag), 1, __out); \ fwrite(__flag, strlen(__flag), 1, __out); \
@ -364,15 +438,24 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
} while(0) } while(0)
#define GEBS_RULE(target, ...) if (needs_rebuild_many(target, __VA_ARGS__)) #define GEBS_RULE(target, ...) if (needs_rebuild_many(target, __VA_ARGS__))
#define GEBS_RULE_ARRAY(target, array) if (gebs_needs_rebuild_many_array(target, (array)))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scratch arena // Scratch arena
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
extern Gebs_Arena gebs_scratch_arena; typedef struct {
Gebs_Arena value;
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_t lock;
#endif
} Gebs_Scratch_Arena;
extern Gebs_Scratch_Arena gebs_scratch_arena;
char *gebs_fmt(const char *fmt, ...);
void gebs_scratch_arena_reset(void); void gebs_scratch_arena_reset(void);
char *gebs_fmt(const char *fmt, ...);
char *gebs_cwd(void);
#ifdef GEBS_IMPLEMENTATION #ifdef GEBS_IMPLEMENTATION
@ -383,6 +466,7 @@ void gebs_scratch_arena_reset(void);
int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd) int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
{ {
Gebs_String_Builder sb = {0}; Gebs_String_Builder sb = {0};
defer { gebs_sb_free_alloc(alloc, &sb); }
gebs_nsl_join_alloc(alloc, cmd, &sb, " "); gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb); gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items); GEBS_LOGI("cmd `%s`\n", sb.items);
@ -393,7 +477,7 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
for (size_t i = 0; i < cmd->count; i++) { for (size_t i = 0; i < cmd->count; i++) {
gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]); gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]);
} }
gebs_cmd_append_alloc((alloc), &new_cmd, NULL); gebs_cmd_append_alloc((alloc), &new_cmd, nil);
pid_t pid = vfork(); pid_t pid = vfork();
switch (pid) { switch (pid) {
@ -424,9 +508,10 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
} }
} }
int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out) int gebs_cmd_fd_run_sync_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd)
{ {
Gebs_String_Builder sb = {0}; Gebs_String_Builder sb = {0};
defer { gebs_sb_free_alloc(alloc, &sb); }
gebs_nsl_join_alloc(alloc, cmd, &sb, " "); gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb); gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items); GEBS_LOGI("cmd `%s`\n", sb.items);
@ -437,7 +522,54 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S
for (size_t i = 0; i < cmd->count; i++) { for (size_t i = 0; i < cmd->count; i++) {
gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]); gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]);
} }
gebs_cmd_append_alloc((alloc), &new_cmd, NULL); gebs_cmd_append_alloc((alloc), &new_cmd, nil);
pid_t pid = vfork();
switch (pid) {
case -1:
GEBS_LOGE("Could not vfork\n");
return -1;
case 0: {
const char *const envp[] = {NULL};
fexecve(fd, (char * const *)new_cmd.items, (char * const *)envp);
exit(EXIT_FAILURE);
} break;
default: {
int wstatus;
do {
if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
return -1;
}
if (WIFEXITED(wstatus)) {
return WEXITSTATUS(wstatus);
} else if (WIFSIGNALED(wstatus)) {
GEBS_LOGI("%d killed by %d\n", pid, WTERMSIG(wstatus));
return -1;
} else if (WIFSTOPPED(wstatus)) {
GEBS_LOGI("%d stopped by %d\n", pid, WSTOPSIG(wstatus));
return -1;
}
} while(!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
}
}
}
int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out)
{
Gebs_String_Builder sb = {0};
defer { gebs_sb_free_alloc(alloc, &sb); }
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items);
// Clone the list
Gebs_Cmd new_cmd = {0};
defer { gebs_cmd_free_alloc(alloc, &new_cmd); }
for (size_t i = 0; i < cmd->count; i++) {
gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]);
}
gebs_cmd_append_alloc((alloc), &new_cmd, nil);
int pipe_ends[2]; int pipe_ends[2];
pipe(pipe_ends); pipe(pipe_ends);
@ -484,6 +616,98 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S
} }
} }
int gebs_cmd_fd_run_sync_collect_alloc(Gebs_Allocator *alloc, int fd, Gebs_Cmd *cmd, Gebs_String_Builder *sb_out)
{
Gebs_String_Builder sb = {0};
defer { gebs_sb_free_alloc(alloc, &sb); }
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items);
// Clone the list
Gebs_Cmd new_cmd = {0};
defer { gebs_cmd_free_alloc(alloc, &new_cmd); }
for (size_t i = 0; i < cmd->count; i++) {
gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]);
}
gebs_cmd_append_alloc((alloc), &new_cmd, nil);
int pipe_ends[2];
pipe(pipe_ends);
pid_t pid = vfork();
switch (pid) {
case -1:
close(pipe_ends[0]);
close(pipe_ends[1]);
GEBS_LOGE("Could not vfork\n");
return -1;
case 0: {
close(pipe_ends[0]);
dup2(pipe_ends[1], 1);
close(pipe_ends[1]);
const char *const envp[] = {NULL};
fexecve(fd, (char *const *)new_cmd.items, (char *const *)envp);
exit(EXIT_FAILURE);
} break;
default: {
close(pipe_ends[1]);
char c;
while (read(pipe_ends[0], &c, 1) > 0) {
gebs_sb_append_char_alloc(alloc, sb_out, c);
}
gebs_sb_finish_alloc(alloc, sb_out);
int wstatus;
do {
if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
return -1;
}
if (WIFEXITED(wstatus)) {
return WEXITSTATUS(wstatus);
} else if (WIFSIGNALED(wstatus)) {
GEBS_LOGI("%d killed by %d\n", pid, WTERMSIG(wstatus));
return -1;
} else if (WIFSTOPPED(wstatus)) {
GEBS_LOGI("%d stopped by %d\n", pid, WSTOPSIG(wstatus));
return -1;
}
} while(!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
}
}
}
pid_t gebs_cmd_run_async_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
{
Gebs_String_Builder sb = {0};
defer { gebs_sb_free_alloc(alloc, &sb); }
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items);
// Clone the list
Gebs_Cmd new_cmd = {0};
defer { gebs_cmd_free_alloc(alloc, &new_cmd); }
for (size_t i = 0; i < cmd->count; i++) {
gebs_cmd_append_alloc(alloc, &new_cmd, cmd->items[i]);
}
gebs_cmd_append_alloc((alloc), &new_cmd, nil);
pid_t pid = vfork();
switch (pid) {
case -1:
GEBS_LOGE("Could not vfork\n");
return -1;
case 0:
execvp(new_cmd.items[0], (char * const *)new_cmd.items);
exit(EXIT_FAILURE);
default:
return pid;
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Allocators // Allocators
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -515,7 +739,7 @@ Gebs_Arena_Chunk *gebs_arena_create_chunk(size_t capacity)
{ {
size_t size = sizeof(Gebs_Arena_Chunk) + sizeof(uintptr_t)*capacity; size_t size = sizeof(Gebs_Arena_Chunk) + sizeof(uintptr_t)*capacity;
Gebs_Arena_Chunk *chunk = (Gebs_Arena_Chunk *)malloc(size); Gebs_Arena_Chunk *chunk = (Gebs_Arena_Chunk *)malloc(size);
chunk->next = NULL; chunk->next = nil;
chunk->size = 0; chunk->size = 0;
chunk->capacity = capacity; chunk->capacity = capacity;
return chunk; return chunk;
@ -532,7 +756,7 @@ void *gebs_arena_malloc(void *self, size_t size)
size_t sz = (size + sizeof(uintptr_t) - 1)/sizeof(uintptr_t); size_t sz = (size + sizeof(uintptr_t) - 1)/sizeof(uintptr_t);
if (a->end == NULL) { if (a->end == nil) {
size_t capacity = GEBS_ARENA_CHUNK_CAPACITY; size_t capacity = GEBS_ARENA_CHUNK_CAPACITY;
if (capacity < sz) { if (capacity < sz) {
capacity = sz; capacity = sz;
@ -541,7 +765,7 @@ void *gebs_arena_malloc(void *self, size_t size)
a->begin = a->end; a->begin = a->end;
} }
while (a->end->size + sz > a->end->capacity && a->end->next != NULL) { while (a->end->size + sz > a->end->capacity && a->end->next != nil) {
a->end = a->end->next; a->end = a->end->next;
} }
@ -581,7 +805,7 @@ void *gebs_arena_realloc(void *self, void *memory,
void gebs_arena_reset(Gebs_Arena *a) void gebs_arena_reset(Gebs_Arena *a)
{ {
for (Gebs_Arena_Chunk *chunk = a->begin; chunk != NULL; chunk = chunk->next) { for (Gebs_Arena_Chunk *chunk = a->begin; chunk != nil; chunk = chunk->next) {
chunk->size = 0; chunk->size = 0;
} }
a->end = a->begin; a->end = a->begin;
@ -595,47 +819,77 @@ void gebs_arena_destroy(Gebs_Arena *a)
chunk = chunk->next; chunk = chunk->next;
gebs_arena_destroy_chunk(chunk1); gebs_arena_destroy_chunk(chunk1);
} }
a->begin = NULL; a->begin = nil;
a->end = NULL; a->end = nil;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scratch arena // Scratch arena
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Gebs_Arena gebs_scratch_arena; Gebs_Scratch_Arena gebs_scratch_arena;
__attribute__((constructor)) __attribute__((constructor))
void gebs_scratch_areana_init(void) void gebs_scratch_areana_init(void)
{ {
gebs_scratch_arena = gebs_arena_get(); gebs_scratch_arena.value = gebs_arena_get();
} }
__attribute__((destructor)) __attribute__((destructor))
void gebs_scratch_areana_free(void) void gebs_scratch_areana_free(void)
{ {
gebs_arena_destroy(&gebs_scratch_arena); gebs_arena_destroy(&gebs_scratch_arena.value);
} }
char *gebs_fmt(const char *fmt, ...) char *gebs_fmt(const char *fmt, ...)
{ {
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_lock(&gebs_scratch_arena.lock);
#endif
va_list list; va_list list;
va_start(list, fmt); va_start(list, fmt);
va_list list_copy; va_list list_copy;
va_copy(list_copy, list); va_copy(list_copy, list);
size_t size = vsnprintf(NULL, 0, fmt, list_copy); size_t size = vsnprintf(nil, 0, fmt, list_copy);
va_end(list_copy); va_end(list_copy);
char *buf = gebs_malloc(&gebs_scratch_arena, size+1); char *buf = gebs_malloc(&gebs_scratch_arena.value, size+1);
vsprintf(buf, fmt, list); vsprintf(buf, fmt, list);
va_end(list); va_end(list);
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_unlock(&gebs_scratch_arena.lock);
#endif
return buf; return buf;
} }
void gebs_scratch_arena_reset(void) void gebs_scratch_arena_reset(void)
{ {
gebs_arena_reset(&gebs_scratch_arena); #ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_lock(&gebs_scratch_arena.lock);
#endif
gebs_arena_reset(&gebs_scratch_arena.value);
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_unlock(&gebs_scratch_arena.lock);
#endif
}
char *gebs_cwd(void)
{
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_lock(&gebs_scratch_arena.lock);
#endif
char *cwd = gebs_malloc(&gebs_scratch_arena.value, PATH_MAX);
if (getcwd(cwd, PATH_MAX) == nil) {
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_unlock(&gebs_scratch_arena.lock);
#endif
return nil;
}
#ifdef GEBS_ENABLE_PTHREAD_FEATURES
pthread_mutex_unlock(&gebs_scratch_arena.lock);
#endif
return cwd;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -752,7 +1006,8 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define list_free gebs_list_free #define list_free gebs_list_free
#define NString_List Gebs_NString_List #define NString_List Gebs_NString_List
#define nsl_join_alloc gebs_nls_join_alloc #define nsl_join_alloc gebs_nsl_join_alloc
#define nsl_join gebs_nsl_join
#define String_Builder Gebs_String_Builder #define String_Builder Gebs_String_Builder
#define sb_append_char_alloc gebs_sb_append_char_alloc #define sb_append_char_alloc gebs_sb_append_char_alloc
@ -763,6 +1018,8 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define sb_free gebs_sb_free #define sb_free gebs_sb_free
#define sb_finish gebs_sb_finish #define sb_finish gebs_sb_finish
#define sb_append_nstr gebs_sb_append_nstr #define sb_append_nstr gebs_sb_append_nstr
#define sb_read_file gebs_sb_read_file
#define sb_read_file_alloc gebs_sb_read_file_alloc
#define rename1 gebs_rename #define rename1 gebs_rename
#define remove1 gebs_remove #define remove1 gebs_remove
@ -771,7 +1028,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define Cmd Gebs_Cmd #define Cmd Gebs_Cmd
#define cmd_append_alloc gebs_cmd_append_alloc #define cmd_append_alloc gebs_cmd_append_alloc
#define cmd_free_aloc gebs_cmd_free_alloc #define cmd_free_alloc gebs_cmd_free_alloc
#define cmd_append gebs_cmd_append #define cmd_append gebs_cmd_append
#define cmd_free gebs_cmd_free #define cmd_free gebs_cmd_free
#define cmd_run_alloc gebs_cmd_run_alloc #define cmd_run_alloc gebs_cmd_run_alloc
@ -781,12 +1038,21 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define cmd_run_sync_collect_alloc gebs_cmd_run_sync_collect_alloc #define cmd_run_sync_collect_alloc gebs_cmd_run_sync_collect_alloc
#define cmd_run_collect_alloc gebs_cmd_run_collect_alloc #define cmd_run_collect_alloc gebs_cmd_run_collect_alloc
#define cmd_run_collect gebs_cmd_run_collect #define cmd_run_collect gebs_cmd_run_collect
#define cmd_fd_run_sync_collect_alloc gebs_cmd_fd_run_sync_collect_alloc
#define cmd_fd_run_collect_alloc gebs_cmd_fd_run_collect_alloc
#define cmd_fd_run_collect gebs_cmd_fd_run_collect
#define cmd_fd_run_sync_alloc gebs_cmd_fd_run_sync_alloc
#define cmd_fd_run_alloc gebs_cmd_fd_run_alloc
#define cmd_fd_run gebs_cmd_fd_run
#define cmd_run_async_alloc gebs_cmd_run_async_alloc
#define cmd_run_async gebs_cmd_run_async
#define needs_rebuild gebs_needs_rebuild #define needs_rebuild gebs_needs_rebuild
#define needs_rebuild_many gebs_needs_rebuild_many #define needs_rebuild_many gebs_needs_rebuild_many
#define rebuild_self gebs_rebuild_self #define rebuild_self gebs_rebuild_self
#define make_compile_flags gebs_make_compile_flags #define make_compile_flags gebs_make_compile_flags
#define RULE GEBS_RULE #define RULE GEBS_RULE
#define RULE_ARRAY GEBS_RULE_ARRAY
#define scratch_arena gebs_scratch_arena #define scratch_arena gebs_scratch_arena
#define fmt gebs_fmt #define fmt gebs_fmt