diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f972477 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dependencies/tlibc"] + path = dependencies/tlibc + url = https://timerix.ddns.net/git/Timerix/tlibc.git diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..bdbec87 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,14 @@ +{ + "configurations": [ + { + "name": "all", + "defines": [], + "includePath": [ + "dependencies/tlibc/include", + "${default}" + ], + "cStandard": "c11" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index 75f1c7b..3164634 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,12 @@ Machine code interpreter written in pure C. Can execute programs up to 1 MEGABYTE (1048576 bytes) in size!!! ## Building -1. Install [cbuild](https://timerix.ddns.net:3322/Timerix/cbuild.git) -2. Install [SDL3](https://github.com/libsdl-org/SDL) and [SDL3_image](https://github.com/libsdl-org/SDL_image) from package manager or source. +1. Clone repo + ``` + git clone --recurse-submodules --depth 1 https://timerix.ddns.net/git/Timerix/tcpu.git + ``` +2. Install [cbuild](https://timerix.ddns.net/git/Timerix/cbuild.git) +3. Install [SDL3](https://github.com/libsdl-org/SDL) and [SDL3_image](https://github.com/libsdl-org/SDL_image) from package manager or source. 3. ```sh cbuild build_exec_dbg ``` diff --git a/dependencies/tlibc b/dependencies/tlibc new file mode 160000 index 0000000..51980eb --- /dev/null +++ b/dependencies/tlibc @@ -0,0 +1 @@ +Subproject commit 51980ebb0b5d220c0e2c7bffe853d4d3e2628a56 diff --git a/dependencies/tlibc.config b/dependencies/tlibc.config new file mode 100644 index 0000000..94d8d2f --- /dev/null +++ b/dependencies/tlibc.config @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +########################################################### +# Copy this file to your cbuild DEPENDENCY_CONFIGS_DIR # +# and enable it (ENABLED_DEPENDENCIES=tlibc). # +########################################################### +DEP_WORKING_DIR="dependencies/tlibc" +DEP_PRE_BUILD_COMMAND="" +DEP_POST_BUILD_COMMAND="" +if [[ "$TASK" = *_dbg ]]; then + dep_build_target="build_static_lib_dbg" +else + dep_build_target="build_static_lib" +fi +DEP_BUILD_COMMAND="cbuild $dep_build_target" +DEP_CLEAN_COMMAND="cbuild clean" +DEP_DYNAMIC_OUT_FILES="" +DEP_STATIC_OUT_FILES="bin/tlibc.a" +DEP_OTHER_OUT_FILES="" +PRESERVE_OUT_DIRECTORY_STRUCTURE=false diff --git a/project.config b/project.config index 84781e7..71549b4 100755 --- a/project.config +++ b/project.config @@ -1,22 +1,21 @@ #!/usr/bin/env bash -CBUILD_VERSION=2.1.4 -CONFIG_VERSION=1 +CBUILD_VERSION=2.2.3 PROJECT="tcpu" CMP_C="gcc" CMP_CPP="g++" STD_C="c11" STD_CPP="c++11" -WARN_C="-Wall -Wextra -Wno-unused-parameter" -WARN_CPP="-Wall -Wextra -Wno-unused-parameter" +WARN_C="-Wall -Wextra -Werror=pointer-arith -Wno-unused-parameter" +WARN_CPP="-Wall -Wextra -Werror=pointer-arith -Wno-unused-parameter" SRC_C="$(find src -name '*.c')" SRC_CPP="$(find src -name '*.cpp')" # Directory with dependency configs. # See cbuild/example_dependency_configs -DEPENDENCY_CONFIGS_DIR='.' +DEPENDENCY_CONFIGS_DIR='dependencies' # List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space. -ENABLED_DEPENDENCIES='' +ENABLED_DEPENDENCIES='tlibc' # OBJDIR structure: # ├── objects/ - Compiled object files. Cleans on each call of build task @@ -27,19 +26,19 @@ OBJDIR="obj" OUTDIR="bin" STATIC_LIB_FILE="lib$PROJECT.a" +INCLUDE="-I./dependencies/tlibc/include" + # OS-specific options case "$OS" in WINDOWS) EXEC_FILE="$PROJECT.exe" SHARED_LIB_FILE="$PROJECT.dll" LINKER_LIBS="-lSDL3_image -lSDL3" - INCLUDE="" ;; LINUX) EXEC_FILE="$PROJECT" SHARED_LIB_FILE="$PROJECT.so" LINKER_LIBS="-lSDL3_image -lSDL3" - INCLUDE="" ;; *) error "operating system $OS has no configuration variants" diff --git a/src/VM/Display/Display.h b/src/VM/Display/Display.h index 557b7c5..010cd66 100644 --- a/src/VM/Display/Display.h +++ b/src/VM/Display/Display.h @@ -1,6 +1,6 @@ #pragma once -#include "../../std.h" -#include "../../string/str.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" typedef struct Rect { i32 x, y; diff --git a/src/VM/VM.h b/src/VM/VM.h index 5a71579..41707b2 100644 --- a/src/VM/VM.h +++ b/src/VM/VM.h @@ -1,6 +1,6 @@ #pragma once -#include "../std.h" -#include "../string/str.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" #include "../instructions/registers.h" typedef union Register { diff --git a/src/VM/time.c b/src/VM/time.c deleted file mode 100644 index a021b8a..0000000 --- a/src/VM/time.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include "time.h" - -void time_sleepMS(u32 ms){ - SDL_Delay(ms); -} - -void time_sleepNS(u64 ns){ - SDL_DelayNS(ns); -} - -u64 time_getMonotonicMS(){ - return SDL_GetTicks(); -} - -u64 time_getMonotonicNS(){ - return SDL_GetTicksNS(); -} diff --git a/src/VM/time.h b/src/VM/time.h deleted file mode 100644 index 810c5c8..0000000 --- a/src/VM/time.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "../std.h" - -void time_sleepMS(u32 ms); -void time_sleepNS(u64 ns); -u64 time_getMonotonicMS(); -u64 time_getMonotonicNS(); diff --git a/src/collections/Array.h b/src/collections/Array.h deleted file mode 100644 index 28a55e1..0000000 --- a/src/collections/Array.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "../std.h" - -#define Array_construct(T, DATA, LEN) ((Array_##T){ .data = DATA, .len = LEN }) - -/// creates Array_##T from a const array -#define ARRAY(T, A...) Array_construct(T, ((T[])A), ARRAY_SIZE(((T[])A))) - -#define Array_declare(T)\ -typedef struct Array_##T {\ - T* data;\ - u32 len;\ -} Array_##T;\ -\ -static inline Array_##T Array_##T##_alloc(u32 len){\ - return Array_construct(T, (T*)malloc(len * sizeof(T)), len);\ -}\ -static inline void Array_##T##_realloc(Array_##T* ptr, u32 new_len){\ - ptr->data = (T*)realloc(ptr->data, new_len * sizeof(T));\ - ptr->len = new_len;\ -} - -Array_declare(u8) -Array_declare(u32) diff --git a/src/collections/HashMap.h b/src/collections/HashMap.h deleted file mode 100644 index 2d13ec3..0000000 --- a/src/collections/HashMap.h +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once -#include "../std.h" -#include "../string/str.h" -#include "Array.h" -#include "List.h" - -//TODO: sorting of bucket and binary search -//TODO: delayed deletion - -#define __HashMap_HASH_FUNC str_hash32 -#define __HashMapBucket_MAX_LEN 16 - -#define HashMap_DESTROY_VALUE_FUNC_NULL ((void (*)(void*))NULL) - -/// call this in a header file -///@param T Value type -#define HashMap_declare(T)\ -typedef struct KeyValue_##T {\ - str key;\ - T value;\ - u32 hash;\ -} KeyValue_##T;\ -\ -List_declare(KeyValue_##T);\ -\ -typedef struct HashMapBucket_##T {\ - List_KeyValue_##T kvs;\ -} HashMapBucket_##T;\ -\ -typedef struct HashMap_##T {\ - HashMapBucket_##T* table;\ - u32 height;\ - u16 height_n;\ -} HashMap_##T;\ -\ -void HashMap_##T##_alloc(HashMap_##T* ptr);\ -void HashMap_##T##_free(HashMap_##T* ptr);\ -T* NULLABLE(HashMap_##T##_tryGetPtr)(HashMap_##T* ptr, str key);\ -bool HashMap_##T##_tryPush(HashMap_##T* ptr, str key, T value);\ -bool HashMap_##T##_tryDelete(HashMap_##T* ptr, str key);\ - - - -/// call this in a source code file -///@param T Value type -///@param DESTROY_VALUE_FUNC `void foo (T*)` or HashMap_DESTROY_VALUE_FUNC_NULL -#define HashMap_define(T, DESTROY_VALUE_FUNC)\ -List_define(KeyValue_##T);\ -\ -static const Array_u32 __HashMap_##T##_heights = ARRAY(u32, {\ - 17, 31, 61, 127, 257, 521, 1021, 2053, 4099, 8191, 16381, 32771,\ - 65521, 131071, 262147, 524287, 1048583, 2097169, 4194319,\ - 8388617, 16777213, 33554467, 67108859, 134217757, 268435493\ -});\ -\ -void HashMap_##T##_alloc(HashMap_##T* ptr){\ - ptr->height_n = 0;\ - ptr->height = __HashMap_##T##_heights.data[0];\ - ptr->table = (HashMapBucket_##T*)malloc(ptr->height * sizeof(HashMapBucket_##T));\ - memset(ptr->table, 0, ptr->height * sizeof(HashMapBucket_##T));\ -}\ -\ -void HashMap_##T##_free(HashMap_##T* ptr){\ - for(u32 i = 0; i < ptr->height; i++){\ - for(u32 j = 0; j < ptr->table[i].kvs.len; j++){\ - KeyValue_##T* kv_ptr = &ptr->table[i].kvs.data[j];\ - if(DESTROY_VALUE_FUNC){\ - DESTROY_VALUE_FUNC(&kv_ptr->value);\ - }\ - free(kv_ptr->key.data);\ - }\ - \ - free(ptr->table[i].kvs.data);\ - }\ - \ - free(ptr->table);\ -}\ -\ -T* NULLABLE(HashMap_##T##_tryGetPtr)(HashMap_##T* ptr, str key){\ - u32 hash = __HashMap_HASH_FUNC(key);\ - HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\ - for(u32 i = 0; i < bu->kvs.len; i++){\ - if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\ - return &bu->kvs.data[i].value;\ - }\ - }\ - \ - return NULL;\ -}\ -\ -bool HashMap_##T##_tryPush(HashMap_##T* ptr, str key, T value){\ - u32 hash = __HashMap_HASH_FUNC(key);\ - HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\ - for(u32 i = 0; i < bu->kvs.len; i++){\ - if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\ - return false;\ - }\ - }\ - \ - if(bu->kvs.len >= __HashMapBucket_MAX_LEN){\ - u32 height_expanded_n = ptr->height_n + 1;\ - if(height_expanded_n >= __HashMap_##T##_heights.len){\ - printf("ERROR: HashMap_" #T " IS FULL\n");\ - return false;\ - }\ - \ - u32 height_expanded = __HashMap_##T##_heights.data[height_expanded_n];\ - HashMapBucket_##T* table_expanded = (HashMapBucket_##T*)malloc(height_expanded * sizeof(HashMapBucket_##T));\ - memset(table_expanded, 0, height_expanded * sizeof(HashMapBucket_##T));\ - for(u32 i = 0; i < height_expanded; i++){\ - for(u32 j = 0; j < ptr->table[i].kvs.len; j++){\ - KeyValue_##T kv = ptr->table[i].kvs.data[j];\ - List_KeyValue_##T##_push(&table_expanded[kv.hash % height_expanded].kvs, kv);\ - }\ - \ - free(ptr->table[i].kvs.data);\ - }\ - free(ptr->table);\ - ptr->table = table_expanded;\ - ptr->height = height_expanded;\ - ptr->height_n = height_expanded_n;\ - bu = &ptr->table[hash % ptr->height];\ - }\ - \ - KeyValue_##T kv = { .key = str_copy(key), .value = value, .hash = hash };\ - List_KeyValue_##T##_push(&bu->kvs, kv);\ - return true;\ -}\ -\ -bool HashMap_##T##_tryDelete(HashMap_##T* ptr, str key){\ - u32 hash = __HashMap_HASH_FUNC(key);\ - HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\ - for(u32 i = 0; i < bu->kvs.len; i++){\ - if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\ - return List_KeyValue_##T##_tryRemoveAt(&bu->kvs, i);\ - }\ - }\ - \ - return false;\ -} diff --git a/src/collections/List.c b/src/collections/List.c deleted file mode 100644 index 2597efb..0000000 --- a/src/collections/List.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "List.h" - -List_define(u32); -List_define(u8); diff --git a/src/collections/List.h b/src/collections/List.h deleted file mode 100644 index a61f34b..0000000 --- a/src/collections/List.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once -#include "../std.h" - -// minimal max_len after initial (0) -#define __List_min_size 16 - -#define List_declare(T)\ - typedef struct List_##T {\ - T* data;\ - u32 len;\ - u32 max_len;\ - } List_##T;\ - \ - static inline List_##T List_##T##_construct(T* data_ptr, u32 len, u32 max_len) {\ - return (List_##T){ .data = data_ptr, .len = len, .max_len = max_len };\ - }\ - \ - List_##T List_##T##_alloc(u32 initial_len);\ - \ - T* List_##T##_expand(List_##T* ptr, u32 count);\ - void List_##T##_push(List_##T* ptr, T value);\ - void List_##T##_pushMany(List_##T* ptr, T* values, u32 count);\ - bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i);\ - - -#define List_define(T)\ - List_##T List_##T##_alloc(u32 initial_len){\ - if(initial_len == 0)\ - return List_##T##_construct((T*)NULL, 0, 0);\ - u32 max_len = ALIGN_TO(initial_len, sizeof(void*)/sizeof(T));\ - /* branchless version of max(max_len, __List_min_size) */\ - max_len += (max_len < __List_min_size) * (__List_min_size - max_len);\ - return List_##T##_construct((T*)malloc(max_len * sizeof(T)), 0, max_len);\ - }\ - \ - T* List_##T##_expand(List_##T* ptr, u32 count){\ - u32 occupied_len = ptr->len;\ - u32 expanded_max_len = ptr->max_len;\ - expanded_max_len += (expanded_max_len < __List_min_size) * (__List_min_size - expanded_max_len);\ - ptr->len += count;\ - while(ptr->len > expanded_max_len){\ - expanded_max_len *= 2;\ - }\ - u32 alloc_size = expanded_max_len * sizeof(T);\ - if(ptr->data == NULL)\ - ptr->data = (T*)malloc(alloc_size);\ - else ptr->data = (T*)realloc(ptr->data, alloc_size);\ - ptr->max_len = expanded_max_len;\ - return ptr->data + occupied_len;\ - }\ - \ - void List_##T##_push(List_##T* ptr, T value){\ - T* empty_cell_ptr = List_##T##_expand(ptr, 1);\ - *empty_cell_ptr = value;\ - }\ - \ - void List_##T##_pushMany(List_##T* ptr, T* values, u32 count){\ - T* empty_cell_ptr = List_##T##_expand(ptr, count);\ - memcpy(empty_cell_ptr, values, count * sizeof(T));\ - }\ - \ - bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i){\ - if(ptr->len == 0 || i >= ptr->len)\ - return false;\ - \ - ptr->len--;\ - for(; i < ptr->len; i++){\ - ptr->data[i] = ptr->data[i + 1];\ - }\ - return true;\ - }\ - - -List_declare(u32); -List_declare(u8); diff --git a/src/compiler/AST.c b/src/compiler/AST.c index 97ca81e..a152725 100644 --- a/src/compiler/AST.c +++ b/src/compiler/AST.c @@ -1,52 +1,49 @@ #include "AST.h" -List_define(Argument); -List_define(Operation); -List_define(DataDefinition); -List_define(Section); - -static str _ArgumentType_str[] = { +static Array(str) _ArgumentType_str_array = ARRAY(str, { STR("Unset"), STR("Register"), STR("ConstValue"), STR("VarDataName"), STR("ConstDataPointer"), STR("ConstDataSize"), -}; +}); str ArgumentType_toString(ArgumentType t){ - if(t >= ARRAY_SIZE(_ArgumentType_str)) + if(t >= Array_len(&_ArgumentType_str_array, str)) return STR("!!ArgumentType INDEX_ERROR!!"); - return _ArgumentType_str[t]; + return ((str*)_ArgumentType_str_array.data)[t]; } void Section_init(Section* sec, str name){ sec->name = name; - sec->data = List_DataDefinition_alloc(256); - sec->code = List_Operation_alloc(1024); + sec->data_definitions_list = List_alloc(DataDefinition, 256); + sec->operations_list = List_alloc(Operation, 1024); } void Section_free(Section* sec){ - for(u32 i = 0; i < sec->data.len; i++){ - free(sec->data.data[i].data.data); + for(u32 i = 0; i < Array_len(&sec->data_definitions_list, DataDefinition); i++){ + DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i; + free(dd->data_bytes.data); } - free(sec->data.data); + free(sec->data_definitions_list.data); - for(u32 i = 0; i < sec->code.len; i++){ - free(sec->code.data[i].args.data); + for(u32 i = 0; i < Array_len(&sec->operations_list, Operation); i++){ + Operation* op = (Operation*)sec->operations_list.data + i; + free(op->args.data); } - free(sec->code.data); + free(sec->operations_list.data); } void AST_init(AST* ast){ - ast->sections = List_Section_alloc(32); + ast->sections = List_alloc(Section, 32); } void AST_free(AST* ast){ - for(u32 i = 0; i != ast->sections.len; i++){ - Section_free(&ast->sections.data[i]); + for(u32 i = 0; i != Array_len(&ast->sections, Section); i++){ + Section_free((Section*)ast->sections.data + i); } free(ast->sections.data); } diff --git a/src/compiler/AST.h b/src/compiler/AST.h index 8c2f878..5355d17 100644 --- a/src/compiler/AST.h +++ b/src/compiler/AST.h @@ -1,9 +1,9 @@ #pragma once -#include "../std.h" -#include "../string/str.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" #include "../instructions/instructions.h" #include "../instructions/registers.h" -#include "../collections/List.h" +#include "tlibc/collections/List.h" typedef enum ArgumentType { ArgumentType_Unset, @@ -26,39 +26,31 @@ typedef struct Argument { } value; } Argument; -List_declare(Argument); - typedef struct Operation { - List_Argument args; + List(Argument) args; Opcode opcode; } Operation; -List_declare(Operation); - typedef struct DataDefinition { str name; - List_u8 data; + List(u8) data_bytes; u32 element_size; } DataDefinition; -List_declare(DataDefinition); - typedef struct Section { str name; - List_DataDefinition data; - List_Operation code; + List(DataDefinition) data_definitions_list; + List(Operation) operations_list; } Section; -List_declare(Section); - void Section_init(Section* Section, str name); void Section_free(Section* Section); typedef struct AST { - List_Section sections; + List(Section) sections; } AST; void AST_init(AST* ast); diff --git a/src/compiler/Binary.c b/src/compiler/Binary.c index ac7b82e..2fc1ce0 100644 --- a/src/compiler/Binary.c +++ b/src/compiler/Binary.c @@ -1,19 +1,12 @@ #include "Binary.h" -List_define(ConstDataProps); -HashMap_define(ConstDataProps, HashMap_DESTROY_VALUE_FUNC_NULL); -List_define(NamedRef); -List_define(CompiledSection); -HashMap_define(CompiledSectionPtr, HashMap_DESTROY_VALUE_FUNC_NULL); - - void CompiledSection_construct(CompiledSection* ptr, str name){ ptr->name = name; ptr->next = NULL; ptr->offset = 0; - ptr->const_data_props_list = List_ConstDataProps_construct(NULL, 0, 0); - ptr->named_refs = List_NamedRef_construct(NULL, 0, 0); - ptr->bytes = List_u8_alloc(64); + ptr->const_data_props_list = List_construct(ConstDataProps, NULL, 0, 0); + ptr->named_refs = List_construct(NamedRef, NULL, 0, 0); + ptr->bytes = List_alloc(u8, 64); } void CompiledSection_free(CompiledSection* ptr){ @@ -24,19 +17,20 @@ void CompiledSection_free(CompiledSection* ptr){ void BinaryObject_construct(BinaryObject* ptr){ - ptr->section_list = List_CompiledSection_alloc(64); - HashMap_CompiledSectionPtr_alloc(&ptr->section_map); - HashMap_ConstDataProps_alloc(&ptr->const_data_map); - ptr->main_section = NULL; + ptr->comp_sec_list = List_alloc(CompiledSection, 64); + HashMap_create(&ptr->comp_sec_i_map, u32, NULL); + HashMap_create(&ptr->const_data_props_map, ConstDataProps, NULL); + ptr->main_sec = NULL; ptr->total_size = 0; } void BinaryObject_free(BinaryObject* ptr){ - for(u32 i = 0; i < ptr->section_list.len; i++){ - CompiledSection_free(&ptr->section_list.data[i]); + for(u32 i = 0; i < List_len(&ptr->comp_sec_list, CompiledSection); i++){ + CompiledSection* sec_ptr = (CompiledSection*)ptr->comp_sec_list.data + i; + CompiledSection_free(sec_ptr); } - free(ptr->section_list.data); + free(ptr->comp_sec_list.data); - HashMap_CompiledSectionPtr_free(&ptr->section_map); - HashMap_ConstDataProps_free(&ptr->const_data_map); + HashMap_destroy(&ptr->comp_sec_i_map); + HashMap_destroy(&ptr->const_data_props_map); } diff --git a/src/compiler/Binary.h b/src/compiler/Binary.h index bbd6e43..8eeb2bd 100644 --- a/src/compiler/Binary.h +++ b/src/compiler/Binary.h @@ -1,10 +1,10 @@ #pragma once -#include "../std.h" -#include "../string/str.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" #include "../instructions/instructions.h" #include "../instructions/registers.h" -#include "../collections/List.h" -#include "../collections/HashMap.h" +#include "tlibc/collections/List.h" +#include "tlibc/collections/HashMap.h" #include "AST.h" typedef struct CompiledSection CompiledSection; @@ -16,9 +16,6 @@ typedef struct ConstDataProps { #define ConstDataProps_construct(NAME, SIZE, OFFSET) ((ConstDataProps){ .name = NAME, .size = SIZE, .offset = OFFSET}) -List_declare(ConstDataProps); -HashMap_declare(ConstDataProps); - typedef enum NamedRefType { NamedRefType_Unset, @@ -34,31 +31,25 @@ typedef struct NamedRef { #define NamedRef_construct(NAME, TYPE, OFFSET) ((NamedRef){ .name = NAME, .type = TYPE, .offset = OFFSET}) -List_declare(NamedRef); - typedef struct CompiledSection { str name; CompiledSection* next; u32 offset; - List_ConstDataProps const_data_props_list; - List_NamedRef named_refs; - List_u8 bytes; + List(ConstDataProps) const_data_props_list; + List(NamedRef) named_refs; + List(u8) bytes; } CompiledSection; void CompiledSection_construct(CompiledSection* ptr, str name); void CompiledSection_free(CompiledSection* ptr); -List_declare(CompiledSection); -typedef CompiledSection* CompiledSectionPtr; -HashMap_declare(CompiledSectionPtr); - typedef struct BinaryObject { - List_CompiledSection section_list; - HashMap_CompiledSectionPtr section_map; - NULLABLE(CompiledSection*) main_section; - HashMap_ConstDataProps const_data_map; + List(CompiledSection) comp_sec_list; + HashMap(u32) comp_sec_i_map; + NULLABLE(CompiledSection*) main_sec; + HashMap(ConstDataProps) const_data_props_map; u32 total_size; } BinaryObject; diff --git a/src/compiler/Compiler.c b/src/compiler/Compiler.c index bb17bbb..732be9b 100644 --- a/src/compiler/Compiler.c +++ b/src/compiler/Compiler.c @@ -1,12 +1,10 @@ #include "Compiler_internal.h" -HashMap_define(SectionPtr, HashMap_DESTROY_VALUE_FUNC_NULL); - void Compiler_init(Compiler* cmp){ memset(cmp, 0, sizeof(Compiler)); cmp->state = CompilerState_Initial; - cmp->tokens = List_Token_alloc(4096); - cmp->line_lengths = List_u32_alloc(1024); + cmp->tokens = List_alloc(Token, 4096); + cmp->line_lengths = List_alloc(u32, 1024); AST_init(&cmp->ast); BinaryObject_construct(&cmp->binary); } @@ -21,11 +19,11 @@ void Compiler_free(Compiler* cmp){ CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){ u32 prev_lines_len = 0; - if(pos >= cmp->code.len) + if(pos >= cmp->code.size) return CodePos_create(0, 0); - for(u32 i = 0; i < cmp->line_lengths.len; i++){ - u32 line_len = cmp->line_lengths.data[i]; + for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){ + u32 line_len = ((u32*)cmp->line_lengths.data)[i]; if(prev_lines_len + line_len > pos) return CodePos_create(i + 1, pos + 1 - prev_lines_len); prev_lines_len += line_len; @@ -36,8 +34,8 @@ CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){ void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){ // happens at the end of file - if(cmp->pos >= cmp->code.len) - cmp->pos = cmp->code.len - 1; + if(cmp->pos >= cmp->code.size) + cmp->pos = cmp->code.size - 1; char position_str[32]; CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos); sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column); @@ -65,19 +63,20 @@ str Compiler_constructTokenStr(Compiler* cmp, Token t){ } static bool compileSection(Compiler* cmp, Section* sec){ - CompiledSection* cs = List_CompiledSection_expand(&cmp->binary.section_list, 1); + u32 cs_index = List_len(&cmp->binary.comp_sec_list, CompiledSection); + CompiledSection* cs = List_expand_size(&cmp->binary.comp_sec_list, sizeof(CompiledSection)); CompiledSection_construct(cs, sec->name); - if(!HashMap_CompiledSectionPtr_tryPush(&cmp->binary.section_map, cs->name, cs)){ + if(!HashMap_tryPush(&cmp->binary.comp_sec_i_map, cs->name, &cs_index)){ returnError("duplicate section '%s'", str_copy(sec->name).data); } // compile code u8 zeroes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - for(u32 i = 0; i < sec->code.len; i++){ - Operation* op = &sec->code.data[i]; - List_u8_pushMany(&cs->bytes, (void*)&op->opcode, sizeof(op->opcode)); - for(u32 j = 0; j < op->args.len; j++){ - Argument* arg = &op->args.data[j]; + for(u32 i = 0; i < List_len(&sec->operations_list, Operation); i++){ + Operation* op = (Operation*)sec->operations_list.data + i; + List_pushMany(&cs->bytes, u8, &op->opcode, sizeof(op->opcode)); + for(u32 j = 0; j < List_len(&op->args, Argument); j++){ + Argument* arg = (Argument*)op->args.data + j; switch(arg->type){ case ArgumentType_VarDataName: returnError("argument type 'VarDataName' is not supported yet"); @@ -87,34 +86,35 @@ static bool compileSection(Compiler* cmp, Section* sec){ returnError("invalid ArgumentType %i", arg->type); case ArgumentType_Register: - List_u8_push(&cs->bytes, arg->value.register_code); + List_push(&cs->bytes, u8, arg->value.register_code); break; case ArgumentType_ConstValue: - List_u8_pushMany(&cs->bytes, (void*)&arg->value.i, 8); + List_pushMany(&cs->bytes, u8, &arg->value.i, 8); break; case ArgumentType_ConstDataPointer: - List_NamedRef_push(&cs->named_refs, NamedRef_construct( + List_push(&cs->named_refs, NamedRef, NamedRef_construct( arg->value.data_name, NamedRefType_Ptr, - cs->bytes.len)); - List_u8_pushMany(&cs->bytes, zeroes, 8); + cs->bytes.size)); + List_pushMany(&cs->bytes, u8, zeroes, 8); break; case ArgumentType_ConstDataSize: - List_NamedRef_push(&cs->named_refs, NamedRef_construct( + List_push(&cs->named_refs, NamedRef, NamedRef_construct( arg->value.data_name, NamedRefType_Size, - cs->bytes.len)); - List_u8_pushMany(&cs->bytes, zeroes, 8); + cs->bytes.size)); + List_pushMany(&cs->bytes, u8, zeroes, 8); break; } } } // compile data - for(u32 i = 0; i < sec->data.len; i++){ - DataDefinition* dd = &sec->data.data[i]; - List_ConstDataProps_push(&cs->const_data_props_list, ConstDataProps_construct(dd->name, dd->data.len, cs->bytes.len)); - List_u8_pushMany(&cs->bytes, dd->data.data, dd->data.len); + for(u32 i = 0; i < List_len(&sec->data_definitions_list, DataDefinition); i++){ + DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i; + List_push(&cs->const_data_props_list, ConstDataProps, + ConstDataProps_construct(dd->name, dd->data_bytes.size, cs->bytes.size)); + List_pushMany(&cs->bytes, u8, dd->data_bytes.data, dd->data_bytes.size); } // TODO: push padding @@ -126,8 +126,8 @@ static bool compileBinary(Compiler* cmp){ returnErrorIf_auto(cmp->state != CompilerState_Parsing); cmp->state = CompilerState_Compiling; - for(u32 i = 0; i < cmp->ast.sections.len; i++){ - SectionPtr sec = &cmp->ast.sections.data[i]; + for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){ + Section* sec = (Section*)cmp->ast.sections.data + i; if(!compileSection(cmp, sec)){ return false; } @@ -135,31 +135,32 @@ static bool compileBinary(Compiler* cmp){ // find main section str main_sec_name = STR("main"); - CompiledSection** main_sec_ptrptr = HashMap_CompiledSectionPtr_tryGetPtr(&cmp->binary.section_map, main_sec_name); - if(main_sec_ptrptr == NULL){ + u32* main_sec_i_ptr = HashMap_tryGetPtr(&cmp->binary.comp_sec_i_map, main_sec_name); + if(main_sec_i_ptr == NULL){ returnError("no 'main' section was defined"); } - cmp->binary.main_section = *main_sec_ptrptr; + u32 main_sec_i = *main_sec_i_ptr; + cmp->binary.main_sec = (CompiledSection*)cmp->binary.comp_sec_list.data + main_sec_i; // create linked list of CompiledSection where main is the first - CompiledSection* prev_sec = *main_sec_ptrptr; + CompiledSection* prev_sec = cmp->binary.main_sec; u32 total_size = 0; - for(u32 i = 0; i < cmp->binary.section_list.len; i++){ - CompiledSection* sec = &cmp->binary.section_list.data[i]; - total_size += sec->bytes.len; + for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){ + CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i; + total_size += sec->bytes.size; bool is_main_sec = str_equals(sec->name, main_sec_name); if(!is_main_sec){ - sec->offset = prev_sec->offset + prev_sec->bytes.len; + sec->offset = prev_sec->offset + prev_sec->bytes.size; } - ConstDataProps cd = ConstDataProps_construct(sec->name, sec->bytes.len, sec->offset); - if(!HashMap_ConstDataProps_tryPush(&cmp->binary.const_data_map, cd.name, cd)){ + ConstDataProps cd = ConstDataProps_construct(sec->name, sec->bytes.size, sec->offset); + if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){ returnError("duplicate named data '%s'", str_copy(cd.name).data); } - for(u32 j = 0; j < sec->const_data_props_list.len; j++){ - cd = sec->const_data_props_list.data[j]; + for(u32 j = 0; j < List_len(&sec->const_data_props_list, ConstDataProps); j++){ + cd = ((ConstDataProps*)sec->const_data_props_list.data)[j]; cd.offset += sec->offset; - if(!HashMap_ConstDataProps_tryPush(&cmp->binary.const_data_map, cd.name, cd)){ + if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){ returnError("duplicate named data '%s'", str_copy(cd.name).data); } } @@ -171,18 +172,18 @@ static bool compileBinary(Compiler* cmp){ } // insert calculated offsets into sections - for(u32 i = 0; i < cmp->binary.section_list.len; i++){ - CompiledSection* sec = &cmp->binary.section_list.data[i]; - for(u32 j = 0; j < sec->named_refs.len; j++){ - NamedRef* ref = &sec->named_refs.data[j]; + for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){ + CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i; + for(u32 j = 0; j < List_len(&sec->named_refs, NamedRef); j++){ + NamedRef* ref = (NamedRef*)sec->named_refs.data +j; - ConstDataProps* target_data = HashMap_ConstDataProps_tryGetPtr( - &cmp->binary.const_data_map, ref->name); + ConstDataProps* target_data = HashMap_tryGetPtr( + &cmp->binary.const_data_props_map, ref->name); if(target_data == NULL){ returnError("can't find named data '%s'", str_copy(ref->name).data); } - u64* ref_value_ptr = (void*)(sec->bytes.data + ref->offset); + u64* ref_value_ptr = (void*)((u8*)sec->bytes.data + ref->offset); switch(ref->type){ default: returnError("invalid NamedRefType %i", ref->type); @@ -203,9 +204,9 @@ static bool compileBinary(Compiler* cmp){ static bool writeBinaryFile(Compiler* cmp, FILE* f){ returnErrorIf_auto(cmp->state != CompilerState_Compiling); - CompiledSection* sec = cmp->binary.main_section; + CompiledSection* sec = cmp->binary.main_sec; while(sec){ - fwrite(sec->bytes.data, 1, sec->bytes.len, f); + fwrite(sec->bytes.data, 1, sec->bytes.size, f); fflush(f); sec = sec->next; } @@ -225,19 +226,19 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, StringBuilder_append_char(&sb, ret); } if(ferror(f)){ - StringBuilder_free(&sb); + StringBuilder_destroy(&sb); fclose(f); returnError("can't read file '%s'", source_file_name); } fclose(f); - if(sb.buffer.len == 0){ - StringBuilder_free(&sb); + if(sb.buffer.size == 0){ + StringBuilder_destroy(&sb); returnError("soucre file is empty"); } cmp->code = str_copy(StringBuilder_getStr(&sb)); - StringBuilder_free(&sb); + StringBuilder_destroy(&sb); f = fopen(out_file_name, "wb"); if(f == NULL){ @@ -256,13 +257,13 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, if(debug_log){ printf("------------------------------------[lines]------------------------------------\n"); - for(u32 i = 0; i < cmp->line_lengths.len; i++){ - printf("[%u] length: %u\n", i+1, cmp->line_lengths.data[i]); + for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){ + printf("[%u] length: %u\n", i+1, ((u32*)cmp->line_lengths.data)[i]); } printf("------------------------------------[tokens]-----------------------------------\n"); - for(u32 i = 0; i < cmp->tokens.len; i++){ - Token t = cmp->tokens.data[i]; + for(u32 i = 0; i < List_len(&cmp->tokens, Token); i++){ + Token t = ((Token*)cmp->tokens.data)[i]; CodePos pos = Compiler_getLineAndColumn(cmp, t.begin); char* tokstr = malloc(4096); strncpy(tokstr, cmp->code.data + t.begin, t.length); @@ -289,22 +290,23 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, if (debug_log){ printf("-------------------------------------[AST]-------------------------------------\n"); - for(u32 i = 0; i < cmp->ast.sections.len; i++){ - Section* sec = &cmp->ast.sections.data[i]; + for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){ + Section* sec = (Section*)cmp->ast.sections.data + i; str tmpstr = str_copy(sec->name); printf("section '%s'\n", tmpstr.data); free(tmpstr.data); - for(u32 j = 0; j < sec->data.len; j++){ - DataDefinition* dd = &sec->data.data[j]; + for(u32 j = 0; j < List_len(&sec->data_definitions_list, DataDefinition); j++){ + DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + j; tmpstr = str_copy(dd->name); - printf(" const%u %s (len %u)\n", dd->element_size * 8, tmpstr.data, dd->data.len/dd->element_size); + printf(" const%u %s (len %u)\n", dd->element_size * 8, tmpstr.data, + dd->data_bytes.size/dd->element_size); free(tmpstr.data); } - for(u32 j = 0; j < sec->code.len; j++){ - Operation* op = &sec->code.data[j]; + for(u32 j = 0; j < List_len(&sec->operations_list, Operation); j++){ + Operation* op = (Operation*)sec->operations_list.data + j; const Instruction* instr = Instruction_getByOpcode(op->opcode); if(instr == NULL){ fclose(f); @@ -312,15 +314,15 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, } printf(" %s", instr->name.data); - for(u32 k = 0; k < op->args.len; k++){ - Argument* arg = &op->args.data[k]; + for(u32 k = 0; k < List_len(&op->args, Argument); k++){ + Argument* arg = (Argument*)op->args.data + k; printf(" %s(", ArgumentType_toString(arg->type).data); switch(arg->type){ default: fclose(f); returnError("invalid argument type %i", arg->type); - case ArgumentType_Register: + case ArgumentType_Register:; str register_name = RegisterCode_toString(arg->value.register_code); printf("%s 0x%x", register_name.data, arg->value.register_code); free(register_name.data); @@ -363,10 +365,10 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, success = compileBinary(cmp); if(debug_log){ - for(u32 i = 0; i < cmp->binary.section_list.len; i++){ - CompiledSection* sec = &cmp->binary.section_list.data[i]; + for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){ + CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i; str tmpstr = str_copy(sec->name); - printf("compiled section '%s' to %u bytes with offset 0x%x\n", tmpstr.data, sec->bytes.len, sec->offset); + printf("compiled section '%s' to %u bytes with offset 0x%x\n", tmpstr.data, sec->bytes.size, sec->offset); free(tmpstr.data); } } diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h index 87af093..c9e42fc 100644 --- a/src/compiler/Compiler.h +++ b/src/compiler/Compiler.h @@ -1,8 +1,8 @@ #pragma once -#include "../std.h" -#include "../string/str.h" -#include "../collections/List.h" -#include "../collections/HashMap.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" +#include "tlibc/collections/List.h" +#include "tlibc/collections/HashMap.h" #include "Token.h" #include "Binary.h" @@ -15,8 +15,6 @@ typedef enum CompilerState { CompilerState_Success } CompilerState; -typedef Section* SectionPtr; -HashMap_declare(SectionPtr); typedef struct Compiler { /* general fields */ @@ -26,8 +24,8 @@ typedef struct Compiler { CompilerState state; NULLABLE(char* error_message); /* lexer fields */ - List_Token tokens; - List_u32 line_lengths; + List(Token) tokens; + List(u32) line_lengths; /* parser fields */ AST ast; u32 tok_i; diff --git a/src/compiler/Compiler_internal.h b/src/compiler/Compiler_internal.h index c91fe2f..dae2fdd 100644 --- a/src/compiler/Compiler_internal.h +++ b/src/compiler/Compiler_internal.h @@ -1,5 +1,5 @@ #include "Compiler.h" -#include "../string/StringBuilder.h" +#include "tlibc/string/StringBuilder.h" void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...) __attribute__((__format__(__printf__, 3, 4))); diff --git a/src/compiler/Lexer.c b/src/compiler/Lexer.c index 665de3a..76a39e9 100644 --- a/src/compiler/Lexer.c +++ b/src/compiler/Lexer.c @@ -9,7 +9,7 @@ #define Error_endOfFile "unexpected end of file" static void completeLine(Compiler* cmp){ - List_u32_push(&cmp->line_lengths, cmp->column); + List_push(&cmp->line_lengths, u32, cmp->column); cmp->column = 0; } @@ -19,12 +19,12 @@ static void readCommentSingleLine(Compiler* cmp){ cmp->column++; cmp->pos++; - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ c = cmp->code.data[cmp->pos]; // end of line if(c == '\r' || c == '\n'){ tok.length = cmp->pos - tok.begin; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); // cmp->line will be increased in lex() return; } @@ -35,7 +35,7 @@ static void readCommentSingleLine(Compiler* cmp){ // end of file tok.length = cmp->pos - tok.begin; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); } static void readCommentMultiLine(Compiler* cmp){ @@ -44,12 +44,12 @@ static void readCommentMultiLine(Compiler* cmp){ cmp->column++; cmp->pos++; - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ c = cmp->code.data[cmp->pos]; // closing comment if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code.data[cmp->pos - 1] == '*') { tok.length = cmp->pos - tok.begin + 1; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); return; } @@ -65,7 +65,7 @@ static void readCommentMultiLine(Compiler* cmp){ static void readComment(Compiler* cmp){ char c; // '/' - if(cmp->pos + 1 == cmp->code.len){ + if(cmp->pos + 1 == cmp->code.size){ setError(Error_endOfFile); return; } @@ -91,13 +91,13 @@ static void readLabel(Compiler* cmp){ cmp->column++; Token tok = Token_construct(TokenType_Label, cmp->pos, 0); - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ c = cmp->code.data[cmp->pos]; // end of line if(c == ':' || c == '\r' || c == '\n'){ tok.length = cmp->pos - tok.begin; if(tok.length > 0) - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); else setError(Error_unexpectedCharacter(cmp->code.data[--cmp->pos])); // cmp->line will be increased in lex() return; @@ -116,7 +116,7 @@ static void readLabel(Compiler* cmp){ // end of file tok.length = cmp->pos - tok.begin; if(tok.length > 0) - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); else setError(Error_endOfFile); } @@ -125,7 +125,7 @@ static void readArguments(Compiler* cmp){ Token tok = Token_construct(TokenType_Unset, cmp->pos, 0); char quot = '\0'; // quotation character of a string value - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ c = cmp->code.data[cmp->pos]; // string argument reading @@ -143,7 +143,7 @@ static void readArguments(Compiler* cmp){ else if(c == '\r' || c == '\n' || c == ';'){ tok.length = cmp->pos - tok.begin; if(tok.length > 0) - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); // cmp->line will be increased in lex() return; } @@ -152,7 +152,7 @@ static void readArguments(Compiler* cmp){ else if(c == ' ' || c == '\t'){ tok.length = cmp->pos - tok.begin; if(tok.length > 0) - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); tok = Token_construct(TokenType_Unset, cmp->pos + 1, 0); } @@ -181,7 +181,7 @@ static void readArguments(Compiler* cmp){ // end of file tok.length = cmp->pos - tok.begin; if(tok.length > 0) - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); } static void readInstruction(Compiler* cmp){ @@ -189,14 +189,14 @@ static void readInstruction(Compiler* cmp){ cmp->pos++; cmp->column++; - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ char c = cmp->code.data[cmp->pos]; // end of line if(c == '\r' || c == '\n' || c == ';'){ tok.length = cmp->pos - tok.begin; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1); - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); // cmp->line will be increased in lex() return; } @@ -204,10 +204,10 @@ static void readInstruction(Compiler* cmp){ // arguments begin if(c == ' ' || c == '\t'){ tok.length = cmp->pos - tok.begin; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); readArguments(cmp); tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1); - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); return; } @@ -222,9 +222,9 @@ static void readInstruction(Compiler* cmp){ // end of file tok.length = cmp->pos - tok.begin; - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1); - List_Token_push(&cmp->tokens, tok); + List_push(&cmp->tokens, Token, tok); } bool Compiler_lex(Compiler* cmp){ @@ -232,7 +232,7 @@ bool Compiler_lex(Compiler* cmp){ cmp->state = CompilerState_Lexing; cmp->column = 1; - while(cmp->pos < cmp->code.len){ + while(cmp->pos < cmp->code.size){ char c = cmp->code.data[cmp->pos]; switch(c){ // skip blank characters diff --git a/src/compiler/Parser.c b/src/compiler/Parser.c index 2214e8f..8d6f545 100644 --- a/src/compiler/Parser.c +++ b/src/compiler/Parser.c @@ -1,7 +1,7 @@ #include "Compiler_internal.h" #define setError(FORMAT, ...) {\ - cmp->pos = cmp->tokens.data[cmp->tok_i].begin;\ + cmp->pos = ((Token*)cmp->tokens.data)[cmp->tok_i].begin;\ Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\ } @@ -27,20 +27,16 @@ #define Error_TokenUnset "token of undefined type" #define Error_BitSize "invalid size in bits" -static void List_u8_pushBytes(List_u8* l, void* value, u32 startIndex, u32 count){ - u8* v = value; - for(u32 byte_i = startIndex; byte_i < startIndex + count; byte_i++){ - List_u8_push(l, v[byte_i]); - } -} +#define List_pushAsBytes(L, VAL_PTR, START_INDEX, COUNT)\ + List_push_size(L, (u8*)(VAL_PTR) + START_INDEX, COUNT) static inline bool isVarSizeBits(u32 B) { return (B == 8 || B == 16 || B == 32 || B == 64); } static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){ - StringBuilder sb = StringBuilder_alloc(src.len); + StringBuilder sb = StringBuilder_alloc(src.size); char c; bool escaped = false; - for(u32 i = 0; i < src.len; i++){ + for(u32 i = 0; i < src.size; i++){ c = src.data[i]; if(c == '\\'){ escaped = !escaped; @@ -75,8 +71,8 @@ static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){ StringBuilder_append_char(&sb, c); break; default: - setError_unexpectedTokenChar(cmp->tokens.data[cmp->tok_i], i); - StringBuilder_free(&sb); + setError_unexpectedTokenChar(((Token*)cmp->tokens.data)[cmp->tok_i], i); + StringBuilder_destroy(&sb); return str_null; } @@ -96,9 +92,9 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d } free(_instr_name_zero_terminated.data); ddf->element_size = _element_size_bits / 8; - ddf->data = List_u8_alloc(32); + ddf->data_bytes = List_alloc(u8, 32); - Token tok = cmp->tokens.data[++cmp->tok_i]; + Token tok = ((Token*)cmp->tokens.data)[++cmp->tok_i]; if(tok.type != TokenType_Name){ setError_unexpectedToken(tok); return; @@ -108,8 +104,8 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d str processed_str = str_null; ddf->name = tok_str; - while(++cmp->tok_i < cmp->tokens.len){ - tok = cmp->tokens.data[cmp->tok_i]; + while(++cmp->tok_i < List_len(&cmp->tokens, Token)){ + tok = ((Token*)cmp->tokens.data)[cmp->tok_i]; switch(tok.type){ case TokenType_SingleLineComment: case TokenType_MultiLineComment: @@ -130,11 +126,11 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d processed_str = str_copy(tok_str); if(str_seekChar(tok_str, '.', 0) != -1){ f64 f = atof(processed_str.data); - List_u8_pushBytes(&ddf->data, &f, 8 - ddf->element_size, ddf->element_size); + List_pushAsBytes(&ddf->data_bytes, &f, 8 - ddf->element_size, ddf->element_size); } else { i64 i = atoll(processed_str.data); - List_u8_pushBytes(&ddf->data, &i, 8 - ddf->element_size, ddf->element_size); + List_pushAsBytes(&ddf->data_bytes, &i, 8 - ddf->element_size, ddf->element_size); } free(processed_str.data); break; @@ -144,11 +140,11 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d tok_str = Compiler_constructTokenStr(cmp, tok); processed_str = resolveEscapeSequences(cmp, tok_str); - if(processed_str.len != ddf->element_size){ - setError("can't fit char of size %i in %u bit variable", processed_str.len, _element_size_bits); + if(processed_str.size != ddf->element_size){ + setError("can't fit char of size %i in %u bit variable", processed_str.size, _element_size_bits); return; } - List_u8_pushBytes(&ddf->data, processed_str.data, 0, processed_str.len); + List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size); free(processed_str.data); break; case TokenType_String: @@ -156,7 +152,7 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d tok.length -= 2; tok_str = Compiler_constructTokenStr(cmp, tok); processed_str = resolveEscapeSequences(cmp, tok_str); - List_u8_pushBytes(&ddf->data, processed_str.data, 0, processed_str.len); + List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size); free(processed_str.data); break; } @@ -165,7 +161,7 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){ - Token tok = cmp->tokens.data[cmp->tok_i]; + Token tok = ((Token*)cmp->tokens.data)[cmp->tok_i]; const Instruction* instr = Instruction_getByName(instr_name); if(instr == NULL){ setError_unexpectedInstruction(tok); @@ -173,12 +169,12 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){ } operPtr->opcode = instr->opcode; - operPtr->args = List_Argument_alloc(8); + operPtr->args = List_alloc(Argument, 8); Argument arg = (Argument){ .type = ArgumentType_Unset, .value.i = 0 }; str tok_str = str_null; str processed_str = str_null; - while(++cmp->tok_i < cmp->tokens.len){ - tok = cmp->tokens.data[cmp->tok_i]; + while(++cmp->tok_i < List_len(&cmp->tokens, Token)){ + tok = ((Token*)cmp->tokens.data)[cmp->tok_i]; switch(tok.type){ case TokenType_SingleLineComment: case TokenType_MultiLineComment: @@ -205,7 +201,7 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){ arg.value.i = atoll(processed_str.data); } free(processed_str.data); - List_Argument_push(&operPtr->args, arg); + List_push(&operPtr->args, Argument, arg); break; case TokenType_Name: tok_str = Compiler_constructTokenStr(cmp, tok); @@ -217,23 +213,23 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){ arg.type = ArgumentType_VarDataName; arg.value.data_name = tok_str; } - List_Argument_push(&operPtr->args, arg); + List_push(&operPtr->args, Argument, arg); break; case TokenType_NamedDataPointer: tok_str = Compiler_constructTokenStr(cmp, tok); tok_str.data++; - tok_str.len--; + tok_str.size--; arg.type = ArgumentType_ConstDataPointer; arg.value.data_name = tok_str; - List_Argument_push(&operPtr->args, arg); + List_push(&operPtr->args, Argument, arg); break; case TokenType_NamedDataSize: tok_str = Compiler_constructTokenStr(cmp, tok); tok_str.data++; - tok_str.len--; + tok_str.size--; arg.type = ArgumentType_ConstDataSize; arg.value.data_name = tok_str; - List_Argument_push(&operPtr->args, arg); + List_push(&operPtr->args, Argument, arg); break; } } @@ -245,8 +241,8 @@ bool Compiler_parse(Compiler* cmp){ Token tok; Section* sec = NULL; - while(cmp->tok_i < cmp->tokens.len){ - tok = cmp->tokens.data[cmp->tok_i]; + while(cmp->tok_i < List_len(&cmp->tokens, Token)){ + tok = ((Token*)cmp->tokens.data)[cmp->tok_i]; switch(tok.type){ case TokenType_Unset: returnError(Error_TokenUnset); @@ -256,7 +252,7 @@ bool Compiler_parse(Compiler* cmp){ break; case TokenType_Label: // create new section - sec = List_Section_expand(&cmp->ast.sections, 1); + sec = List_expand_size(&cmp->ast.sections, sizeof(Section)); Section_init(sec, Compiler_constructTokenStr(cmp, tok)); break; case TokenType_Instruction: @@ -265,12 +261,14 @@ bool Compiler_parse(Compiler* cmp){ str instr_name = Compiler_constructTokenStr(cmp, tok); // data definition starts with const if(str_startsWith(instr_name, STR("const"))){ - DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data, 1); + DataDefinition* dataDefPtr = List_expand_size( + &sec->data_definitions_list, sizeof(DataDefinition)); memset(dataDefPtr, 0, sizeof(DataDefinition)); parseDataDefinition(cmp, instr_name, dataDefPtr); } else { - Operation* operPtr = List_Operation_expand(&sec->code, 1); + Operation* operPtr = List_expand_size( + &sec->operations_list, sizeof(Operation)); memset(operPtr, 0, sizeof(Operation)); parseOperation(cmp, instr_name, operPtr); } diff --git a/src/compiler/Token.c b/src/compiler/Token.c index 502262d..04768fc 100644 --- a/src/compiler/Token.c +++ b/src/compiler/Token.c @@ -1,8 +1,6 @@ #include "Token.h" -List_define(Token); - -static str _TokenType_str[] = { +static Array(str) _TokenType_str_array = ARRAY(str, { STR("Unset"), STR("SingleLineComment"), STR("MultiLineComment"), @@ -15,10 +13,10 @@ static str _TokenType_str[] = { STR("NamedDataPointer"), STR("NamedDataSize"), STR("OperationEnd"), -}; +}); str TokenType_toString(TokenType t){ - if(t >= ARRAY_SIZE(_TokenType_str)) + if(t >= Array_len(&_TokenType_str_array, str)) return STR("!!TokenType INDEX_ERROR!!"); - return _TokenType_str[t]; + return ((str*)_TokenType_str_array.data)[t]; } diff --git a/src/compiler/Token.h b/src/compiler/Token.h index 3277ef3..964c138 100644 --- a/src/compiler/Token.h +++ b/src/compiler/Token.h @@ -1,7 +1,7 @@ #pragma once -#include "../std.h" -#include "../string/str.h" -#include "../collections/List.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" +#include "tlibc/collections/List.h" typedef enum TokenType { TokenType_Unset, // initial value @@ -26,6 +26,4 @@ typedef struct Token { TokenType type : 8; // type of token (8 bits) } Token; -List_declare(Token); - #define Token_construct(TYPE, BEGIN, LEN) ((Token){ .type = TYPE, .begin = BEGIN, .length = LEN }) diff --git a/src/cstr.c b/src/cstr.c deleted file mode 100644 index 0552230..0000000 --- a/src/cstr.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "std.h" - -char* _strcat_malloc(size_t n, cstr str0, ...){ - va_list argv; - va_start(argv, str0); - char* heap_ptr = _vstrcat_malloc(n, str0, argv); - va_end(argv); - return heap_ptr; -} - -char* _vstrcat_malloc(size_t n, cstr str0, va_list argv){ - size_t str0_len = strlen(str0); - size_t total_len = str0_len; - cstr* const parts = malloc(sizeof(cstr) * n); - size_t* const part_lengths = malloc(sizeof(size_t) * n); - for(size_t i = 0; i < n; i++){ - cstr part = va_arg(argv, cstr); - size_t length = strlen(part); - parts[i] = part; - part_lengths[i] = length; - total_len += length; - } - char* const buf = malloc(total_len + 1); - memcpy(buf, str0, str0_len); - char* walking_ptr = buf + str0_len; - for(size_t i = 0; i < n; i++){ - memcpy(walking_ptr, parts[i], part_lengths[i]); - walking_ptr += part_lengths[i]; - } - buf[total_len] = '\0'; - free(parts); - free(part_lengths); - return buf; -} - -char* NULLABLE(sprintf_malloc)(size_t buffer_size, cstr format, ...){ - va_list argv; - va_start(argv, format); - char* NULLABLE(heap_ptr) = vsprintf_malloc(buffer_size, format, argv); - va_end(argv); - return heap_ptr; -} - -char* NULLABLE(vsprintf_malloc)(size_t buffer_size, cstr format, va_list argv){ - char* buf = malloc(buffer_size); - int r = vsprintf(buf, format, argv); - if(r < 0){ - free(buf); - return NULL; - } - return buf; -} diff --git a/src/instructions/instructions.c b/src/instructions/instructions.c index f299dc5..b05effb 100644 --- a/src/instructions/instructions.c +++ b/src/instructions/instructions.c @@ -1,5 +1,5 @@ #include "instructions.h" -#include "../collections/HashMap.h" +#include "tlibc/collections/HashMap.h" i32 NOP_impl(VM* vm); i32 EXIT_impl(VM* vm); @@ -31,8 +31,7 @@ i32 JNZ_impl(VM* vm); i32 JZ_impl(VM* vm); -Array_declare(Instruction); -static const Array_Instruction instructions_array = ARRAY(Instruction, { +static const Array(Instruction) instructions_array = ARRAY(Instruction, { Instruction_construct(NOP), Instruction_construct(EXIT), Instruction_construct(SYS), @@ -64,35 +63,39 @@ static const Array_Instruction instructions_array = ARRAY(Instruction, { }); const Instruction* Instruction_getByOpcode(Opcode opcode){ - if(opcode >= instructions_array.len) + if(opcode >= Array_len(&instructions_array, Instruction)) return NULL; - return instructions_array.data + opcode; + return (Instruction*)instructions_array.data + opcode; } -HashMap_declare(Instruction); -HashMap_define(Instruction, HashMap_DESTROY_VALUE_FUNC_NULL); -static HashMap_Instruction* instructions_map = NULL; +static HashMap(Opcode)* opcode_map = NULL; + +static void _opcode_map_init(){ + opcode_map = malloc(sizeof(*opcode_map)); + HashMap_create(opcode_map, Opcode, NULL); + for(u32 i = 0; i < Array_len(&instructions_array, Instruction); i++){ + Instruction* instr_ptr = (Instruction*)instructions_array.data + i; + HashMap_tryPush(opcode_map, instr_ptr->name, &instr_ptr->opcode); + } +} const Instruction* Instruction_getByName(str name){ - if(instructions_map == NULL){ - instructions_map = malloc(sizeof(HashMap_Instruction)); - HashMap_Instruction_alloc(instructions_map); - for(u32 i = 0; i < instructions_array.len; i++){ - HashMap_Instruction_tryPush(instructions_map, instructions_array.data[i].name, instructions_array.data[i]); - } - } + if(opcode_map == NULL) + _opcode_map_init(); str name_upper = str_toUpper(name); - Instruction* iptr = HashMap_Instruction_tryGetPtr(instructions_map, name_upper); + Opcode* op_ptr = HashMap_tryGetPtr(opcode_map, name_upper); free(name_upper.data); - return iptr; + if(op_ptr == NULL) + return NULL; + return Instruction_getByOpcode(*op_ptr); } void Instruction_freeSearchStructs(){ - if(instructions_map != NULL){ - HashMap_Instruction_free(instructions_map); - free(instructions_map); + if(opcode_map != NULL){ + HashMap_destroy(opcode_map); + free(opcode_map); } -} \ No newline at end of file +} diff --git a/src/instructions/registers.c b/src/instructions/registers.c index 95a2bf8..35326b2 100644 --- a/src/instructions/registers.c +++ b/src/instructions/registers.c @@ -60,15 +60,15 @@ str RegisterCode_toString(RegisterCode code){ break; case 4: buf_str.data += 1; - buf_str.len -= 1; + buf_str.size -= 1; break; case 7: buf_str.data[0] = 'l'; - buf_str.len -= 1; + buf_str.size -= 1; break; case 8: buf_str.data[0] = 'h'; - buf_str.len -= 1; + buf_str.size -= 1; break; } diff --git a/src/instructions/registers.h b/src/instructions/registers.h index 45bb2fd..021b9bd 100644 --- a/src/instructions/registers.h +++ b/src/instructions/registers.h @@ -1,6 +1,6 @@ #pragma once -#include "../std.h" -#include "../string/str.h" +#include "tlibc/std.h" +#include "tlibc/string/str.h" typedef enum RegisterCode { RegisterCode_Unset = 0, diff --git a/src/main.c b/src/main.c index 648ab03..ef177c0 100644 --- a/src/main.c +++ b/src/main.c @@ -1,9 +1,8 @@ #include "VM/VM.h" #include "instructions/instructions.h" -#include "collections/List.h" +#include "tlibc/collections/List.h" #include "compiler/Compiler.h" #include "VM/Display/Display.h" -#include #define arg_is(STR) (strcmp(argv[argi], STR) == 0) diff --git a/src/std.h b/src/std.h deleted file mode 100644 index 03fbc55..0000000 --- a/src/std.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef int8_t i8; -typedef uint8_t u8; -typedef int16_t i16; -typedef uint16_t u16; -typedef int32_t i32; -typedef uint32_t u32; -typedef int64_t i64; -typedef uint64_t u64; -typedef float f32; -typedef double f64; - -typedef const char* cstr; - -#if defined(_WIN64) || defined(_WIN32) - #define IFWIN(YES, NO) YES -#else - #define IFWIN(YES, NO) NO -#endif - -#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0])) -#define ALIGN_TO(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) - -#define __count_args( \ - a0, a1, a2, a3, a4, a5, a6, a7 , a8, a9, a10,a11,a12,a13,a14,a15, \ - a16,a17,a18,a19,a20,a21,a22,a23, a24,a25,a26,a27,a28,a29,a30,a31, \ - a32,a33,a34,a35,a36,a37,a38,a39, a40,a41,a42,a43,a44,a45,a46,a47, \ - a48,a49,a50,a51,a52,a53,a54,a55, a56,a57,a58,a59,a60,a61,a62,a63, \ - a64,...) a64 -// Macro for counting variadic arguments (max 64) -// (see usage in kprint.h) -#define count_args(ARGS...) __count_args(ARGS, \ - 64,63,62,61,60,59,58,57, 56,55,54,53,52,51,50,49, \ - 48,47,46,45,44,43,42,41, 40,39,38,37,36,35,34,33, \ - 32,31,30,29,28,27,26,25, 24,23,22,21,20,19,18,17, \ - 16,15,14,13,12,11,10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0) - -#define printfe(FORMAT, ...) fprintf(stderr, FORMAT ,##__VA_ARGS__) - -/// @warning pointer can be null -#define NULLABLE(NAME) NAME - -#define strcat_malloc(STR0, ...) _strcat_malloc(count_args(__VA_ARGS__), STR0, __VA_ARGS__) -char* _strcat_malloc(size_t n, cstr str0, ...); -char* _vstrcat_malloc(size_t n, cstr str0, va_list argv); - -char* NULLABLE(sprintf_malloc)(size_t buffer_size, cstr format, ...) __attribute__((__format__(__printf__, 2, 3))); -char* NULLABLE(vsprintf_malloc)(size_t buffer_size, cstr format, va_list argv); - -static inline bool isAlphabeticalLower(char c) { return 'a' <= c && c <= 'z'; } -static inline bool isAlphabeticalUpper(char c) { return 'A' <= c && c <= 'Z'; } -static inline bool isDigit(char c) { return '0' <= c && c <= '9'; } diff --git a/src/string/StringBuilder.c b/src/string/StringBuilder.c deleted file mode 100644 index 5f27fd0..0000000 --- a/src/string/StringBuilder.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "StringBuilder.h" - -void StringBuilder_free(StringBuilder* b){ - free(b->buffer.data); - b->buffer = List_u8_construct(NULL, 0, 0); -} - -str StringBuilder_getStr(StringBuilder* b){ - List_u8_push(&b->buffer, '\0'); - str result = str_construct((char*)b->buffer.data, b->buffer.len - 1, true); - return result; -} - -void StringBuilder_removeFromEnd(StringBuilder* b, u32 count){ - if(count < b->buffer.len){ - b->buffer.len -= count; - } - else{ - b->buffer.len = 0; - } -} - - -void StringBuilder_append_char(StringBuilder* b, char c){ - List_u8_push(&b->buffer, c); -} - - -void StringBuilder_append_string(StringBuilder* b, str s){ - List_u8_pushMany(&b->buffer, (u8*)s.data, s.len); -} - -void StringBuilder_append_cstr(StringBuilder* b, char* s){ - StringBuilder_append_string(b, str_construct(s, strlen(s), true)); -} - -void StringBuilder_append_i64(StringBuilder* b, i64 n){ - char buf[32]; - sprintf(buf, IFWIN("%lli", "%li"), n); - StringBuilder_append_cstr(b, buf); -} - -void StringBuilder_append_u64(StringBuilder* b, u64 n){ - char buf[32]; - sprintf(buf, IFWIN("%llu", "%lu"), n); - StringBuilder_append_cstr(b, buf); -} - -void StringBuilder_append_f64(StringBuilder* b, f64 n){ - char buf[32]; - sprintf(buf, "%lf", n); - StringBuilder_append_cstr(b, buf); -} diff --git a/src/string/StringBuilder.h b/src/string/StringBuilder.h deleted file mode 100644 index c91d6aa..0000000 --- a/src/string/StringBuilder.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "../collections/List.h" -#include "str.h" - -typedef struct StringBuilder { - List_u8 buffer; -} StringBuilder; - -static inline StringBuilder StringBuilder_alloc(u32 initial_size) { - return (StringBuilder){ .buffer = List_u8_alloc(initial_size) }; -} -void StringBuilder_free(StringBuilder* b); - -/// @param count set to -1 to clear StringBuilder -void StringBuilder_removeFromEnd(StringBuilder* b, u32 count); -void StringBuilder_append_char(StringBuilder* b, char c); -void StringBuilder_append_cstr(StringBuilder* b, char* s); -void StringBuilder_append_string(StringBuilder* b, str s); -void StringBuilder_append_i64(StringBuilder* b, i64 a); -void StringBuilder_append_u64(StringBuilder* b, u64 a); -void StringBuilder_append_f64(StringBuilder* b, f64 a); - -// adds '\0' to the buffer and returns pointer to buffer content -str StringBuilder_getStr(StringBuilder* b); diff --git a/src/string/str.c b/src/string/str.c deleted file mode 100644 index 0d510cb..0000000 --- a/src/string/str.c +++ /dev/null @@ -1,125 +0,0 @@ -#include "str.h" - -str str_copy(str src){ - if(src.data == NULL || src.len == 0) - return src; - - str nstr = str_construct((char*)malloc(src.len + 1), src.len, true); - memcpy(nstr.data, src.data, src.len); - nstr.data[nstr.len] = '\0'; - return nstr; -} - -bool str_equals(str s0, str s1){ - if(s0.len != s1.len) - return false; - - for(u32 i = 0; i < s0.len; i++) - if(s0.data[i] != s1.data[i]) - return false; - - return true; -} - -str str_reverse(str s){ - if(s.data == NULL || s.len == 0) - return s; - - str r = str_construct(malloc(s.len), s.len, s.isZeroTerminated); - for(u32 i = 0; i < s.len; i++ ) - r.data[i] = s.data[s.len - i - 1]; - return r; -} - -i32 str_seek(str src, str fragment, u32 startIndex){ - if(src.len == 0 || fragment.len == 0) - return -1; - - for(u32 i = startIndex; i < src.len - fragment.len + 1; i++){ - for(u32 j = 0;; j++){ - if(j == fragment.len) - return i; - if(src.data[i + j] != fragment.data[j]) - break; - } - } - return -1; -} - -i32 str_seekReverse(str src, str fragment, u32 startIndex){ - if(src.len == 0 || fragment.len == 0) - return -1; - - if(startIndex > src.len - 1) - startIndex = src.len - 1; - for(u32 i = startIndex; i >= fragment.len - 1; i--){ - for(u32 j = 0;; j++){ - if(j == fragment.len) - return i - j + 1; - if(src.data[i - j] != fragment.data[fragment.len - 1 - j]) - break; - } - } - return -1; -} - -i32 str_seekChar(str src, char c, u32 startIndex){ - for(u32 i = startIndex; i < src.len; i++){ - if(src.data[i] == c) - return i; - } - return -1; -} - -i32 str_seekCharReverse(str src, char c, u32 startIndex){ - if(startIndex > src.len - 1) - startIndex = src.len - 1; - for(u32 i = startIndex; i != (u32)-1; i--){ - if(src.data[i] == c) - return i; - } - return -1; -} - -bool str_startsWith(str src, str fragment){ - if(src.len < fragment.len) - return false; - - src.len = fragment.len; - return str_equals(src, fragment); -} - -bool str_endsWith(str src, str fragment){ - if(src.len < fragment.len) - return false; - - src.data = (char*)(src.data + src.len - fragment.len); - src.len = fragment.len; - return str_equals(src, fragment); -} - -u32 str_hash32(str s){ - u8* ubuf = (u8*)s.data; - u32 hash=0; - for (u32 i = 0; i < s.len; i++) - hash = (hash<<6) + (hash<<16) - hash + ubuf[i]; - return hash; -} - -str str_toUpper(str src){ - str r = str_copy(src); - for (u32 i = 0; i < r.len; i++){ - if(isAlphabeticalLower(r.data[i])) - r.data[i] = r.data[i] - 'a' + 'A'; - } - return r; -} - -str str_toLower(str src){ - str r = str_copy(src); - for (u32 i = 0; i < r.len; i++){ - if(isAlphabeticalUpper(r.data[i])) - r.data[i] = r.data[i] - 'A' + 'a'; - } - return r; -} diff --git a/src/string/str.h b/src/string/str.h deleted file mode 100644 index 399bad5..0000000 --- a/src/string/str.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "../std.h" - -typedef struct str { - char* data; - u32 len; - bool isZeroTerminated; -} str; - -/// creates str from a string literal -#define STR(LITERAL) str_construct(LITERAL, ARRAY_SIZE(LITERAL) - 1, true) - -#define str_construct(DATA, LEN, ZERO_TERMINATED) ((str){ .data = DATA, .len = LEN, .isZeroTerminated = ZERO_TERMINATED }) - -static const str str_null = str_construct(NULL, 0, 0); - -/// copies src content to new string and adds \0 at the end -str str_copy(str src); - -/// compares two strings, NullPtr-friendly -bool str_equals(str str0, str str1); - -/// allocates new string which is reversed variant of -str str_reverse(str s); - -i32 str_seek(str src, str fragment, u32 startIndex); -i32 str_seekReverse(str src, str fragment, u32 startIndex); - -i32 str_seekChar(str src, char c, u32 startIndex); -i32 str_seekCharReverse(str src, char c, u32 startIndex); - -bool str_startsWith(str src, str fragment); -bool str_endsWith(str src, str fragment); - -/// @brief calculates string hash using sdbm32 algorythm (something like lightweight crc32) -/// @return non-cryptografic hash of the string -u32 str_hash32(str s); - -str str_toUpper(str src); -str str_toLower(str src);