mirror of
https://github.com/0x221E/ibuild.git
synced 2026-01-18 02:42:20 +00:00
Refactor: Enhance error reporting for build system exception
This commit is contained in:
96
ibuild.c
96
ibuild.c
@@ -5,14 +5,37 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
void die(char* s)
|
#define CONFIG_FILE "IBUILD"
|
||||||
|
#define DIE(fmt, ...) die_t(__func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
// Developer-reporting error interface, along with steps to reproduce the error.
|
||||||
|
// Include this log in your issues
|
||||||
|
void die_t(const char* func, int line, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
printf("BuildSystem Error: %s\n", s);
|
va_list args;
|
||||||
// printf("Last syscall error: %s", ERRNO);
|
va_start(args, fmt);
|
||||||
|
printf("ibuild exception(f:%s-l:%d) ", func, line);
|
||||||
|
vprintf(fmt, args);
|
||||||
|
printf("\n");
|
||||||
|
printf("******Last syscall error: %s\n", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User-reporting error interface
|
||||||
|
// func_name(): ERRMSG
|
||||||
|
void log_error(const char* func, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
printf("%s: ", func);
|
||||||
|
vprintf(fmt, args);
|
||||||
|
printf("\n");
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char* compiler_path;
|
char* compiler_path;
|
||||||
@@ -20,30 +43,33 @@ typedef struct
|
|||||||
char* target_exec;
|
char* target_exec;
|
||||||
char* src_dir;
|
char* src_dir;
|
||||||
char* version;
|
char* version;
|
||||||
|
char** src_files;
|
||||||
} CompileOptions;
|
} CompileOptions;
|
||||||
|
|
||||||
void launch_compile(CompileOptions* co)
|
void launch_compile(CompileOptions* co)
|
||||||
{
|
{
|
||||||
if(co == NULL) die("launch_compile() co has to be valid");
|
if(co == NULL) DIE("launch_compile() co has to be valid");
|
||||||
|
|
||||||
if(co->compiler_path == NULL) die("launch_compile() requires a valid compiler path");
|
if(co->compiler_path == NULL) DIE("launch_compile() requires a valid compiler path");
|
||||||
|
|
||||||
pid_t p = fork();
|
pid_t p = fork();
|
||||||
|
|
||||||
if(p<0)
|
if(p<0)
|
||||||
die("launch_compile() fork error");
|
{
|
||||||
|
DIE("launch_compile() fork error");
|
||||||
|
}
|
||||||
else if (p==0)
|
else if (p==0)
|
||||||
{
|
{
|
||||||
char* args[] = {"compile", "test.c", "-o", "test", NULL};
|
char* args[] = {co->compiler_path, "ibuild.c", "-o", co->target_exec, NULL};
|
||||||
printf("SET COMPILER: %s\n", co->compiler_path);
|
printf("SET COMPILER: %s\n", co->compiler_path);
|
||||||
if((execvp(co->compiler_path, args)) == -1)
|
if((execvp(co->compiler_path, args)) == -1)
|
||||||
die("launch_compile() execvp error");
|
DIE("launch_compile() execvp error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool detect_config_file()
|
bool detect_config_file()
|
||||||
{
|
{
|
||||||
if(access("IBUILD", F_OK | R_OK) == 0)
|
if(access(CONFIG_FILE, F_OK | R_OK) == 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -96,7 +122,7 @@ bool is_part_of_key(char s)
|
|||||||
|
|
||||||
size_t skip_group(Tokenizer* t, bool (*func)(char))
|
size_t skip_group(Tokenizer* t, bool (*func)(char))
|
||||||
{
|
{
|
||||||
if(func == NULL) die("skip_group() func invalid!");
|
if(func == NULL) DIE("skip_group() func invalid!");
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
while(func(*t->src))
|
while(func(*t->src))
|
||||||
{
|
{
|
||||||
@@ -169,14 +195,16 @@ typedef enum
|
|||||||
K_UNKNOWN = 0,
|
K_UNKNOWN = 0,
|
||||||
K_COMPILER_PATH = 1,
|
K_COMPILER_PATH = 1,
|
||||||
K_SRC_DIR = 2,
|
K_SRC_DIR = 2,
|
||||||
K_BUILD_DIR = 3,
|
K_SRC_FILES = 3,
|
||||||
K_TARGET_EXEC = 4,
|
K_BUILD_DIR = 4,
|
||||||
|
K_TARGET_EXEC = 5,
|
||||||
} Key;
|
} Key;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
N_STRING = 0,
|
N_STRING = 0,
|
||||||
N_PAIR = 1
|
N_ARRAY = 1,
|
||||||
|
N_PAIR = 2,
|
||||||
} NodeType;
|
} NodeType;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -203,6 +231,7 @@ typedef struct
|
|||||||
static KeyMap keyword_mappings[] = {
|
static KeyMap keyword_mappings[] = {
|
||||||
{K_COMPILER_PATH, "COMPILER_PATH"},
|
{K_COMPILER_PATH, "COMPILER_PATH"},
|
||||||
{K_SRC_DIR, "SRC_DIR"},
|
{K_SRC_DIR, "SRC_DIR"},
|
||||||
|
{K_SRC_FILES, "SRC_FILES"},
|
||||||
{K_BUILD_DIR, "BUILD_DIR"},
|
{K_BUILD_DIR, "BUILD_DIR"},
|
||||||
{K_TARGET_EXEC, "TARGET_EXEC"},
|
{K_TARGET_EXEC, "TARGET_EXEC"},
|
||||||
{K_UNKNOWN, NULL},
|
{K_UNKNOWN, NULL},
|
||||||
@@ -235,7 +264,7 @@ Token parser_previous(Parser* p)
|
|||||||
{
|
{
|
||||||
if(p->loc - 1 < 0)
|
if(p->loc - 1 < 0)
|
||||||
{
|
{
|
||||||
die("parser logic error.");
|
DIE("parser logic error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((Token*)p->tokens_alloc->start)[p->loc - 1];
|
return ((Token*)p->tokens_alloc->start)[p->loc - 1];
|
||||||
@@ -253,11 +282,11 @@ Token parser_advance(Parser* p)
|
|||||||
|
|
||||||
Token parser_expect(Parser* p, TokenType tt, char* s)
|
Token parser_expect(Parser* p, TokenType tt, char* s)
|
||||||
{
|
{
|
||||||
if(p == NULL) die("parser_expect() p must not be NULL");
|
if(p == NULL) DIE("parser_expect() p must not be NULL");
|
||||||
if(p == NULL) die("parser_expect() s must not be NULL");
|
if(p == NULL) DIE("parser_expect() s must not be NULL");
|
||||||
|
|
||||||
if(parser_peek(p, 1).type != tt)
|
if(parser_peek(p, 1).type != tt)
|
||||||
die(s);
|
DIE(s);
|
||||||
|
|
||||||
return parser_advance(p);
|
return parser_advance(p);
|
||||||
}
|
}
|
||||||
@@ -275,7 +304,7 @@ Node* parser_expression(Parser* p)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
die("Syntax error: Invalid expression.");
|
DIE("Syntax error: Invalid expression.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* parser_statement(Parser* p)
|
Node* parser_statement(Parser* p)
|
||||||
@@ -284,7 +313,7 @@ Node* parser_statement(Parser* p)
|
|||||||
if(t.type == T_IDENTIFIER)
|
if(t.type == T_IDENTIFIER)
|
||||||
{
|
{
|
||||||
Key k = key_lookup(t.value);
|
Key k = key_lookup(t.value);
|
||||||
if(k == K_UNKNOWN) die("Syntax error: Unexpected identifer encountered");
|
if(k == K_UNKNOWN) DIE("Syntax error: Unexpected identifer encountered");
|
||||||
parser_expect(p, T_IS, "Syntax error: Expected '=' after identifier");
|
parser_expect(p, T_IS, "Syntax error: Expected '=' after identifier");
|
||||||
Node* expression = parser_expression(p);
|
Node* expression = parser_expression(p);
|
||||||
Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node));
|
Node* node = (Node*)arena_alloc(&p->alloc, sizeof(Node));
|
||||||
@@ -294,7 +323,7 @@ Node* parser_statement(Parser* p)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
die("Syntax error: expected an identifier");
|
DIE("Syntax error: expected an identifier");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,10 +371,10 @@ void debug_parser(Node* n, int indent)
|
|||||||
|
|
||||||
long get_file_size(FILE* fd)
|
long get_file_size(FILE* fd)
|
||||||
{
|
{
|
||||||
if(fd == NULL) die("get_file_size() fd cannot be NULL.");
|
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.");
|
if(fseek(fd, 0, SEEK_END) != 0) DIE("process_config() file exists, fseek SEEK_END fail.");
|
||||||
long size = ftell(fd);
|
long size = ftell(fd);
|
||||||
if(fseek(fd, 0, SEEK_SET) != 0) die("process_config() file exists, fseek SEEK_SET fail.");
|
if(fseek(fd, 0, SEEK_SET) != 0) DIE("process_config() file exists, fseek SEEK_SET fail.");
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +394,7 @@ int process_config(Node*** ast)
|
|||||||
|
|
||||||
FILE* fd = fopen("IBUILD", "r");
|
FILE* fd = fopen("IBUILD", "r");
|
||||||
|
|
||||||
if(fd == NULL) die("process_config() file exists however fd is NULL");
|
if(fd == NULL) DIE("process_config() file exists however fd is NULL");
|
||||||
|
|
||||||
long fs = get_file_size(fd);
|
long fs = get_file_size(fd);
|
||||||
|
|
||||||
@@ -386,7 +415,7 @@ int process_config(Node*** ast)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
Token token = tokenizer_next(&t);
|
Token token = tokenizer_next(&t);
|
||||||
if(token.type == T_INVALID) die("illegal token!");
|
if(token.type == T_INVALID) DIE("illegal token!");
|
||||||
|
|
||||||
Token* tm = arena_alloc(&cm.tokens, sizeof(Token));
|
Token* tm = arena_alloc(&cm.tokens, sizeof(Token));
|
||||||
*tm = token;
|
*tm = token;
|
||||||
@@ -400,7 +429,7 @@ int process_config(Node*** ast)
|
|||||||
Node** statements = NULL;
|
Node** statements = NULL;
|
||||||
size_t statements_len = parser_parse(&parser, &statements);
|
size_t statements_len = parser_parse(&parser, &statements);
|
||||||
|
|
||||||
if(statements == NULL) die("parser return invalid results");
|
if(statements == NULL) DIE("parser return invalid results");
|
||||||
|
|
||||||
for (size_t i = 0; i < statements_len; i++)
|
for (size_t i = 0; i < statements_len; i++)
|
||||||
debug_parser(statements[i], 0);
|
debug_parser(statements[i], 0);
|
||||||
@@ -421,7 +450,7 @@ void set_compiler_option(CompileOptions* co, Key k, char* val)
|
|||||||
case K_BUILD_DIR: co->build_dir = val; break;
|
case K_BUILD_DIR: co->build_dir = val; break;
|
||||||
case K_TARGET_EXEC: co->target_exec = val; break;
|
case K_TARGET_EXEC: co->target_exec = val; break;
|
||||||
default:
|
default:
|
||||||
die("Invalid compiler option was supplied!");
|
DIE("Invalid compiler option was supplied!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,10 +482,11 @@ void build(int len, Node** st)
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
printf("Build version: 0.0.1\n");
|
||||||
Node** ast = NULL;
|
Node** ast = NULL;
|
||||||
int len_ast = process_config(&ast);
|
int len_ast = process_config(&ast);
|
||||||
|
|
||||||
build(len_ast, ast);
|
build(len_ast, ast);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user