| @@ -1,5 +1,7 @@ | |||
| @echo off | |||
| mkdir bin | |||
| set EXE_RAW=test | |||
| set BINDIR_RAW=bin | |||
| set SRC=test.cpp | |||
| @@ -11,12 +13,12 @@ set BINDIR_LINUX=./%BINDIR_RAW% | |||
| echo. | |||
| echo clang: | |||
| clang %SRC% -o %BINDIR_WIN%\clang_%EXE_WIN% | |||
| clang -std=c++17 %SRC% -o %BINDIR_WIN%\clang_%EXE_WIN% | |||
| %BINDIR_WIN%\clang_%EXE_WIN% | |||
| echo. | |||
| echo g++: | |||
| g++ %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN% | |||
| g++ -std=c++17 %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN% | |||
| %BINDIR_WIN%\g++_%EXE_WIN% | |||
| echo. | |||
| @@ -26,8 +28,8 @@ cl %SRC% /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: | |||
| echo. | |||
| echo bash_clang: | |||
| bash -c "clang -std=c++11 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%" | |||
| bash -c "clang -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%" | |||
| echo. | |||
| echo bash_g++: | |||
| bash -c "g++ -std=c++11 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%" | |||
| bash -c "g++ -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%" | |||
| @@ -0,0 +1,104 @@ | |||
| #pragma once | |||
| #include "stdio.h" | |||
| #include "math.h" | |||
| #include "stdarg.h" | |||
| #include "stdlib.h" | |||
| #include "types.hpp" | |||
| #include "print.hpp" | |||
| struct Error { | |||
| String type; | |||
| String message; | |||
| }; | |||
| Error* error = nullptr; | |||
| auto delete_error() -> void { | |||
| free(error); | |||
| error = nullptr; | |||
| } | |||
| auto create_error(const char* c_func_name, const char* c_file_name, | |||
| u32 c_file_line, String type, const char* format, ...) -> void { | |||
| error = new Error; | |||
| error->type = type; | |||
| va_list args; | |||
| va_start(args, format); | |||
| error->message.length = print_va_args_to_string(&(error->message.data), format, &args); | |||
| va_end(args); | |||
| print("\n%{color<}%{->Str} error:%{>color} %{->Str}\n", | |||
| console_red, &(error->type), &(error->message)); | |||
| printf("in"); | |||
| s32 spacing = 30-((s32)strlen(c_file_name) + (s32)log10(c_file_line)); | |||
| if (spacing < 1) spacing = 1; | |||
| for (s32 i = 0; i < spacing; ++i) | |||
| printf(" "); | |||
| printf("%s (%u) ", c_file_name, c_file_line); | |||
| printf("-> %s\n", c_func_name); | |||
| } | |||
| #define __create_error(keyword, ...) \ | |||
| create_error( \ | |||
| __FUNCTION__, __FILE__, __LINE__, \ | |||
| make_heap_string(keyword), \ | |||
| __VA_ARGS__) | |||
| #define create_assertion_error(...) \ | |||
| __create_error("assert", __VA_ARGS__) | |||
| #define create_generic_error(...) \ | |||
| __create_error("generic", __VA_ARGS__) | |||
| #define assert(condition, format, ...) \ | |||
| do { \ | |||
| if (!(condition)) { \ | |||
| char* msg; \ | |||
| print_to_string(&msg, format, __VA_ARGS__); \ | |||
| create_assertion_error("Assertion-error: %s\n" \ | |||
| " condition: %s\n" \ | |||
| " in: %s:%d", \ | |||
| msg, #condition, \ | |||
| __FILE__, __LINE__ ); \ | |||
| } \ | |||
| } while(0) | |||
| #define log_location() \ | |||
| do { \ | |||
| printf("in"); \ | |||
| s32 spacing = 30-((s32)strlen(__FILE__) + (s32)log10(__LINE__)); \ | |||
| if (spacing < 1) spacing = 1; \ | |||
| for (s32 i = 0; i < spacing;++i) \ | |||
| printf(" "); \ | |||
| printf("%s (%d) ", __FILE__, __LINE__); \ | |||
| printf("-> %s\n", __FUNCTION__); \ | |||
| } while(0) | |||
| #define if_error_log_location_and_return(val) \ | |||
| do { \ | |||
| if (error) { \ | |||
| log_location(); \ | |||
| return val; \ | |||
| } \ | |||
| } while(0) | |||
| #define try_or_else_return(val) \ | |||
| if (1) \ | |||
| goto label(body,__LINE__); \ | |||
| else \ | |||
| while (1) \ | |||
| if (1) { \ | |||
| if (error) { \ | |||
| log_location(); \ | |||
| return val; \ | |||
| } \ | |||
| break; \ | |||
| } \ | |||
| else label(body,__LINE__): | |||
| #define check_error_struct try_or_else_return({}) | |||
| #define check_error_void try_or_else_return(;) | |||
| #define check_error try_or_else_return(0) | |||
| @@ -1,8 +1,8 @@ | |||
| #pragma once | |||
| #define proc auto | |||
| #define TOKENPASTE(x, y) x ## y | |||
| #define TOKENPASTE2(x, y) TOKENPASTE(x, y) | |||
| #define concat(x, y) x ## y | |||
| #define label(x, y) concat(x, y) | |||
| /** | |||
| @@ -34,7 +34,7 @@ static struct { | |||
| } | |||
| } deferrer; | |||
| #define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&] | |||
| #define defer auto label(__deferred_lambda_call, __COUNTER__) = deferrer << [&] | |||
| #define defer_free(var) defer { free(var); } | |||
| @@ -57,13 +57,13 @@ expands to: | |||
| #define fluid_let(var, val) \ | |||
| if (0) \ | |||
| TOKENPASTE2(finished,__LINE__): ; \ | |||
| label(finished,__LINE__): ; \ | |||
| else \ | |||
| for (auto TOKENPASTE2(fluid_let_, __LINE__) = var;;) \ | |||
| for (defer{var = TOKENPASTE2(fluid_let_, __LINE__);};;) \ | |||
| for (auto label(fluid_let_, __LINE__) = var;;) \ | |||
| for (defer{var = label(fluid_let_, __LINE__);};;) \ | |||
| for(var = val;;) \ | |||
| if (1) { \ | |||
| goto TOKENPASTE2(body,__LINE__); \ | |||
| goto label(body,__LINE__); \ | |||
| } \ | |||
| else \ | |||
| while (1) \ | |||
| @@ -11,6 +11,11 @@ | |||
| #define str_eq(s1, s2) (strcmp(s1, s2) == 0) | |||
| #define console_normal "\x1B[0m" | |||
| #define console_red "\x1B[31m" | |||
| #define console_green "\x1B[32m" | |||
| #define console_cyan "\x1B[36m" | |||
| typedef const char* static_string; | |||
| typedef int (*printer_function_32b)(FILE*, u32); | |||
| typedef int (*printer_function_64b)(FILE*, u64); | |||
| @@ -27,13 +32,14 @@ enum struct Printer_Function_Type { | |||
| _void | |||
| }; | |||
| Hash_Map<char*, printer_function_32b> printer_map = {0}; | |||
| Array_List<char*> color_stack = {0}; | |||
| Hash_Map<char*, printer_function_ptr> printer_map = {0}; | |||
| Hash_Map<char*, int> type_map = {0}; | |||
| #define register_printer(spec, fun, type) \ | |||
| register_printer_32(spec, (printer_function_32b)fun, type) | |||
| #define register_printer(spec, fun, type) \ | |||
| register_printer_ptr(spec, (printer_function_ptr)fun, type) | |||
| void register_printer_32(const char* spec, printer_function_32b fun, Printer_Function_Type type) { | |||
| void register_printer_ptr(const char* spec, printer_function_ptr fun, Printer_Function_Type type) { | |||
| printer_map.set_object((char*)spec, fun); | |||
| type_map.set_object((char*)spec, (int)type); | |||
| } | |||
| @@ -69,14 +75,15 @@ int maybe_special_print(FILE* file, static_string format, int* pos, va_list* arg | |||
| } printer; | |||
| // just grab it, it will have the correct type | |||
| printer.printer_32b = printer_map.get_object(spec, spec_hash); | |||
| free(spec); | |||
| printer.printer_ptr = printer_map.get_object(spec, spec_hash); | |||
| if (type == Printer_Function_Type::unknown) { | |||
| printf("ERROR: %s printer not found\n", spec); | |||
| free(spec); | |||
| return 0; | |||
| } | |||
| free(spec); | |||
| if (format[end_pos] == ',') { | |||
| int element_count; | |||
| @@ -399,28 +406,63 @@ int print_str(FILE* f, char* str) { | |||
| return print_to_file(f, "%s", str); | |||
| } | |||
| int print_color_start(FILE* f, char* str) { | |||
| color_stack.append(str); | |||
| return print_to_file(f, "%s", str); | |||
| } | |||
| int print_color_end(FILE* f) { | |||
| --color_stack.next_index; | |||
| if (color_stack.next_index == 0) { | |||
| return print_to_file(f, "%s", console_normal); | |||
| } else { | |||
| return print_to_file(f, "%s", color_stack[color_stack.next_index-1]); | |||
| } | |||
| } | |||
| int print_ptr(FILE* f, void* ptr) { | |||
| if (ptr) | |||
| return print_to_file(f, "%#0*X", sizeof(void*)*2+2, ptr); | |||
| return print_to_file(f, "nullptr"); | |||
| } | |||
| auto print_Str(FILE* f, String* str) -> s32 { | |||
| return print_to_file(f, "%.*s", str->length, str->data); | |||
| } | |||
| auto print_str_line(FILE* f, char* str) -> s32 { | |||
| u32 length = 0; | |||
| char* str_cpy = str; | |||
| while (str[length] != '\0') { | |||
| if (str[length] == '\n') | |||
| break; | |||
| length++; | |||
| } | |||
| return print_to_file(f, "%.*s", length, str); | |||
| } | |||
| void deinit_printer() { | |||
| printer_map.dealloc(); | |||
| type_map.dealloc(); | |||
| } | |||
| void init_printer() { | |||
| color_stack.alloc(); | |||
| printer_map.alloc(); | |||
| type_map.alloc(); | |||
| register_printer("u32", print_u32, Printer_Function_Type::_32b); | |||
| register_printer("u64", print_u64, Printer_Function_Type::_64b); | |||
| register_printer("bool", print_bool, Printer_Function_Type::_32b); | |||
| register_printer("s64", print_s64, Printer_Function_Type::_64b); | |||
| register_printer("s32", print_s32, Printer_Function_Type::_32b); | |||
| register_printer("f32", print_flt, Printer_Function_Type::_flt); | |||
| register_printer("f64", print_flt, Printer_Function_Type::_flt); | |||
| register_printer("str", print_str, Printer_Function_Type::_ptr); | |||
| register_printer("ptr", print_ptr, Printer_Function_Type::_ptr); | |||
| register_printer("u32", print_u32, Printer_Function_Type::_32b); | |||
| register_printer("u64", print_u64, Printer_Function_Type::_64b); | |||
| register_printer("bool", print_bool, Printer_Function_Type::_32b); | |||
| register_printer("s64", print_s64, Printer_Function_Type::_64b); | |||
| register_printer("s32", print_s32, Printer_Function_Type::_32b); | |||
| register_printer("f32", print_flt, Printer_Function_Type::_flt); | |||
| register_printer("f64", print_flt, Printer_Function_Type::_flt); | |||
| register_printer("->char", print_str, Printer_Function_Type::_ptr); | |||
| register_printer("->", print_ptr, Printer_Function_Type::_ptr); | |||
| register_printer("color<", print_color_start, Printer_Function_Type::_ptr); | |||
| register_printer(">color", print_color_end, Printer_Function_Type::_void); | |||
| register_printer("->Str", print_Str, Printer_Function_Type::_ptr); | |||
| register_printer("->char_line", print_str_line, Printer_Function_Type::_ptr); | |||
| } | |||
| @@ -6,6 +6,7 @@ | |||
| #include "./hooks.hpp" | |||
| #include "./error.hpp" | |||
| #include "./print.hpp" | |||
| @@ -13,25 +14,25 @@ int print_dots(FILE* f) { | |||
| return print_to_file(f, "..."); | |||
| } | |||
| s32 main(s32 argc, char* argv[]) { | |||
| u32 arr[] = {1,2,3,4,1,1,3}; | |||
| f32 f_arr[] = {1.1,2.1,3.2}; | |||
| void test_printer() { | |||
| // u32 arr[] = {1,2,3,4,1,1,3}; | |||
| // f32 f_arr[] = {1.1,2.1,3.2}; | |||
| init_printer(); | |||
| register_printer("dots", print_dots, Printer_Function_Type::_void); | |||
| // init_printer(); | |||
| // register_printer("dots", print_dots, Printer_Function_Type::_void); | |||
| u32 u1 = -1; | |||
| u64 u2 = -1; | |||
| // u32 u1 = -1; | |||
| // u64 u2 = -1; | |||
| char* str; | |||
| print_to_string(&str, " - %{dots[5]} %{ptr} <> %{ptr,2}\n", &u1, &arr, nullptr); | |||
| print("---> %{str}", str); | |||
| // char* str; | |||
| // print_to_string(&str, " - %{dots[5]} %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||
| // print("---> %{->char}", str); | |||
| // print(" - %{dots[3]}\n"); | |||
| // print(" - %{u32} %{u64}\n", u1, u2); | |||
| // print(" - %{u32} %{u32} %{u32}\n", 2, 5, 7); | |||
| // print(" - %{f32} %{f32} %{f32}\n", 2.0, 5.0, 7.0); | |||
| // print(" - %{u32} %{bool} %{str}\n", 2, true, "hello"); | |||
| // print(" - %{u32} %{bool} %{->char}\n", 2, true, "hello"); | |||
| // print(" - %{f32[3]}\n", f_arr); | |||
| // print(" - %{f32,3}\n", 44.9, 55.1, 66.2); | |||
| // print(" - %{u32[5]}\n", arr); | |||
| @@ -39,8 +40,33 @@ s32 main(s32 argc, char* argv[]) { | |||
| // print(" - %{u32,5}\n", 1,2,3,4,1,2); | |||
| // print(" - %{unknown%d}\n", 1); | |||
| // print(" - %{s32,3}\n", -1,200,-300); | |||
| // print(" - %{ptr} <> %{ptr,2}\n", &u1, &arr, nullptr); | |||
| // print(" - %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||
| } | |||
| s32 main(s32 argc, char* argv[]) { | |||
| // test_printer(); | |||
| init_printer(); | |||
| // create_generic_error("nothing to lex was found:\n" | |||
| // " in %{color<}%{->char}%{>color}\n" | |||
| // " at %{color<}%{->char}%{>color}\n" | |||
| // "bottom text\n", | |||
| // console_green, | |||
| // "some file name", | |||
| // console_cyan, | |||
| // "yesssssss"); | |||
| create_error(__FUNCTION__, __FILE__, __LINE__, | |||
| make_heap_string("generic"), | |||
| "nothing to lex was found:\n" | |||
| " in %{color<}%{->char}%{>color}\n" | |||
| " at %{color<}%{->char}%{>color}\n" | |||
| "bottom text\n", | |||
| console_green, | |||
| "some file name", | |||
| console_cyan, | |||
| "yesssssss"); | |||
| return 0; | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| #pragma once | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| typedef int8_t s8; | |||
| typedef int16_t s16; | |||
| @@ -20,3 +21,15 @@ typedef wchar_t path_char; | |||
| #else | |||
| typedef char path_char; | |||
| #endif | |||
| struct String { | |||
| u32 length; | |||
| char* data; | |||
| }; | |||
| inline String make_heap_string(const char* str) { | |||
| String ret; | |||
| ret.length = strlen(str); | |||
| ret.data = _strdup(str); | |||
| return ret; | |||
| } | |||