diff --git a/build_file.cpp b/build_file.cpp index b44bb94..54f0ff6 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -1,25 +1,59 @@ #include "build_tool/library.cpp" -void Compile(Strs cc, Str files); +void Compile(S8_String cc, S8_String files); int ReturnValue = 0; int Main() { - Strs cc = CMDLine.get("cc"_s, ON_WINDOWS("cl"_s) ON_MAC("clang"_s) ON_LINUX("gcc"_s)); + S8_String cc = CMDLine.get("cc", ON_WINDOWS("cl") ON_MAC("clang") ON_LINUX("gcc")); Compile(cc, "../tests/test_main.cpp"); Compile(cc, "../tests/test_filesystem.c"); return ReturnValue; } -void Compile(Strs cc, Str file) { +void Compile(S8_String cc, S8_String file) { int result = 0; - Str exe = FilenameWithoutExt(file); - bool is_cpp = S8_EndsWith(file, ".cpp"); - if (cc == "gcc" && is_cpp) result = OS_SystemF("g++ -o %.*s.exe %.*s -g -Wno-write-strings -fsanitize=address", S8_Expand(exe), S8_Expand(file)); - else if (cc == "gcc" && !is_cpp) result = OS_SystemF("g -o %.*s.exe %.*s -g -Wno-write-strings -fsanitize=address", S8_Expand(exe), S8_Expand(file)); - else if (cc == "clang" && is_cpp) result = OS_SystemF("clang++ -std=c++11 -o %.*s.exe %.*s -fdiagnostics-absolute-paths -g -Wno-writable-strings -fsanitize=address", S8_Expand(exe), S8_Expand(file)); - else if (cc == "clang" && !is_cpp) result = OS_SystemF("clang -o %.*s.exe %.*s -fdiagnostics-absolute-paths -g -Wno-writable-strings -fsanitize=address", S8_Expand(exe), S8_Expand(file)); - else result = OS_SystemF("cl -Fe:%.*s.exe %.*s -FC -Zi -WX -W3 -wd4200 -diagnostics:column -nologo -D_CRT_SECURE_NO_WARNINGS -fsanitize=address -RTC1", S8_Expand(exe), S8_Expand(file)); + + S8_String name_no_ext = S8_GetNameNoExt(file); + S8_String exe = Fmt("%.*s.exe", S8_Expand(name_no_ext)); + + if (cc == "cl") { + Array flags = Split("/MP /Zi -D_CRT_SECURE_NO_WARNINGS /GF /Gm- /Oi"); + flags += Split("/FC /WX /W3 /wd4200 /diagnostics:column /nologo"); + flags += Split("/GR- /EHa-"); + flags += Split("-fsanitize=address -RTC1"); + + Array link = Split("/link /incremental:no"); + S8_String name = Fmt("/Fe:%.*s", S8_Expand(exe)); + + result = Run(cc + file + name + flags + link); + } + else if (cc == "clang") { + Array flags = Split("-g -Wno-write-strings -fdiagnostics-absolute-paths"); + flags += "-fsanitize=address"; + + if (S8_EndsWith(file, ".cpp")) { + cc = "clang++"; + flags += "-std=c++11"; + } + + S8_String name = Fmt("-o %.*s", S8_Expand(exe)); + result = Run(cc + file + name + flags); + } + else { + IO_Assert(cc == "gcc"); + + Array flags = Split("-g -Wno-write-strings"); + flags += "-fsanitize=address"; + + if (S8_EndsWith(file, ".cpp")) { + cc = "g++"; + flags += "-std=c++11"; + } + + S8_String name = Fmt("-o %.*s", S8_Expand(exe)); + result = Run(cc + file + name + flags); + } if (result == 0) result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%.*s.exe", S8_Expand(exe)); else ReturnValue = result; diff --git a/build_tool/easy_strings.cpp b/build_tool/easy_strings.cpp new file mode 100644 index 0000000..43f8649 --- /dev/null +++ b/build_tool/easy_strings.cpp @@ -0,0 +1,100 @@ +S8_String Fmt(const char *str, ...) S8__PrintfFormat(1, 2); + +Array operator+(Array a, Array b) { + Array c = a.copy(*Perm); + c.add_array(b); + return c; +} + +Array operator+(Array a, S8_String b) { + Array c = a.copy(*Perm); + c.add(b); + return c; +} + +Array operator+(S8_String a, Array b) { + Array c = b.copy(*Perm); + c.insert(a, 0); + return c; +} + +Array operator+(S8_String a, S8_String b) { + Array c = {*Perm}; + c.add(a); + c.add(b); + return c; +} + +Array &operator+=(Array &a, Array b) { + a.add_array(b); + return a; +} + +Array &operator+=(Array &a, S8_String s) { + a.add(s); + return a; +} + +//@todo: split on any whitespace instead! +Array Split(char *str) { + S8_String s = S8_MakeFromChar(str); + S8_List list = S8_Split(Perm, s, S8_Lit(" "), 0); + + Array result = {*Perm}; + S8_For(it, list) result.add(it->string); + return result; +} + +S8_String Merge(Array list, S8_String separator = " "_s) { + int64_t char_count = 0; + For(list) char_count += it.len; + if (char_count == 0) return {}; + int64_t node_count = list.len; + + int64_t base_size = (char_count + 1); + int64_t sep_size = (node_count - 1) * separator.len; + int64_t size = base_size + sep_size; + char *buff = (char *)MA_PushSize(Perm, sizeof(char) * size); + S8_String string = S8_Make(buff, 0); + For(list) { + IO_Assert(string.len + it.len <= size); + MA_MemoryCopy(string.str + string.len, it.str, it.len); + string.len += it.len; + if (!list.is_last(it)) { + MA_MemoryCopy(string.str + string.len, separator.str, separator.len); + string.len += separator.len; + } + } + IO_Assert(string.len == size - 1); + string.str[size] = 0; + return string; +} + +S8_String Fmt(const char *str, ...) { + S8_FORMAT(Perm, str, str_fmt); + return str_fmt; +} + +bool CodeWasModified(S8_String str, S8_String artifact = {}) { + return SRC_WasModified(str, artifact); +} + +S8_String IfCodeWasModified(S8_String cfile, S8_String objfile) { + Array result = {}; + if (SRC_WasModified(cfile, objfile)) + return cfile; + return objfile; +} + +int Run(Array s) { + S8_String cmd = Merge(s); + return OS_SystemF("%.*s", S8_Expand(cmd)); +} + +Array ListDir(char *dir) { + Array result = {}; + for (OS_FileIter it = OS_IterateFiles(Perm, S8_MakeFromChar(dir)); OS_IsValid(it); OS_Advance(&it)) { + result.add(S8_Copy(Perm, it.absolute_path)); + } + return result; +} diff --git a/build_tool/library.cpp b/build_tool/library.cpp index f026af9..230afad 100644 --- a/build_tool/library.cpp +++ b/build_tool/library.cpp @@ -4,8 +4,7 @@ FLAGS = /MP /Zi /FC /WX /W3 /wd4200 /diagnostics:column /nologo -D_CRT_SE LINK = /link /incremental:no STD_OFF = /GR- /EHa- STD_ON = /EHsc -DEBUG = -Od -D_DEBUG -MDd -fsanitize=address -RTC1 -DEBUG_LINK = -NODEFAULTLIB:LIBCMT +DEBUG = -Od -D_DEBUG -fsanitize=address -RTC1 RELEASE = -O2 -MT -DNDEBUG -GL RELEASE_LINK = -opt:ref -opt:icf ----------------- CL.EXE ----------------- @@ -48,175 +47,18 @@ MA_Arena *Perm = &PernamentArena; Table CMDLine; #include "cache.cpp" +#include "easy_strings.cpp" -// -// -// +#ifndef BUILD_MAIN +int Main(); -using Str = S8_String; -struct Strs : Array { - Strs() = default; - Strs(char *str) { - *this = {}; - this->add(S8_MakeFromChar(str)); - } - Strs(char *a, char *b) { - *this = {}; - this->add(S8_MakeFromChar(a)); - this->add(S8_MakeFromChar(b)); - } - Strs(char *a, char *b, char *c) { - *this = {}; - this->add(S8_MakeFromChar(a)); - this->add(S8_MakeFromChar(b)); - this->add(S8_MakeFromChar(c)); - } - Strs(Str a) { - *this = {}; - this->add(a); - } - Strs(Array a) { MA_MemoryCopy(this, &a, sizeof(a)); } -}; - -bool operator==(Strs a, char *b) { - if (a.len != 1) return false; - bool result = a[0] == S8_MakeFromChar(b); - return result; -} - -bool operator==(Strs a, const char *b) { - if (a.len != 1) return false; - bool result = a[0] == S8_MakeFromChar((char *)b); - return result; -} - -Strs operator+(Strs a, Strs b) { - Strs c = {a.copy(*Perm)}; - c.add_array(b); - return c; -} - -Strs operator+(Strs a, Str b) { - Strs c = {a.copy(*Perm)}; - c.add(b); - return c; -} - -Strs operator+(Str a, Strs b) { - Strs c = {b.copy(*Perm)}; - c.add(a); - return c; -} - -Strs &operator+=(Strs &a, Strs b) { - a.add_array(b); - return a; -} - -Strs &operator+=(Strs &a, char *str) { - a.add(S8_MakeFromChar(str)); - return a; -} - -Strs &operator+=(Strs &a, Str s) { - a.add(s); - return a; -} - -Strs operator+(Strs a, char *b) { - Strs c = {a.copy(*Perm)}; - c.add(S8_MakeFromChar(b)); - return c; -} - -Strs operator+(char *a, Strs b) { - Strs c = {b.copy(*Perm)}; - c.add(S8_MakeFromChar(a)); - return c; -} - -Strs operator+(Str a, Str b) { - Strs c = {}; - c.add(a); - c.add(b); - return c; -} - -Strs operator+(Str a, char *b) { - return a + S8_MakeFromChar(b); -} - -//@todo: split on any whitespace instead! -Strs Split(char *str) { - Str s = S8_MakeFromChar(str); - S8_List list = S8_Split(Perm, s, S8_Lit(" "), 0); - - Strs result = {}; - S8_For(it, list) result.add(it->string); - return result; -} - -Str Merge(Strs list, Str separator = " "_s) { - int64_t char_count = 0; - For(list) char_count += it.len; - if (char_count == 0) return {}; - int64_t node_count = list.len; - - int64_t base_size = (char_count + 1); - int64_t sep_size = (node_count - 1) * separator.len; - int64_t size = base_size + sep_size; - char *buff = (char *)MA_PushSize(Perm, sizeof(char) * size); - Str string = S8_Make(buff, 0); - For(list) { - IO_Assert(string.len + it.len <= size); - MA_MemoryCopy(string.str + string.len, it.str, it.len); - string.len += it.len; - if (!list.is_last(it)) { - MA_MemoryCopy(string.str + string.len, separator.str, separator.len); - string.len += separator.len; - } - } - IO_Assert(string.len == size - 1); - string.str[size] = 0; - return string; -} - -S8_String FilenameWithoutExt(S8_String it) { return S8_SkipToLastSlash(S8_ChopLastPeriod(it)); } -bool CodeWasModified(char *str, char *artifact = 0) { return SRC_WasModified(S8_MakeFromChar(str), S8_MakeFromChar(artifact)); } -bool CodeWasModified(S8_String str, S8_String artifact = {}) { return SRC_WasModified(str, artifact); } -Strs IfCodeWasModified(char *cfile, char *objfile) { - Strs result = {}; - S8_String s = S8_MakeFromChar(cfile); - S8_String o = S8_MakeFromChar(objfile); - if (SRC_WasModified(s, o)) { - return cfile; - } - return objfile; -} -void MakeDir(char *str) { OS_MakeDir(S8_MakeFromChar(str)); } -void ChangeDir(char *str) { OS_SetWorkingDir(S8_MakeFromChar(str)); } -int Run(Strs s) { - Str cmd = Merge(s); - return OS_SystemF("%.*s", S8_Expand(cmd)); -} - -Strs ListDir(char *dir) { - Strs result = {}; - for (OS_FileIter it = OS_IterateFiles(Perm, S8_MakeFromChar(dir)); OS_IsValid(it); OS_Advance(&it)) { - result.add(S8_Copy(Perm, it.absolute_path)); - } - return result; -} - -void ReportError(S8_String it) { +void BUILD_ReportError(S8_String it) { IO_FatalErrorf("Invalid command line argument syntax! Expected a key value pair!\n" "Here is the wrong argument: %.*s\n" "Here is a good example: bld.exe profile=release platform=windows\n", S8_Expand(it)); } -#ifndef BUILD_MAIN -int Main(); int main(int argc, char **argv) { if (argc > 1) IO_Printf("Command line arguments:\n"); @@ -227,13 +69,13 @@ int main(int argc, char **argv) { if (S8_Seek(it, "="_s, 0, &idx)) { S8_String key = S8_GetPrefix(it, idx); S8_String value = S8_Skip(it, idx + 1); - if (key.len == 0) ReportError(it); - if (value.len == 0) ReportError(it); + if (key.len == 0) BUILD_ReportError(it); + if (value.len == 0) BUILD_ReportError(it); IO_Printf("[%d] %.*s = %.*s\n", i, S8_Expand(key), S8_Expand(value)); CMDLine.put(key, value); } - else ReportError(it); + else BUILD_ReportError(it); } SRC_InitCache(Perm, S8_Lit("build_file.cache")); diff --git a/build_tool/main.cpp b/build_tool/main.cpp index 711b8b4..741da19 100644 --- a/build_tool/main.cpp +++ b/build_tool/main.cpp @@ -49,7 +49,7 @@ int main(int argument_count, char **arguments) { result = OS_SystemF("cl %.*s -Fe:%.*s -WX -W3 -wd4200 -diagnostics:column -nologo -Zi", S8_Expand(build_file), S8_Expand(exe_name)); } else if (cc == "clang"_s) { - result = OS_SystemF("clang++ -std=c++11 -Wno-writable-strings %.*s -o %.*s -g", S8_Expand(build_file), S8_Expand(exe_name)); + result = OS_SystemF("clang++ -std=c++11 -fdiagnostics-absolute-paths -Wno-writable-strings %.*s -o %.*s -g", S8_Expand(build_file), S8_Expand(exe_name)); } else { IO_Assert(cc == "gcc"_s); diff --git a/standalone_libraries/string.h b/standalone_libraries/string.h index a622f07..4ab3887 100644 --- a/standalone_libraries/string.h +++ b/standalone_libraries/string.h @@ -36,12 +36,6 @@ struct S8_String { struct Iter { UTF8_Iter i; - Iter operator++(int) { - Iter ret = *this; - UTF8_Advance(&i); - return ret; - } - Iter &operator++() { UTF8_Advance(&i); return *this; @@ -67,6 +61,23 @@ struct S8_List { int64_t char_count; S8_Node *first; S8_Node *last; + +#if defined(__cplusplus) + struct Iter { + S8_Node *it; + + Iter &operator++() { + it = it->next; + return *this; + } + + friend bool operator!=(const Iter &a, const Iter &b) { return a.it != b.it; } + S8_String &operator*() { return it->string; } + }; + + Iter begin() { return {first}; } + Iter end() { return {0}; } +#endif }; typedef int S8_FindFlag; diff --git a/tests/test_main.cpp b/tests/test_main.cpp index e2440c0..83420f0 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -4,6 +4,7 @@ #include "test_arena.cpp" void TestClexer(); + int main() { TestSimpleInsertAndIntegrity(); TestStrings(); @@ -22,7 +23,7 @@ int main() { TestClexer(); - // Unicode iteration over codepoints + // Unicode iteration over codepoints using For { S8_String s = "mrówka"; @@ -35,6 +36,23 @@ int main() { } IO_Assert(found_two_byte); } + + // List iteration using For + { + MA_Scratch scratch; + S8_List list = {}; + S8_AddF(scratch, &list, "1"); + S8_AddF(scratch, &list, "2"); + S8_AddF(scratch, &list, "3"); + S8_AddF(scratch, &list, "4"); + S8_AddF(scratch, &list, "5"); + + int i = 0; + For(list) { + i += 1; + } + IO_Assert(i == 5); + } } #define CL_Allocator MA_Arena *