Compare commits

...

10 Commits

Author SHA1 Message Date
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 256 additions and 19 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") {
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") {
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") {
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;

248
gebs.h
View File

@ -88,6 +88,7 @@ int main(int argc, char ** argv)
#include <inttypes.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
@ -95,6 +96,17 @@ int main(int argc, char ** argv)
#include <sys/wait.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))
// ----------------------------------------------------------------------------
@ -199,7 +211,7 @@ void gebs_arena_destroy_chunk(Gebs_Arena_Chunk *chunk);
#define gebs_list_append_alloc(alloc, list, item) \
do { \
if ((list)->items == NULL) { \
if ((list)->items == nil) { \
(list)->capacity = 1; \
(list)->items = gebs_malloc((alloc), \
sizeof(*(list)->items) * (list)->capacity); \
@ -220,9 +232,9 @@ void gebs_arena_destroy_chunk(Gebs_Arena_Chunk *chunk);
#define gebs_list_free_alloc(alloc, list) \
do { \
if ((list)->items != NULL) { \
if ((list)->items != nil) { \
gebs_free((alloc), (list)->items); \
(list)->items = NULL; \
(list)->items = nil; \
} \
(list)->count = 0; \
} while(0)
@ -245,6 +257,9 @@ typedef struct {
} \
} while(0)
#define gebs_nsl_join(nsl, sb, sep) \
gebs_nsl_join_alloc(&gebs_default_allocator, (nsl), (sb), (sep))
typedef struct {
char *items;
size_t count, capacity;
@ -272,6 +287,29 @@ typedef struct {
#define gebs_sb_append_nstr(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
// ----------------------------------------------------------------------------
@ -293,10 +331,17 @@ typedef Gebs_NString_List Gebs_Cmd;
#define gebs_cmd_free gebs_list_free
#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_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_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(...) \
({ \
@ -312,11 +357,18 @@ 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_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_fd_run_collect_alloc gebs_cmd_fd_run_sync_collect_alloc
#define gebs_cmd_run_collect(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
// ----------------------------------------------------------------------------
@ -336,6 +388,9 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
({ \
const char *__deps[] = { __VA_ARGS__ }; \
bool __ok = false; \
if (sizeof(__deps)/sizeof(__deps[0]) == 0) { \
__ok = true; \
} \
for (size_t __i = 0; __i < sizeof(__deps)/sizeof(__deps[0]); __i++) { \
if (gebs_needs_rebuild((out), __deps[__i])) { \
__ok = true; \
@ -352,7 +407,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
const char *__flags[] = { __VA_ARGS__ }; \
FILE *__out = fopen("compile_flags.txt", "w"); \
char __nl = '\n'; \
if (__out != NULL) { \
if (__out != nil) { \
for (size_t __i = 0; __i < sizeof(__flags)/sizeof(__flags[0]); __i++) { \
const char *__flag = __flags[__i]; \
fwrite(__flag, strlen(__flag), 1, __out); \
@ -371,8 +426,9 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
extern Gebs_Arena gebs_scratch_arena;
char *gebs_fmt(const char *fmt, ...);
void gebs_scratch_arena_reset(void);
char *gebs_fmt(const char *fmt, ...);
char *gebs_cwd(void);
#ifdef GEBS_IMPLEMENTATION
@ -383,6 +439,7 @@ void gebs_scratch_arena_reset(void);
int gebs_cmd_run_sync_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);
@ -393,7 +450,7 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *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, NULL);
gebs_cmd_append_alloc((alloc), &new_cmd, nil);
pid_t pid = vfork();
switch (pid) {
@ -424,9 +481,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};
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);
@ -437,7 +495,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++) {
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];
pipe(pipe_ends);
@ -484,6 +589,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
// ----------------------------------------------------------------------------
@ -515,7 +712,7 @@ Gebs_Arena_Chunk *gebs_arena_create_chunk(size_t capacity)
{
size_t size = sizeof(Gebs_Arena_Chunk) + sizeof(uintptr_t)*capacity;
Gebs_Arena_Chunk *chunk = (Gebs_Arena_Chunk *)malloc(size);
chunk->next = NULL;
chunk->next = nil;
chunk->size = 0;
chunk->capacity = capacity;
return chunk;
@ -532,7 +729,7 @@ void *gebs_arena_malloc(void *self, size_t size)
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;
if (capacity < sz) {
capacity = sz;
@ -541,7 +738,7 @@ void *gebs_arena_malloc(void *self, size_t size)
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;
}
@ -581,7 +778,7 @@ void *gebs_arena_realloc(void *self, void *memory,
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;
}
a->end = a->begin;
@ -595,8 +792,8 @@ void gebs_arena_destroy(Gebs_Arena *a)
chunk = chunk->next;
gebs_arena_destroy_chunk(chunk1);
}
a->begin = NULL;
a->end = NULL;
a->begin = nil;
a->end = nil;
}
// ----------------------------------------------------------------------------
@ -624,7 +821,7 @@ char *gebs_fmt(const char *fmt, ...)
va_list list_copy;
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);
char *buf = gebs_malloc(&gebs_scratch_arena, size+1);
@ -638,6 +835,15 @@ void gebs_scratch_arena_reset(void)
gebs_arena_reset(&gebs_scratch_arena);
}
char *gebs_cwd(void)
{
char *cwd = gebs_malloc(&gebs_scratch_arena, PATH_MAX);
if (getcwd(cwd, PATH_MAX) == nil) {
return nil;
}
return cwd;
}
// ----------------------------------------------------------------------------
// Filesystem operations
// ----------------------------------------------------------------------------
@ -752,7 +958,8 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define list_free gebs_list_free
#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 sb_append_char_alloc gebs_sb_append_char_alloc
@ -763,6 +970,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
#define sb_free gebs_sb_free
#define sb_finish gebs_sb_finish
#define sb_append_nstr gebs_sb_append_nstr
#define sb_read_file gebs_sb_read_file
#define rename1 gebs_rename
#define remove1 gebs_remove
@ -781,6 +989,14 @@ 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_collect_alloc gebs_cmd_run_collect_alloc
#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_many gebs_needs_rebuild_many