diff --git a/include/tlibc/collections/List.h b/include/tlibc/collections/List.h index 48e621f..8173cb4 100755 --- a/include/tlibc/collections/List.h +++ b/include/tlibc/collections/List.h @@ -7,14 +7,14 @@ typedef struct List { u32 allocated_size; } List; -#define List_construct(L, T, OCCUPIED_COUNT, ALLOCATED_COUNT) \ - List_construct_size(L, (OCCUPIED_COUNT) * sizeof(T), (ALLOCATED_COUNT) * sizeof(T)) +#define List_construct(DATA_PTR, T, OCCUPIED_COUNT, ALLOCATED_COUNT) \ + List_construct_size(DATA_PTR, (OCCUPIED_COUNT) * sizeof(T), (ALLOCATED_COUNT) * sizeof(T)) -static inline List List_construct_size(void* data_ptr, u32 size, u32 allocated_size) { - return (List){ .data = data_ptr, .size = size, .allocated_size = allocated_size }; +static inline List List_construct_size(void* data_ptr, u32 occupied_size, u32 allocated_size) { + return (List){ .data = data_ptr, .size = occupied_size, .allocated_size = allocated_size }; } -#define List_alloc(L, T, INITIAL_COUNT) List_alloc_size(L, (INITIAL_COUNT) * sizeof(T)) +#define List_alloc(T, INITIAL_COUNT) List_alloc_size((INITIAL_COUNT) * sizeof(T)) List List_alloc_size(u32 initial_size); void* List_expand(List* ptr, u32 expansion_size); diff --git a/include/tlibc/errors.h b/include/tlibc/errors.h index 9dc67e8..0c4918c 100755 --- a/include/tlibc/errors.h +++ b/include/tlibc/errors.h @@ -1,9 +1,34 @@ #pragma once #include "std.h" -#include "string/cstr.h" +#include "string/str.h" +#include "collections/List.h" + +typedef struct ErrorCallPos { + i32 line; + str file; + str func; +} ErrorCallPos; +#define ErrorCallPos_here() (ErrorCallPos){\ + .line = __LINE__,\ + .file = str_construct((char*)(void*)__FILE__, sizeof(__FILE__), true),\ + .func = str_construct((char*)(void*)__func__, sizeof(__func__), true)\ +} + +typedef struct Error { + str msg; + bool is_msg_on_heap; + /* List */ + List call_stack; +} Error; + +Error* Error_create(const char* msg, bool is_msg_on_heap, ErrorCallPos); +void Error_destroy(Error* e); +void Error_addCallPos(Error* e, ErrorCallPos p); +str Error_toStr(Error* e); +void Error_printAndExit(Error* e) __attribute__ ((__noreturn__)); typedef struct Result_ { - cstr error; + Error* error; union { u64 v_u64; i64 v_i64; @@ -15,12 +40,22 @@ typedef struct Result_ { #define Result(T) Result_ -char* _genErrorMessage(cstr file, i32 line, cstr func, char* msg, bool free_msg); - -#define _genErrorMessageHere(MSG, FREE_MSG) \ - _genErrorMessage(__FILE__, __LINE__, __func__, MSG, FREE_MSG) - -#define RESULT_ERROR(MSG, FREE_MSG) (Result_){ .error = _genErrorMessageHere(MSG, FREE_MSG) } +#define RESULT_ERROR(MSG, IS_MSG_ON_HEAP) (Result_){ .error = Error_create(MSG, IS_MSG_ON_HEAP, ErrorCallPos_here()) } #define RESULT_VOID (Result_){ .error = NULL } #define RESULT_VALUE(TYPE, V) (Result_){ .error = NULL, .v_##TYPE = V } + +#define try(VAR, RSLT_CALL, DEFER_CODE) \ + Result_ VAR = RSLT_CALL;\ + if(VAR.error){\ + Error_addCallPos(VAR.error, ErrorCallPos_here());\ + DEFER_CODE;\ + return VAR;\ + }; + +#define try_fatal(VAR, RSLT_CALL, DEFER_CODE) \ + Result_ VAR = RSLT_CALL;\ + if(VAR.error){\ + DEFER_CODE;\ + Error_printAndExit(VAR.error);\ + }; diff --git a/src/errors.c b/src/errors.c index 846b57c..7611471 100755 --- a/src/errors.c +++ b/src/errors.c @@ -1,10 +1,53 @@ #include "tlibc/errors.h" +#include "tlibc/string/StringBuilder.h" #define ERRMSG_LENGTH 1024 -char* _genErrorMessage(cstr file, i32 line, cstr func, char* msg, bool free_msg){ - char* result = sprintf_malloc(1024, "[%s:%i] %s() throwed error: %s", file, line, func, msg); - if(free_msg) - free(msg); - return result; +Error* Error_create(const char* msg, bool is_msg_on_heap, ErrorCallPos){ + Error* e = (Error*)malloc(sizeof(Error)); + e->msg = str_construct((char*)(void*)msg, strlen(msg), true); + e->is_msg_on_heap = is_msg_on_heap; + e->call_stack = List_alloc(ErrorCallPos, 1); + return e; +} + +void Error_destroy(Error* e){ + if(e->is_msg_on_heap) + free(e->msg.data); + free(e->call_stack.data); +} + +void Error_addCallPos(Error* e, ErrorCallPos p){ + List_push(&e->call_stack, ErrorCallPos, p); +} + +str Error_toStr(Error* e){ + u32 len = List_len(&e->call_stack, ErrorCallPos); + StringBuilder b = StringBuilder_alloc(e->msg.size + 80 * len); + + StringBuilder_append_str(&b, STR("Error: ")); + StringBuilder_append_str(&b, e->msg); + for(u32 i = 0; i < len; i++){ + ErrorCallPos* ep = (ErrorCallPos*)e->call_stack.data + i; + StringBuilder_append_str(&b, STR("\n at ")); + StringBuilder_append_str(&b, ep->file); + StringBuilder_append_char(&b, ':'); + StringBuilder_append_i64(&b, ep->line); + StringBuilder_append_char(&b, ' '); + StringBuilder_append_str(&b, ep->func); + StringBuilder_append_str(&b, STR("()\n")); + } + + return StringBuilder_getStr(&b); +} + + +void Error_printAndExit(Error* e){ + Error_addCallPos(e, ErrorCallPos_here());\ + str e_str = Error_toStr(e); + printfe("%s\n", e_str.data); + free(e_str.data); + Error_destroy(e); + free(e); + exit(111); }