Compare commits
13 Commits
5960af297c
...
unstable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b6873ebad | ||
|
|
d68fc7db47 | ||
|
|
87085661a2 | ||
|
|
c7a96b14e8 | ||
|
|
3cba603e7c | ||
|
|
abe970c173 | ||
|
|
5fd1f72624 | ||
|
|
fbb1868d82 | ||
|
|
1b889b7625 | ||
|
|
e61af99a0c | ||
|
|
38ca8ae719 | ||
|
|
b62d35a130 | ||
|
|
724b0047e6 |
21
README.md
21
README.md
@@ -1,5 +1,7 @@
|
||||
# ibuild
|
||||
A simple build system written in C. The project is incomplete and is not meant to be used by anyone. It is designed to work out-of-the-box on C/C++ projects. However, it has a Recursive Descent Parser and supports a very small DSL. The DSL is in the format of a very basic configuration file. As of now, there is no complex configuration support as well as cross-platform compatibility features, as this is only available in linux.
|
||||
A simple build system written in C. The project is incomplete and is not meant to be used by anyone. It is designed to work out-of-the-box on C/C++ projects.
|
||||
|
||||
This project is maintained in: <https://universe.0xinfinity.dev/0x221E/ibuild>, where the plans, issues, and wiki are located.
|
||||
|
||||
## Security Disclaimer
|
||||
The project has not been battle-tested yet. I am not using as a daily driver yet, and when I do, I will conduct thorough testing by fuzzing the application continously for a period of time (likely a week).
|
||||
@@ -12,13 +14,12 @@ You either place the executable to your /usr/local/bin, or place it into your pr
|
||||
Then run `ibuild`, and it should build the binary.
|
||||
|
||||
## Configuration File
|
||||
Below is a sample configuration file;
|
||||
Below is a sample (future) syntax;
|
||||
````
|
||||
COMPILER_PATH = "/usr/bin/gcc"
|
||||
SRC_DIR = "src" # Recursively discovers files here
|
||||
SRC_FILES = ["src/main.c"] # Manual file specification is optional
|
||||
TARGET_EXEC = "ibuild" # executable name
|
||||
DEP_SEARCHER = "/usr/bin/gcc" # Default, no need to specify explicitly
|
||||
DEP_SEARCHER_FLAGS = "-MM" # Default, no need to specify explicitly
|
||||
VERSION = "0.0.1" # Can specify version here, which would be passed as a macro.
|
||||
````
|
||||
KEY = "VALUE";
|
||||
KEY = ["VALUE1", "VALUE2"];
|
||||
````
|
||||
### All Key-Values
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| CC_COMPILER_PATH | `e.g. /usr/bin/gcc`|
|
||||
2
build.sh
2
build.sh
@@ -1 +1 @@
|
||||
gcc -o ibuild src/main.c src/memory.c src/utils.c src/string.c src/discovery.c src/io.c -fsanitize=address -g -DDEBUG
|
||||
gcc -o example/ibuild src/main.c src/memory.c src/utils.c src/string.c src/discovery.c src/io.c src/command.c src/build.c -fsanitize=address -g -DDEBUG -Wall -Wextra -Wpedantic -Wshadow
|
||||
|
||||
8
example/main.c
Normal file
8
example/main.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
printf("This is build 2!\n");
|
||||
return 0;
|
||||
}
|
||||
1
example/test.c
Normal file
1
example/test.c
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
87
src/build.c
Normal file
87
src/build.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "build.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "string.h"
|
||||
#include "discovery.h"
|
||||
#include "command.h"
|
||||
#include "io.h"
|
||||
#include "utils.h"
|
||||
|
||||
// Only supports C and multiple files
|
||||
|
||||
void build(BuildContext* bc)
|
||||
{
|
||||
assert(bc != NULL);
|
||||
assert(bc->sp != NULL);
|
||||
|
||||
int sc = build_c_to_o(bc);
|
||||
if(sc != 0) DIE("Compilation failed!");
|
||||
link(bc);
|
||||
}
|
||||
|
||||
void link(BuildContext* bc)
|
||||
{
|
||||
assert(bc != NULL);
|
||||
|
||||
if(bc->obj_files == NULL) DIE("Linking process was triggered, however there are no object files.");
|
||||
|
||||
Command cmd;
|
||||
cmd.a = bc->a;
|
||||
cmd.app = bc->d->cc;
|
||||
|
||||
size_t len = bc->d->c_count + 2;
|
||||
|
||||
const char** args = (const char**)arena_alloc(bc->a, sizeof(const char*) * len);
|
||||
|
||||
args[0] = bc->d->cc.buf;
|
||||
|
||||
for(size_t i = 0; i < bc->d->c_count; i++)
|
||||
{
|
||||
args[i + 1] = bc->obj_files[i]->buf;
|
||||
}
|
||||
|
||||
args[len - 1] = NULL;
|
||||
cmd.args = args;
|
||||
|
||||
int status = command_run(&cmd);
|
||||
if(status != 0)
|
||||
DIE("Linking failed with status code: %d");
|
||||
|
||||
LOG_DEBUG("Linking completed!");
|
||||
}
|
||||
|
||||
int build_c_to_o(BuildContext* bc)
|
||||
{
|
||||
assert(bc != NULL);
|
||||
if(bc->d->c_count == 0)
|
||||
return 1;
|
||||
|
||||
CommandOptions co;
|
||||
co.a = bc->a;
|
||||
co.sp = bc->sp;
|
||||
co.bp = bc->build_profile;
|
||||
co.c = bc->c;
|
||||
co.app = bc->d->cc;
|
||||
|
||||
StringView* arr = (StringView*)arena_alloc(bc->a, sizeof(StringView) * 1);
|
||||
co.files = arr;
|
||||
|
||||
StringView** obj_files = (StringView**)arena_alloc(bc->a, sizeof(StringView*) * bc->d->c_count);
|
||||
bc->obj_files = obj_files;
|
||||
|
||||
for(size_t i = 0; i < bc->d->c_count; i++)
|
||||
{
|
||||
co.files[0] = bc->d->c_files[i]->path;
|
||||
Command cmd = command_create_f_to_o(&co);
|
||||
int status = command_run(&cmd);
|
||||
if(status != 0)
|
||||
DIE("Failed to compile %s, compiler exited with status code: %d", bc->d->c_files[i]->path.buf, status);
|
||||
bc->obj_files[i] = &bc->d->c_files[i]->path;
|
||||
LOG_DEBUG("Compiling %s", bc->d->c_files[i]->path.buf);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
36
src/build.h
Normal file
36
src/build.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef BUILD_H
|
||||
#define BUILD_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct Configuration Configuration;
|
||||
typedef struct Discovery Discovery;
|
||||
typedef struct Arena Arena;
|
||||
typedef struct StringPool StringPool;
|
||||
typedef struct StringView StringView;
|
||||
typedef struct Command Command;
|
||||
|
||||
struct BuildContext
|
||||
{
|
||||
// Memory
|
||||
Arena* a;
|
||||
StringPool* sp;
|
||||
|
||||
// Build Params
|
||||
enum BuildProfile build_profile;
|
||||
Configuration* c;
|
||||
Discovery* d;
|
||||
|
||||
StringView** obj_files;
|
||||
};
|
||||
|
||||
typedef enum BuildProfile BuildProfile;
|
||||
typedef struct BuildContext BuildContext;
|
||||
|
||||
void build(BuildContext* bc);
|
||||
|
||||
void link(BuildContext* bc);
|
||||
|
||||
int build_c_to_o(BuildContext* bc);
|
||||
|
||||
#endif
|
||||
87
src/command.c
Normal file
87
src/command.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "command.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "discovery.h"
|
||||
#include "io.h"
|
||||
#include "utils.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
// TODO: This file is UNSAFE. This file is purely here for MVP purposes, and to self-host this program itself.
|
||||
|
||||
Command command_create_f_to_o(CommandOptions* co)
|
||||
{
|
||||
assert(co != NULL);
|
||||
|
||||
size_t len_args = 6;
|
||||
|
||||
ProfileResult pr = command_get_profile(co);
|
||||
len_args += pr.compiler_flags_count;
|
||||
|
||||
const char** args_buf = (const char**)arena_alloc(co->a, sizeof(const char*) * len_args);
|
||||
args_buf[0] = co->app.buf;
|
||||
args_buf[1] = "-c";
|
||||
args_buf[2] = co->files[0].buf;
|
||||
args_buf[3] = "-o";
|
||||
|
||||
StringView o_ext = STR_LIT(co->sp, ".o");
|
||||
StringView f_o = string_concat_ss(co->sp, &co->files[0], &o_ext);
|
||||
args_buf[4] = f_o.buf;
|
||||
args_buf[5] = "-MMD";
|
||||
|
||||
for (size_t i = 0; i < pr.compiler_flags_count; i++)
|
||||
{
|
||||
args_buf[i + 6] = pr.compiler_flags_buf[i].buf;
|
||||
}
|
||||
|
||||
args_buf[len_args] = NULL;
|
||||
|
||||
LOG_DEBUG("Command created, first 4 args: %s %s %s %s %s | total args: %d", args_buf[0], args_buf[1], args_buf[2], args_buf[3], args_buf[4], len_args);
|
||||
|
||||
return (Command){.a = co->a, .app = co->app, .args = args_buf};
|
||||
}
|
||||
|
||||
ProfileResult command_get_profile(CommandOptions* co)
|
||||
{
|
||||
ProfileResult pr;
|
||||
switch(co->bp)
|
||||
{
|
||||
case B_DEBUG:
|
||||
pr.compiler_flags_count = co->c->debug_compiler_flags_c;
|
||||
pr.compiler_flags_buf = co->c->debug_compiler_flags;
|
||||
break;
|
||||
case B_PROD:
|
||||
pr.compiler_flags_count = co->c->prod_compiler_flags_c;
|
||||
pr.compiler_flags_buf = co->c->prod_compiler_flags;
|
||||
break;
|
||||
default:
|
||||
DIE("No configuration was selected!");
|
||||
}
|
||||
return pr;
|
||||
}
|
||||
|
||||
// TODO: Add input sanitization to cmd->app and cmd->args
|
||||
int command_run(Command* cmd)
|
||||
{
|
||||
assert(cmd != NULL);
|
||||
if(cmd->args == NULL) DIE("No arguments were supplied to the command");
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if(pid == -1) DIE("fork failed, could not create child process.");
|
||||
|
||||
if(pid == 0)
|
||||
{
|
||||
if(execvp(cmd->app.buf, (char*const*)cmd->args) == -1)
|
||||
DIE("Failed to launch command: %s.", cmd->app.buf);
|
||||
}
|
||||
|
||||
int wstatus = 0;
|
||||
if(waitpid(pid, &wstatus, 0) == -1) DIE("wait failed.");
|
||||
LOG_DEBUG("Command calling app %s exited with status code %d on child process PID %d.", cmd->app.buf, wstatus, pid);
|
||||
return wstatus;
|
||||
}
|
||||
|
||||
44
src/command.h
Normal file
44
src/command.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
#include "string.h"
|
||||
#include "common.h"
|
||||
|
||||
typedef struct Arena Arena;
|
||||
typedef struct Discovery Discovery;
|
||||
typedef struct Configuration Configuration;
|
||||
|
||||
struct CommandOptions
|
||||
{
|
||||
Arena* a;
|
||||
StringPool* sp;
|
||||
BuildProfile bp;
|
||||
Configuration* c;
|
||||
StringView app;
|
||||
StringView* files;
|
||||
};
|
||||
|
||||
struct ProfileResult
|
||||
{
|
||||
size_t compiler_flags_count;
|
||||
StringView* compiler_flags_buf;
|
||||
};
|
||||
|
||||
struct Command
|
||||
{
|
||||
Arena* a;
|
||||
StringView app;
|
||||
const char** args;
|
||||
};
|
||||
|
||||
typedef struct Argument Argument;
|
||||
typedef struct Command Command;
|
||||
typedef struct CommandOptions CommandOptions;
|
||||
typedef struct ProfileResult ProfileResult;
|
||||
|
||||
Command command_create_f_to_o(CommandOptions* co);
|
||||
ProfileResult command_get_profile(CommandOptions* co);
|
||||
|
||||
int command_run(Command* cmd);
|
||||
|
||||
#endif
|
||||
12
src/common.h
Normal file
12
src/common.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
enum BuildProfile
|
||||
{
|
||||
B_DEBUG,
|
||||
B_PROD
|
||||
};
|
||||
|
||||
typedef enum BuildProfile BuildProfile;
|
||||
|
||||
#endif
|
||||
2
src/config.c
Normal file
2
src/config.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "config.h"
|
||||
|
||||
30
src/config.h
Normal file
30
src/config.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "string.h"
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
// C-Compiler Flags
|
||||
StringView cc_compiler_path;
|
||||
StringView src_dir;
|
||||
|
||||
// General Flags
|
||||
//StringView* src_files;
|
||||
|
||||
// Debug Profile
|
||||
StringView* debug_compiler_flags;
|
||||
size_t debug_compiler_flags_c;
|
||||
|
||||
// Production Profile
|
||||
StringView* prod_compiler_flags;
|
||||
size_t prod_compiler_flags_c;
|
||||
|
||||
// Linker arguments
|
||||
StringView* linker_flags;
|
||||
size_t linker_flags_c;
|
||||
};
|
||||
|
||||
typedef struct Configuration Configuration;
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Discovery discovery_create(Arena* a, StringPool* sp)
|
||||
{
|
||||
@@ -31,23 +34,18 @@ Discovery discovery_create(Arena* a, StringPool* sp)
|
||||
return d;
|
||||
}
|
||||
|
||||
void discovery_cleanup(Discovery* d)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void discovery_discover(Discovery* d)
|
||||
{
|
||||
assert(d != NULL);
|
||||
DirOpContext doc;
|
||||
doc.a_f = d->a;
|
||||
doc.sp = d->sp;
|
||||
StringView path = SV(d->sp, ".");
|
||||
StringView path = STR_LIT(d->sp, ".");
|
||||
size_t count = dir_get_recursive(&doc, &path);
|
||||
d->file_count = count;
|
||||
LOG_DEBUG("Discovered %d files.", count);
|
||||
|
||||
StringView c_ext = SV(d->sp, ".c");
|
||||
StringView c_ext = STR_LIT(d->sp, ".c");
|
||||
ExtDiscoveryResult c_res = discovery_discover_ext(d, d->a, &c_ext);
|
||||
|
||||
if(c_res.mem != NULL)
|
||||
@@ -57,7 +55,7 @@ void discovery_discover(Discovery* d)
|
||||
d->c_files = c_res.mem;
|
||||
}
|
||||
|
||||
StringView h_ext = SV(d->sp, ".h");
|
||||
StringView h_ext = STR_LIT(d->sp, ".h");
|
||||
ExtDiscoveryResult h_res = discovery_discover_ext(d, d->a, &h_ext);
|
||||
|
||||
if(h_res.mem != NULL)
|
||||
@@ -66,6 +64,35 @@ void discovery_discover(Discovery* d)
|
||||
d->h_count = h_res.len;
|
||||
d->h_files = h_res.mem;
|
||||
}
|
||||
|
||||
if(d->c_count > 0)
|
||||
{
|
||||
discovery_discover_ccompiler(d);
|
||||
}
|
||||
}
|
||||
|
||||
void discovery_discover_ccompiler(Discovery* d)
|
||||
{
|
||||
assert(d != NULL);
|
||||
|
||||
StringView gcc = STR_LIT(d->sp, "gcc");
|
||||
StringView cc_gcc = discovery_discover_path(d, &gcc);
|
||||
|
||||
if(cc_gcc.buf != NULL)
|
||||
{
|
||||
d->cc = cc_gcc;
|
||||
return;
|
||||
}
|
||||
|
||||
StringView clang = STR_LIT(d->sp, "clang");
|
||||
StringView cc_clang = discovery_discover_path(d, &clang);
|
||||
|
||||
if(cc_clang.buf != NULL)
|
||||
{
|
||||
d->cc = cc_clang;
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("No C compilers were found, however, %d C files were found. Not installed?", d->c_count);
|
||||
}
|
||||
|
||||
// TODO: Make the search logic faster, or at least search all of the wanted extension at once, uniformly.
|
||||
@@ -91,9 +118,40 @@ ExtDiscoveryResult discovery_discover_ext(Discovery* d, Arena* a, StringView* ex
|
||||
DirEntry** entry = (DirEntry**)arena_alloc(a, sizeof(DirEntry*));
|
||||
*entry = &d->files[i];
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(count > 0) return (ExtDiscoveryResult){.mem = res, .len = count};
|
||||
return (ExtDiscoveryResult){.mem = NULL, .len = 0};
|
||||
}
|
||||
|
||||
StringView discovery_discover_path(Discovery* d, StringView* s)
|
||||
{
|
||||
assert(d != NULL);
|
||||
assert(s != NULL);
|
||||
|
||||
char* path_env = getenv("PATH");
|
||||
|
||||
if(path_env == NULL) return (StringView){.buf = NULL, .len = 0};
|
||||
|
||||
char* path = strdup(path_env);
|
||||
|
||||
errno = 0;
|
||||
if(path == NULL && errno != 0) DIE("String copy failure.");
|
||||
|
||||
char* current = strtok(path, ":");
|
||||
do
|
||||
{
|
||||
LOG_DEBUG("Checking: %s for %s in PATH.", current, s->buf);
|
||||
StringView p = string_create(d->sp, current, strlen(current));
|
||||
StringView fp = path_concat_ss(d->sp, &p, s);
|
||||
if(access(fp.buf, X_OK) == 0)
|
||||
{
|
||||
LOG_DEBUG("Found %s in PATH:%s", s->buf, p.buf);
|
||||
return fp;
|
||||
}
|
||||
}while((current = strtok(NULL, ":")) != NULL);
|
||||
|
||||
return (StringView){.buf = NULL, .len = 0};
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
|
||||
typedef struct Arena Arena;
|
||||
typedef struct StringPool StringPool;
|
||||
typedef struct StringView StringView;
|
||||
typedef struct DirEntry DirEntry;
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
struct Discovery
|
||||
{
|
||||
// Memory
|
||||
@@ -25,6 +26,9 @@ struct Discovery
|
||||
size_t c_count;
|
||||
size_t h_count;
|
||||
size_t cpp_count;
|
||||
|
||||
StringView cc;
|
||||
StringView cxx;
|
||||
};
|
||||
|
||||
struct ExtDiscoveryResult
|
||||
@@ -40,6 +44,9 @@ Discovery discovery_create(Arena* a, StringPool* sp);
|
||||
void discovery_cleanup(Discovery* d);
|
||||
void discovery_discover(Discovery* d);
|
||||
|
||||
void discovery_discover_ccompiler(Discovery* d);
|
||||
|
||||
ExtDiscoveryResult discovery_discover_ext(Discovery* d, Arena* a, StringView* ext);
|
||||
StringView discovery_discover_path(Discovery* d, StringView* s);
|
||||
|
||||
#endif
|
||||
|
||||
8
src/io.c
8
src/io.c
@@ -14,10 +14,10 @@ StringView path_concat_ss(StringPool *sp, StringView* a, StringView* b)
|
||||
if(b == NULL) DIE("b must be a valid string!");
|
||||
if(a->len <= 0 || b->len <= 0) DIE("a and b must not be empty! (a:%d, b:%d)", a->len, b->len);
|
||||
if(a->buf[a->len - 1] == '/')
|
||||
return string_createcat_ss(sp, a, b);
|
||||
return string_concat_ss(sp, a, b);
|
||||
StringView slash = (StringView){.buf = "/", .len = 1};
|
||||
StringView ts = string_createcat_ss(sp, a, &slash);
|
||||
return string_createcat_ss(sp, &ts, b);
|
||||
StringView ts = string_concat_ss(sp, a, &slash);
|
||||
return string_concat_ss(sp, &ts, b);
|
||||
}
|
||||
|
||||
// Utilize DFS for recursive directory search.
|
||||
@@ -40,7 +40,7 @@ size_t dir_get_recursive(DirOpContext* doc, StringView* p)
|
||||
if(de == NULL && errno != 0) DIE("failed to read directory: \"%s\"", p);
|
||||
if(de == NULL) break;
|
||||
|
||||
if(de->d_type == DT_UNKNOWN) DIE("Filesystem not supported!!");
|
||||
if(de->d_type == DT_UNKNOWN) DIE("Filesystem not supported!!"); // Add support for modern filesystems using stat()
|
||||
if(de->d_type != DT_DIR && de->d_type != DT_REG) continue;
|
||||
if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, ".git") == 0) continue;
|
||||
|
||||
|
||||
26
src/main.c
26
src/main.c
@@ -7,20 +7,34 @@
|
||||
#include "utils.h"
|
||||
#include "string.h"
|
||||
#include "discovery.h"
|
||||
#include "command.h"
|
||||
#include "config.h"
|
||||
#include "build.h"
|
||||
|
||||
int main(void) {
|
||||
Backend b = {NULL, 0};
|
||||
int main(void)
|
||||
{
|
||||
Backend b = BACKEND_CONST;
|
||||
backend_initialize(&b);
|
||||
|
||||
Arena a_sp = arena_create(&b, MEM_ARENA_MAX_CAP);
|
||||
Arena a_sp = arena_create(&b, MEM_ARENA_MAX_CAP);
|
||||
StringPool sp = string_pool_create(&a_sp);
|
||||
|
||||
Arena a_sptemp = arena_create(&b, MEM_ARENA_MAX_CAP);
|
||||
StringPool sp_temp = string_pool_create(&a_sptemp);
|
||||
|
||||
Arena a_d = arena_create(&b, 1024*1024*5); // 5MB for Discovery
|
||||
Discovery d = discovery_create(&a_d, &sp);
|
||||
discovery_discover(&d);
|
||||
|
||||
Configuration sample_config;
|
||||
|
||||
Arena a_b = arena_create(&b, 1024*1024*5);
|
||||
|
||||
BuildContext bc;
|
||||
bc.build_profile = B_DEBUG;
|
||||
bc.d = &d;
|
||||
bc.c = &sample_config;
|
||||
bc.a = &a_b;
|
||||
bc.sp = &sp;
|
||||
|
||||
build(&bc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void* backend_reserve(Backend* b, size_t cap)
|
||||
{
|
||||
assert(b != NULL);
|
||||
void* ptr = b->last;
|
||||
if(b->len + cap >= MEM_BACKEND_MAX_CAP)
|
||||
if(b->len + cap >= b->cap)
|
||||
DIE("Process out of memory, requested %d (current usage %d out of %d).", cap, b->len, b->cap);
|
||||
b->last = (char*)b->last + (int)cap;
|
||||
b->len += cap;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
|
||||
#ifndef MEM_ARENA_MAX_CAP
|
||||
#define MEM_ARENA_MAX_CAP 1024 * 1024
|
||||
#endif
|
||||
@@ -20,16 +19,20 @@ struct Backend
|
||||
size_t cap;
|
||||
};
|
||||
|
||||
#define BACKEND_CONST {NULL, NULL, 0, 0}
|
||||
|
||||
struct Arena
|
||||
{
|
||||
void* mem;
|
||||
void* last;
|
||||
size_t len;
|
||||
size_t cap;
|
||||
void* next;
|
||||
void* next; //TODO
|
||||
struct Backend* b;
|
||||
};
|
||||
|
||||
#define ARENA_CONST {NULL, NULL, 0, 0, NULL}
|
||||
|
||||
typedef struct Backend Backend;
|
||||
typedef struct Arena Arena;
|
||||
|
||||
|
||||
@@ -14,11 +14,6 @@ StringPool string_pool_create(Arena* a)
|
||||
return sp;
|
||||
}
|
||||
|
||||
void string_pool_reset(StringPool* ps)
|
||||
{
|
||||
// arena_reset(&ps->a);
|
||||
}
|
||||
|
||||
StringView string_create(StringPool* sp, const char* s, size_t len)
|
||||
{
|
||||
assert(sp != NULL);
|
||||
@@ -30,7 +25,7 @@ StringView string_create(StringPool* sp, const char* s, size_t len)
|
||||
return (StringView){.buf = buf, .len=len};
|
||||
}
|
||||
|
||||
StringView string_createcat_ss(StringPool* sp, StringView* a, StringView* b)
|
||||
StringView string_concat_ss(StringPool* sp, StringView* a, StringView* b)
|
||||
{
|
||||
if(a == NULL) DIE("a must be a valid C-style string!");
|
||||
if(b == NULL) DIE("b must be a valid C-style string!");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SV(sp, s) string_create(sp, s, sizeof(s) - 1)
|
||||
#define STR_LIT(sp, s) string_create(sp, s, sizeof(s) - 1)
|
||||
|
||||
struct StringPool
|
||||
{
|
||||
@@ -22,11 +22,10 @@ typedef struct StringPool StringPool;
|
||||
typedef struct StringView StringView;
|
||||
|
||||
StringPool string_pool_create(Arena* a);
|
||||
void string_pool_reset(StringPool* sp);
|
||||
|
||||
StringView string_create(StringPool* sp, const char* s, size_t len);
|
||||
|
||||
// Ensure that lengths do not contain null term
|
||||
StringView string_createcat_ss(StringPool* sp, StringView* a, StringView* b);
|
||||
StringView string_concat_ss(StringPool* sp, StringView* a, StringView* b);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
void die_f(const char* func, int l, const char* fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args);
|
||||
va_start(args, fmt);
|
||||
printf("IBUILD Error (%d:%s): ", l, func);
|
||||
vprintf(fmt, args);
|
||||
printf("\nlast syscall error: \n", strerror(errno));
|
||||
printf("\nlast syscall error: %s \n", strerror(errno));
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
@@ -21,7 +21,7 @@ void die_f(const char* func, int l, const char* fmt,...)
|
||||
void log_f(const char* func, int l, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args);
|
||||
va_start(args, fmt);
|
||||
printf("IBUILD Log (%d:%s): ", l, func);
|
||||
vprintf(fmt, args);
|
||||
printf("\n");
|
||||
|
||||
Reference in New Issue
Block a user