From 0845c56c2b54f3efb63a39af13e663cc29eced87 Mon Sep 17 00:00:00 2001 From: 0x221E Date: Fri, 9 Jan 2026 21:29:18 +0100 Subject: [PATCH] Initial Commit - Not functional --- .gitignore | 1 + .gitmodules | 3 + deps/utils | 1 + ibuild.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 394 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 160000 deps/utils create mode 100644 ibuild.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..727435f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +ibuild\ntest\ntest.c diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..917e069 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/utils"] + path = deps/utils + url = git@github.com:0x221E/utils.git diff --git a/deps/utils b/deps/utils new file mode 160000 index 0000000..e5cf1a2 --- /dev/null +++ b/deps/utils @@ -0,0 +1 @@ +Subproject commit e5cf1a23b3f11fa68006ea2e19b950715dcacea1 diff --git a/ibuild.c b/ibuild.c new file mode 100644 index 0000000..9c699ec --- /dev/null +++ b/ibuild.c @@ -0,0 +1,389 @@ +#include "deps/utils/src/arena_alloc.h" + +#include +#include +#include +#include +#include + +void die(char* s) +{ + printf("BuildSystem Error: %s\n", s); + // printf("Last syscall error: %s", ERRNO); + exit(1); +} + +typedef struct +{ + char* compiler_path; + char* build_dir; + char* target_exec; + char* src_dir; + char* version; +} CompileOptions; + +void launch_compile(CompileOptions* co) +{ + if(co == NULL) die("launch_compile() co has to be valid"); + + if(co->compiler_path == NULL) die("launch_compile() requires a valid compiler path"); + + pid_t p = fork(); + + if(p<0) + die("launch_compile() fork error"); + else if (p==0) + { + char* args[] = {"compile", "test.c", "-o", "test", NULL}; + if((execvp(co->compiler_path, args)) == -1) + die("launch_compile() execvp error"); + } + } + +bool detect_config_file() +{ + if(access("IBUILD", F_OK | R_OK) == 0) + return true; + return false; +} + +/*** configuration lexer ***/ + +typedef struct +{ + char *src; + Arena alloc; +} Tokenizer; + +typedef enum +{ + T_INVALID = -1, + T_IDENTIFIER = 0, + T_STRING = 1, + T_IS = 2, + T_EOF = 3, +} TokenType; + +typedef struct +{ + TokenType type; + char* value; + int line; +} Token; + +#define TOKEN_CONST {T_INVALID, NULL, 0} + +bool is_alpha_uppercase(char s) +{ + return (s >= 'A' && s <= 'Z'); +} + +bool is_alpha_lowercase(char s) +{ + return (s >= 'a' && s <= 'z'); +} + +bool is_whitespace(char s) +{ + return s == ' ' || s == '\t' || s == '\r' || s == '\n'; +} + +bool is_part_of_key(char s) +{ + return is_alpha_uppercase(s) || s == '_'; +} + +size_t skip_group(Tokenizer* t, bool (*func)(char)) +{ + if(func == NULL) die("skip_group() func invalid!"); + size_t len = 0; + while(func(*t->src)) + { + len++; + t->src += 1; + } + + return len; +} + +Token tokenize_identifier(Tokenizer *t) +{ + char* temp = t->src; + size_t len = skip_group(t, &is_part_of_key); + char* buf = (char*)arena_alloc(&t->alloc, sizeof(char) * len + 1); + memcpy(buf, temp, len); + buf[len] = '\0'; + return (Token){T_IDENTIFIER, buf}; +} + +Token tokenize_string(Tokenizer *t) +{ + t->src += 1; + char* temp = t->src; + size_t len = 0; + + while(*t->src != '"' && *t->src != '\0') + { + len++; + t->src += 1; + } + + if(*t->src == '"') t->src++; + + char* buf = (char*)arena_alloc(&t->alloc, (sizeof(char) * len) + 1); + memcpy(buf, temp, len); + buf[len] = '\0'; + return (Token){T_STRING, buf}; +} + +Token tokenizer_next(Tokenizer* t) +{ + if(is_whitespace(*t->src)) skip_group(t, &is_whitespace); + + if(is_alpha_uppercase(*t->src)) + { + return tokenize_identifier(t); + } + + switch(*t->src) + { + case '"': + return tokenize_string(t); + case '=': + t->src++; + return (Token){T_IS, NULL}; + } + + if(*t->src == '\0') return (Token){T_EOF, NULL}; + + t->src++; + return (Token){T_INVALID, NULL}; +} + +/*** configuration parser ***/ + +typedef enum +{ + K_UNKNOWN = 0, + K_COMPILER_PATH = 1, + K_SRC_DIR = 2, + K_BUILD_DIR = 3, +} Key; + +typedef enum +{ + N_STRING = 0, + N_PAIR = 1 +} NodeType; + +typedef struct +{ + NodeType type; + Key key; + void* value; +} Node; + +typedef struct +{ + Tokenizer* tokenizer; + size_t loc; + size_t cap; + Arena alloc; +} Parser; + +typedef struct +{ + Key key; + const char* value; +} KeyMap; + +static KeyMap keyword_mappings[] = { + {K_COMPILER_PATH, "COMPILER_PATH"}, + {K_SRC_DIR, "SRC_DIR"}, + {K_BUILD_DIR, "BUILD_DIR"}, + {K_UNKNOWN, NULL}, +}; + +Key key_lookup(char* s) +{ + if(s == NULL) return K_UNKNOWN; + + for(const KeyMap* ptr = keyword_mappings; ptr->value != NULL; ptr++) + { + if(strcmp(ptr->value, s) == 0) + { + return ptr->key; + } + } + return K_UNKNOWN; +} + +Token parser_peek(Parser* p, size_t o) +{ + if (p->loc + o >= p->cap) + { + return ((Token*)p->tokenizer->alloc.start)[p->loc - 1]; + } + return ((Token*)p->tokenizer->alloc.start)[p->loc + o]; +} + +Token parser_previous(Parser* p) +{ + if(p->loc - 1 < 0) + { + die("parser logic error."); + } + + return ((Token*)p->tokenizer->alloc.start)[p->loc - 1]; +} + +Token parser_advance(Parser* p) +{ + if(p->loc + 1 >= p->cap) + { + return ((Token*)p->tokenizer->alloc.start)[p->loc]; + } + p->loc++; + return ((Token*)p->tokenizer->alloc.start)[p->loc]; +} + +Node* parser_expression(Parser* p) +{ + Token t = parser_peek(p,0); + if(t.type == T_STRING) + { + Key k = key_lookup(t.value); + if(k == K_UNKNOWN) die("Syntax error: Unexpected expression encountered"); + Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node)); + node->key = k; + node->value = (void*)t.value; + node->type = N_STRING; + return node; + } + + die("Syntax error: Invalid expression."); +} + +Node* parser_statement(Parser* p) +{ + Token t = parser_advance(p); + if(t.type == T_IDENTIFIER) + { + Key k = key_lookup(t.value); + if(k == K_UNKNOWN) die("Syntax error: Unexpected identifer encountered"); + Node* expression = parser_expression(p); + Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node)); + node->key = k; + node->value = (void*)expression; + node->type = N_PAIR; + } + else + { + printf("%d", t.type); + die("Syntax error: expected an identifier"); + } +} + +Node* parser_parse(Parser* p) +{ + return parser_statement(p); +} + +/*** configuration file management ***/ + +long get_file_size(FILE* fd) +{ + if(fd == NULL) die("get_file_size() fd cannot be NULL."); + if(fseek(fd, 0, SEEK_END) != 0) die("process_config() file exists, fseek SEEK_END fail."); + long size = ftell(fd); + if(fseek(fd, 0, SEEK_SET) != 0) die("process_config() file exists, fseek SEEK_SET fail."); + return size; +} + +int process_config(Arena* tokens) +{ + if(!detect_config_file()) + return 1; + + printf("IBUILD Configuration file detected.\n"); + + FILE* fd = fopen("IBUILD", "r"); + + if(fd == NULL) die("process_config() file exists however fd is NULL"); + + long fs = get_file_size(fd); + + printf("IBUILD file of size: %d\n", fs); + + char* config_mem = malloc(fs + 1); + + fread(config_mem, sizeof(char), fs, fd); + config_mem[fs] = '\0'; + + printf("Config file:\n%s\n", config_mem); + + size_t t_count = 0; + + Tokenizer t = { .src = config_mem, .alloc = ARENA_CONST}; + while(1) + { + Token token = tokenizer_next(&t); + if(token.type == T_INVALID) die("illegal token!"); + + Token* tm = arena_alloc(tokens, sizeof(Token)); + *tm = token; + + t_count++; + if(token.type == T_EOF) break; + } + + Parser parser = {.tokenizer = &t, .loc = 0, .cap = t_count, .alloc = ARENA_CONST}; + parser_parse(&parser); + + free(config_mem); + return 0; +} + +/*** build configuration process ***/ +/* +void populate_compile_options(CompileOptions* co, Token* t) +{ + switch(t->type) + { + case T_KEY_COMPILER_PATH: co->compiler_path = t->value; break; + case T_KEY_BUILD_DIR: co->build_dir = t->value; break; + case T_KEY_TARGET_EXEC: co->target_exec = t->value; break; + case T_KEY_SRC_DIR: co->compiler_path = t->value; break; + case T_KEY_VERSION: co->version = t->value; break; + } + }*/ + +void build(Token* options) +{ + CompileOptions co; + co.compiler_path = "/usr/bin/gcc"; + + Token* temp = options; + for(; temp->type != T_EOF; temp++) + { + // populate_compile_options(&co, temp); + } + + launch_compile(&co); + printf("Compilation finished.\n"); +} + +int main(int argc, char** argv) +{ + Arena a = ARENA_CONST; + + process_config(&a); + + Token* ptr = (Token*)a.start; + for(; ptr->type != T_EOF; ptr++) + { + printf("TokenType: %d, Value: %s\n", ptr->type, ptr->value); + } + + return 0; +}