Compare commits
14 Commits
3cbe43eec4
...
master
Author | SHA1 | Date | |
---|---|---|---|
db8389f7d5 | |||
5e6291cdc6 | |||
596bb1ef76 | |||
595b7d06f1 | |||
6db36114d5 | |||
c3be4ce8ee | |||
d8e1d54f3d | |||
2f9ff2e757 | |||
61e59e6550 | |||
9582176638 | |||
692358fd8a | |||
579c2f34d9 | |||
5724c8ffa8 | |||
0ce4a1018e |
17
example/sb.c
Normal file
17
example/sb.c
Normal 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
10
gebs.c
@ -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
312
gebs.h
@ -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
|
||||||
|
Reference in New Issue
Block a user