From fcc64d84a2cabdf3ce6fed49f0326b8e626e500a Mon Sep 17 00:00:00 2001 From: FelixBrendel Date: Tue, 19 May 2020 09:35:36 +0200 Subject: [PATCH] added print --- build.bat | 50 ++++--- hashmap.hpp | 32 ++++- print.hpp | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test.cpp | 53 ++++--- 4 files changed, 491 insertions(+), 42 deletions(-) create mode 100644 print.hpp diff --git a/build.bat b/build.bat index 099d8a2..8775660 100644 --- a/build.bat +++ b/build.bat @@ -1,29 +1,33 @@ @echo off -pushd %~dp0 -set exeName=main.exe -set binDir=bin +set EXE_RAW=test +set BINDIR_RAW=bin +set SRC=test.cpp -mkdir %bindir% -pushd %bindir% +set EXE_WIN=%EXE_RAW%.exe +set EXE_LINUX=%EXE_RAW% +set BINDIR_WIN=.\%BINDIR_RAW% +set BINDIR_LINUX=./%BINDIR_RAW% -cl^ - ../test.cpp^ - /Fe%exeName% /MP /openmp /W3 /std:c++latest^ - /nologo /EHsc /Z7^ - /link /incremental +echo. +echo clang: +clang %SRC% -o %BINDIR_WIN%\clang_%EXE_WIN% +%BINDIR_WIN%\clang_%EXE_WIN% -if %errorlevel% == 0 ( - echo. - if not exist ..\%binDir% mkdir ..\%binDir% - move %exeName% ..\%binDir%\ > NUL - echo ---------- Output start ---------- - %exeName% - echo ---------- Output end ---------- - popd -) else ( - echo. - echo Fucki'n 'ell -) +echo. +echo g++: +g++ %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN% +%BINDIR_WIN%\g++_%EXE_WIN% -popd +echo. +echo cl: +cl %SRC% /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: %BINDIR_WIN%\cl_%EXE_WIN% /wd4090 +%BINDIR_WIN%\cl_%EXE_WIN% + +echo. +echo bash_clang: +bash -c "clang -std=c++11 %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%" diff --git a/hashmap.hpp b/hashmap.hpp index 3a33872..7c43f8e 100644 --- a/hashmap.hpp +++ b/hashmap.hpp @@ -6,6 +6,29 @@ #include "types.hpp" #include "arraylist.hpp" + +u32 hm_hash(char* str) { + u32 value = str[0] << 7; + s32 i = 0; + while (str[i]) { + value = (10000003 * value) ^ str[i++]; + } + return value ^ i; +} + +u32 hm_hash(void* ptr) { + return ((u64)ptr * 2654435761) % 4294967296; +} + +inline bool hm_objects_match(char* a, char* b) { + return strcmp(a, b) == 0; +} + +inline bool hm_objects_match(void* a, void* b) { + return a == b; +} + + #define for_hash_map(hm) \ if (decltype((hm).data[0].original) key = 0); else \ if (decltype((hm).data[0].object) value = 0); else \ @@ -103,14 +126,19 @@ struct Hash_Map { return ret; } - value_type get_object(key_type key) { - s32 index = get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key)); + value_type get_object(key_type key, u64 hash_val) { + s32 index = get_index_of_living_cell_if_it_exists(key, hash_val); if (index != -1) { return data[index].object; } return 0; } + value_type get_object(key_type key) { + return get_object(key, hm_hash((key_type)key)); + } + + void delete_object(key_type key) { s32 index = get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key)); if (index != -1) { diff --git a/print.hpp b/print.hpp new file mode 100644 index 0000000..d22bcb6 --- /dev/null +++ b/print.hpp @@ -0,0 +1,398 @@ +#pragma once +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +#include "hashmap.hpp" + +#define str_eq(s1, s2) (strcmp(s1, s2) == 0) + +typedef const char* static_string; +typedef int (*printer_function_32b)(FILE*, u32); +typedef int (*printer_function_64b)(FILE*, u64); +typedef int (*printer_function_flt)(FILE*, double); +typedef int (*printer_function_ptr)(FILE*, void*); +typedef int (*printer_function_void)(FILE*); + +enum struct Printer_Function_Type { + unknown, + _32b, + _64b, + _flt, + _ptr, + _void +}; + +Hash_Map printer_map = {0}; +Hash_Map type_map = {0}; + +#define register_printer(spec, fun, type) \ + register_printer_32(spec, (printer_function_32b)fun, type) + +void register_printer_32(const char* spec, printer_function_32b fun, Printer_Function_Type type) { + printer_map.set_object((char*)spec, fun); + type_map.set_object((char*)spec, (int)type); +} + +int maybe_special_print(FILE* file, static_string format, int* pos, va_list* arg_list) { + if(format[*pos] != '{') + return 0; + + int end_pos = (*pos)+1; + while (format[end_pos] != '}' && + format[end_pos] != ',' && + format[end_pos] != '[' && + format[end_pos] != 0) + ++end_pos; + + if (format[end_pos] == 0) + return 0; + + char* spec = (char*)malloc(end_pos - (*pos)); + strncpy(spec, format+(*pos)+1, end_pos - (*pos)); + spec[end_pos - (*pos)-1] = '\0'; + + u64 spec_hash = hm_hash(spec); + Printer_Function_Type type = (Printer_Function_Type)type_map.get_object(spec, spec_hash); + + + union { + printer_function_32b printer_32b; + printer_function_64b printer_64b; + printer_function_ptr printer_ptr; + printer_function_flt printer_flt; + printer_function_void printer_void; + } printer; + + // just grab it, it will have the correct type + printer.printer_32b = printer_map.get_object(spec, spec_hash); + + free(spec); + + if (type == Printer_Function_Type::unknown) { + return 0; + } + + if (format[end_pos] == ',') { + int element_count; + + ++end_pos; + sscanf(format+end_pos, "%d", &element_count); + + while (format[end_pos] != '}' && + format[end_pos] != 0) + ++end_pos; + if (format[end_pos] == 0) + return 0; + + // both brackets already included: + int written_length = 2; + + fputs("[", file); + for (int i = 0; i < element_count - 1; ++i) { + if (type == Printer_Function_Type::_32b) written_length += printer.printer_32b(file, va_arg(*arg_list, u32)); + else if (type == Printer_Function_Type::_64b) written_length += printer.printer_64b(file, va_arg(*arg_list, u64)); + else if (type == Printer_Function_Type::_flt) written_length += printer.printer_flt(file, va_arg(*arg_list, double)); + else if (type == Printer_Function_Type::_ptr) written_length += printer.printer_ptr(file, va_arg(*arg_list, void*)); + else written_length += printer.printer_void(file); + written_length += 2; + fputs(", ", file); + } + if (element_count > 0) { + if (type == Printer_Function_Type::_32b) written_length += printer.printer_32b(file, va_arg(*arg_list, u32)); + else if (type == Printer_Function_Type::_64b) written_length += printer.printer_64b(file, va_arg(*arg_list, u64)); + else if (type == Printer_Function_Type::_flt) written_length += printer.printer_flt(file, va_arg(*arg_list, double)); + else if (type == Printer_Function_Type::_ptr) written_length += printer.printer_ptr(file, va_arg(*arg_list, void*)); + else written_length += printer.printer_void(file); + } + fputs("]", file); + + *pos = end_pos; + return written_length; + } else if (format[end_pos] == '[') { + end_pos++; + u32 element_count; + union { + u32* arr_32b; + u64* arr_64b; + f32* arr_flt; + void** arr_ptr; + } arr; + + if (type == Printer_Function_Type::_32b) arr.arr_32b = va_arg(*arg_list, u32*); + else if (type == Printer_Function_Type::_64b) arr.arr_64b = va_arg(*arg_list, u64*); + else if (type == Printer_Function_Type::_flt) arr.arr_flt = va_arg(*arg_list, f32*); + else arr.arr_ptr = va_arg(*arg_list, void**); + + if (format[end_pos] == '*') { + element_count = va_arg(*arg_list, u32); + } else { + sscanf(format+end_pos, "%d", &element_count); + } + + // skip to next ']' + while (format[end_pos] != ']' && + format[end_pos] != 0) + ++end_pos; + if (format[end_pos] == 0) + return 0; + + // skip to next '}' + while (format[end_pos] != '}' && + format[end_pos] != 0) + ++end_pos; + if (format[end_pos] == 0) + return 0; + + // both brackets already included: + int written_length = 2; + + fputs("[", file); + for (u32 i = 0; i < element_count - 1; ++i) { + if (type == Printer_Function_Type::_32b) written_length += printer.printer_32b(file, arr.arr_32b[i]); + else if (type == Printer_Function_Type::_64b) written_length += printer.printer_64b(file, arr.arr_64b[i]); + else if (type == Printer_Function_Type::_flt) written_length += printer.printer_flt(file, arr.arr_flt[i]); + else if (type == Printer_Function_Type::_ptr) written_length += printer.printer_ptr(file, arr.arr_ptr[i]); + else written_length += printer.printer_void(file); + written_length += 2; + fputs(", ", file); + } + if (element_count > 0) { + if (type == Printer_Function_Type::_32b) written_length += printer.printer_32b(file, arr.arr_32b[element_count - 1]); + else if (type == Printer_Function_Type::_64b) written_length += printer.printer_64b(file, arr.arr_64b[element_count - 1]); + else if (type == Printer_Function_Type::_flt) written_length += printer.printer_flt(file, arr.arr_flt[element_count - 1]); + else if (type == Printer_Function_Type::_ptr) written_length += printer.printer_ptr(file, arr.arr_ptr[element_count - 1]); + else written_length += printer.printer_void(file); + } + fputs("]", file); + + *pos = end_pos; + return written_length; + } else { + *pos = end_pos; + if (type == Printer_Function_Type::_32b) return printer.printer_32b(file, va_arg(*arg_list, u32)); + else if (type == Printer_Function_Type::_64b) return printer.printer_64b(file, va_arg(*arg_list, u64)); + else if (type == Printer_Function_Type::_flt) return printer.printer_flt(file, va_arg(*arg_list, double)); + else if (type == Printer_Function_Type::_ptr) return printer.printer_ptr(file, va_arg(*arg_list, void*)); + else return printer.printer_void(file); + } + return 0; + +} + +int maybe_fprintf(FILE* file, static_string format, int* pos, va_list* arg_list) { + // %[flags][width][.precision][length]specifier + // flags ::= [+- #0] + // width ::= [+ \*] + // precision ::= \.[+ \*] + // length ::= [h l L] + // specifier ::= [c d i e E f g G o s u x X p n %] + int end_pos = *pos; + int writen_len = 0; + int used_arg_values = 1; + + // overstep flags: + while(format[end_pos] == '+' || + format[end_pos] == '-' || + format[end_pos] == ' ' || + format[end_pos] == '#' || + format[end_pos] == '0') + ++end_pos; + + // overstep width + if (format[end_pos] == '*') { + ++used_arg_values; + ++end_pos; + } + else { + while(format[end_pos] >= '0' && format[end_pos] <= '9') + ++end_pos; + } + + // overstep precision + if (format[end_pos] == '.') { + ++end_pos; + if (format[end_pos] == '*') { + ++used_arg_values; + ++end_pos; + } + else { + while(format[end_pos] >= '0' && format[end_pos] <= '9') + ++end_pos; + } + } + + // overstep length: + while(format[end_pos] == 'h' || + format[end_pos] == 'l' || + format[end_pos] == 'L') + ++end_pos; + + // check for actual built_in specifier + if(format[end_pos] == 'c' || + format[end_pos] == 'd' || + format[end_pos] == 'i' || + format[end_pos] == 'e' || + format[end_pos] == 'E' || + format[end_pos] == 'f' || + format[end_pos] == 'g' || + format[end_pos] == 'G' || + format[end_pos] == 'o' || + format[end_pos] == 's' || + format[end_pos] == 'u' || + format[end_pos] == 'x' || + format[end_pos] == 'X' || + format[end_pos] == 'p' || + format[end_pos] == 'n' || + format[end_pos] == '%') + { + writen_len = end_pos - *pos + 2; + char* temp = (char*)malloc((writen_len+1)* sizeof(char)); + temp[0] = '%'; + temp[1] = 0; + strncpy(temp+1, format+*pos, writen_len); + temp[writen_len] = 0; + + // printf("\ntest:: len(%s) = %d\n", temp, writen_len+1); + + writen_len = vfprintf(file, temp, *arg_list); + + // NOTE(Felix): For WSL Linux we have to manually overstep the + // used args + for (int i = 0; i < used_arg_values; ++i) { + va_arg(*arg_list, void*); + } + + free(temp); + *pos = end_pos; + } + + return writen_len; +} + + +int vafprint(FILE* file, static_string format, va_list* arg_list) { + int printed_chars = 0; + + char c; + int pos = -1; + while ((c = format[++pos])) { + if (c != '%') { + putc(c, file); + ++printed_chars; + } else { + c = format[++pos]; + int move = maybe_special_print(file, format, &pos, arg_list); + if (move == 0) { + move = maybe_fprintf(file, format, &pos, arg_list); + if (move == 0) { + putchar('%'); + putchar(c); + move = 1; + } + } + printed_chars += move; + } + } + + return printed_chars; +} + +int print_to_string(char** out, static_string format, ...) { + va_list arg_list; + va_start(arg_list, format); + + FILE* t_file = tmpfile(); + if (!t_file) { + return 0; + } + + int num_printed_chars = vafprint(t_file, format, &arg_list); + va_end(arg_list); + + + *out = (char*)malloc(sizeof(char) * (num_printed_chars+1)); + + rewind(t_file); + size_t newLen = fread(*out, sizeof(char), num_printed_chars, t_file); + (*out)[num_printed_chars] = '\0'; + + fclose(t_file); + + return num_printed_chars; +} + +int print_to_file(FILE* file, static_string format, ...) { + va_list arg_list; + va_start(arg_list, format); + + int num_printed_chars = vafprint(file, format, &arg_list); + + va_end(arg_list); + + return num_printed_chars; +} + +int print(static_string format, ...) { + va_list arg_list; + va_start(arg_list, format); + + int num_printed_chars = vafprint(stdout, format, &arg_list); + + va_end(arg_list); + + return num_printed_chars; +} + +int print_bool(FILE* f, u32 val) { + return print_to_file(f, val ? "true" : "false"); +} + +int print_u32(FILE* f, u32 num) { + return print_to_file(f, "%u", num); +} + +int print_u64(FILE* f, u64 num) { + return print_to_file(f, "%llu", num); +} + +int print_s32(FILE* f, s32 num) { + return print_to_file(f, "%d", num); +} + +int print_s64(FILE* f, s64 num) { + return print_to_file(f, "%lld", num); +} + +int print_flt(FILE* f, double arg) { + return print_to_file(f, "%f", arg); +} + +int print_str(FILE* f, char* str) { + return print_to_file(f, "%s", str); +} + +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"); +} + +void init_printer() { + 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); +} diff --git a/test.cpp b/test.cpp index 5e092d0..32a8a4b 100644 --- a/test.cpp +++ b/test.cpp @@ -1,27 +1,46 @@ #define _CRT_SECURE_NO_WARNINGS #include +#include #include "./types.hpp" #include "./hooks.hpp" -Hook h; + +#include "./print.hpp" + + +int print_dots(FILE* f) { + return print_to_file(f, "..."); +} + s32 main(s32 argc, char* argv[]) { - printf("Hello world"); - // system_shutdown_hook << [] { - // printf("Goodbye world\n"); - // }; - - h << []{ - printf("Hallo1"); - }; - h << [] { - printf("Hallo2"); - }; - - h << [] { - printf("Hallo3"); - }; - h(); + 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); + + u32 u1 = -1; + u64 u2 = -1; + + char* str; + print_to_string(&str, " - %{dots[5]} %{ptr} <> %{ptr,2}\n", &u1, &arr, nullptr); + print("---> %{str}", 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(" - %{f32[3]}\n", f_arr); + // print(" - %{f32,3}\n", 44.9, 55.1, 66.2); + // print(" - %{u32[5]}\n", arr); + // print(" - %{u32[*]}\n", arr, 4); + // 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); + return 0; }