From 231c893c6b008e2a42635237305d386ee39f042b Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 17 Mar 2023 02:09:19 -0400 Subject: [PATCH] Rework of project implementation For include and multi-file support. I still need to debug it, Test will be adjusted as well; I want to get all the files not just zpl refactored using a powershell script. I dropped the idea of semantically identifiying macros. While it may be possible, I don't see the utility vs the regular idendentifier distinction. I want to keep the refactoring as simple as possible, where it just takes one pass to go through a file without any context to other files. So far the ignores behave as a good guard filter for unwanted refactors and the only true weak area was the includes (which should be aleviated with the coming support for it. --- Readme.md | 30 +- Test/bloat.refactored.hpp | 2 +- project/Bloat.cpp | 37 ++ project/IO.cpp | 159 +++++++ project/IO.hpp | 25 ++ project/Spec.cpp | 315 ++++++++++++++ project/Spec.hpp | 73 ++++ project/_Docs.md | 41 ++ project/bloat.hpp | 63 ++- project/refactor.cpp | 853 ++++++++++++++------------------------ refactor.10x | 63 +++ 11 files changed, 1074 insertions(+), 587 deletions(-) create mode 100644 project/Bloat.cpp create mode 100644 project/IO.cpp create mode 100644 project/IO.hpp create mode 100644 project/Spec.cpp create mode 100644 project/Spec.hpp create mode 100644 project/_Docs.md create mode 100644 refactor.10x diff --git a/Readme.md b/Readme.md index af0376c..f592b90 100644 --- a/Readme.md +++ b/Readme.md @@ -1,9 +1,10 @@ # refactor -A code identifier refactoring app. Intended for c/c++ like identifiers. +Refactor c/c++ files (and problably others) with ease. Parameters : +* `-num` : Used if more than one source file is provided (if used, number of destination files provided MUST MATCH). * `-src` : Source file to refactor * `-dst` : Destination file after the refactor (omit to use the same as source) * `-spec` : Specification containing rules to use for the refactor. @@ -11,18 +12,33 @@ Parameters : Syntax : * `not` Omit word or namespace. +* `include` Preprocessor include related identifiers. * `word` Fixed sized identifier. * `namespace` Variable sized identifiers, mainly intended to redefine c-namespace of an identifier. * `,` is used to delimit arguments to word or namespace. * `L-Value` is the signature to modify. * `R-Value` is the substitute ( only available if rule does not use `not` keyword ) +The only keyword here excluisve to c/c++ is the `include` as it does search specifically for `#include `. +However, the rest of the categorical keywords (word, namespace), can really be used for any langauge. + +There is no semantic awareness this is truely just a simple find and replace, but with some filters specifiable, and +words/namespaces only being restricted to the rules for C/C++ identifiers (alphanumeric or underscores only) + +The main benefit for using this over other stuff is its faster and more ergonomic for large refactors on libraries that +you may want to have automated in a script. + +There are other programs more robust for doing that sort of thing but I was not able to find something this simple. + +**Note** +* Building for debug provides some nice output with context on a per-line basis. +* Release will only show errors for asserts (that will kill the refactor early). +* If the refactor crashes, the files previously written to will retain their changes. +Make sure to have the code backed up on a VCS or in some other way. +* This was compiled using meson with ninja and clang on windows 11. The ZPL library used however should work fine on the other major os platforms and compiler venders. +* The scripts used for building and otherwise are in the scripts directory and are all in powershell (with exception to the meson.build). Techncially there should be a powershell package available on other platorms but worst case it should be pretty easily to port these scripts to w/e shell script you'd perfer. TODO: * Possibly come up with a better name. -* Cleanup memory usage (it hogs quite a bit for what it does..) -* Split lines of file and refactor it that way instead (better debug, problably negligable performance loss, worst case can have both depending on build type) -* Accept multiple files at once `-files` -* Add support for `macro` keyword (single out macro identifiers) -* Add support for `include` keyword (single out include definitions) -* Add support for auto-translating a namespace in a macro to a cpp namespace +* Test to see how much needs to be ported for other platforms (if at all) +* Provide binaries in the release page for github. (debug and release builds) diff --git a/Test/bloat.refactored.hpp b/Test/bloat.refactored.hpp index 3c390ea..ec79e74 100644 --- a/Test/bloat.refactored.hpp +++ b/Test/bloat.refactored.hpp @@ -85,7 +85,7 @@ namespace Memory void setup() { - arena_init_from_allocator( & Global_Arena, heap(), megabytes(10) ); + arena_init_from_allocator( & Global_Arena, heap(), megabytes(1) ); if ( Global_Arena.total_size == 0 ) { diff --git a/project/Bloat.cpp b/project/Bloat.cpp new file mode 100644 index 0000000..648d780 --- /dev/null +++ b/project/Bloat.cpp @@ -0,0 +1,37 @@ +#define BLOAT_IMPL +#include "bloat.hpp" + + + +namespace Memory +{ + static zpl_arena Global_Arena {}; + + void setup() + { + zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(2) ); + + if ( Global_Arena.total_size == 0 ) + { + zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" ); + } + } + + void resize( uw new_size ) + { + void* new_memory = zpl_resize( zpl_heap(), Global_Arena.physical_start, Global_Arena.total_size, new_size ); + + if ( new_memory == nullptr ) + { + fatal("Failed to resize global arena!"); + } + + Global_Arena.physical_start = new_memory; + Global_Arena.total_size = new_size; + } + + void cleanup() + { + zpl_arena_free( & Global_Arena); + } +} diff --git a/project/IO.cpp b/project/IO.cpp new file mode 100644 index 0000000..c0dc399 --- /dev/null +++ b/project/IO.cpp @@ -0,0 +1,159 @@ +#include "IO.hpp" + + +namespace IO +{ + using array_string = zpl_array( zpl_string ); + + namespace StaticData + { + array_string Sources = nullptr; + array_string Destinations = nullptr; + zpl_string Specification = nullptr; + + // Current source and destination index. + // Used to keep track of which file get_next_source or write refer to. + uw Current = 0; + char* Current_Content = nullptr; + uw Current_Size = 0; + uw Largest_Src_Size = 0; + + /* + Will persist throughout loading different file content. + Should hold a bit more than the largest source file's content, + As an array of lines. + */ + zpl_arena MemPerist; + + /* + Temporary memory held while procesisng files to get their content. + zpl_files are stored here + */ + // zpl_arena MemTransient; + } + using namespace StaticData; + + + void prepare() + { + const sw num_srcs = zpl_array_count( Sources ); + + // Determine the largest content size. + sw left = num_srcs; + zpl_string* path = Sources; + do + { + zpl_file src = {}; + zpl_file_error error = zpl_file_open( & src, *path ); + + if ( error != ZPL_FILE_ERROR_NONE ) + { + fatal("Could not open source file: %s", *path ); + } + + const sw fsize = zpl_file_size( & src ); + + if ( fsize > Largest_Src_Size ) + { + Largest_Src_Size = fsize; + } + + zpl_file_close( & src ); + } + while ( --left ); + + uw persist_size = ZPL_ARRAY_GROW_FORMULA( Largest_Src_Size ); + + zpl_arena_init_from_allocator( & MemPerist, zpl_heap(), persist_size ); + // zpl_arena_init_from_allocator( & MemTransient, zpl_heap(), Largest_Src_Size ); + } + + void cleanup() + { + zpl_arena_free( & MemPerist ); + // zpl_arena_free( & MemTransient ); + } + + Array_Line get_specification() + { + zpl_file file {}; + zpl_file_error error = zpl_file_open( & file, Specification); + + if ( error != ZPL_FILE_ERROR_NONE ) + { + fatal("Could not open the specification file: %s", Specification); + } + + sw fsize = scast( sw, zpl_file_size( & file ) ); + + if ( fsize <= 0 ) + { + fatal("No content in specificaiton to process"); + } + + char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & MemPerist), fsize + 1) ); + + zpl_file_read( & file, content, fsize); + zpl_file_close( & file ); + + content[fsize] = 0; + + Array_Line lines = zpl_str_split_lines( zpl_arena_allocator( & MemPerist ), content, false ); + return lines; + } + + Array_Line get_next_source() + { + // zpl_memset( MemTransient.physical_start, 0, MemTransient.total_allocated); + // MemTransient.total_allocated = 0; + // MemTransient.temp_count = 0; + + zpl_memset( MemPerist.physical_start, 0, MemPerist.total_allocated); + MemPerist.total_allocated = 0; + MemPerist.temp_count = 0; + + zpl_file file {}; + zpl_file_error error = zpl_file_open( & file, Specification); + + if ( error != ZPL_FILE_ERROR_NONE ) + { + fatal("Could not open the source file: %s", Sources[Current]); + } + + Current_Size = scast( sw, zpl_file_size( & file ) ); + + if ( Current_Size <= 0 ) + return nullptr; + + Current_Content = rcast( char* , zpl_alloc( zpl_arena_allocator( & MemPerist), Current_Size + 1) ); + + zpl_file_read( & file, Current_Content, Current_Size ); + zpl_file_close( & file ); + + Current_Content[Current_Size] = 0; + Current_Size++; + + Array_Line lines = zpl_str_split_lines( zpl_arena_allocator( & MemPerist), Current_Content, ' ' ); + return lines; + } + + void write( zpl_string refacotred ) + { + if ( refacotred == nullptr) + return; + + zpl_string dst = Destinations[Current]; + + zpl_file file_dest {}; + zpl_file_error error = zpl_file_create( & file_dest, dst ); + + if ( error != ZPL_FILE_ERROR_NONE ) + { + fatal( "Unable to open destination file: %s\n", dst ); + } + + zpl_file_write( & file_dest, refacotred, zpl_string_length(refacotred) ); + + zpl_file_close( & file_dest ); + } +} diff --git a/project/IO.hpp b/project/IO.hpp new file mode 100644 index 0000000..051a6a3 --- /dev/null +++ b/project/IO.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "bloat.hpp" + + +namespace IO +{ + ct uw Path_Size_Largest = zpl_kilobytes(1); + + // Preps the IO by loading all the files and checking to see what the largest size is. + // The file with the largest size is used to determine the size of the persistent memory. + void prepare(); + + // Frees the persistent and transient memory arenas. + void cleanup(); + + // Provides the content of the specification. + Array_Line get_specification(); + + // Provides the content of the next source, broken up as a series of lines. + Array_Line get_next_source(); + + // Writes the refactored content ot the current corresponding destination. + void write( zpl_string refactored ); +} diff --git a/project/Spec.cpp b/project/Spec.cpp new file mode 100644 index 0000000..6ef1d98 --- /dev/null +++ b/project/Spec.cpp @@ -0,0 +1,315 @@ +#include "Spec.hpp" + +#include "IO.hpp" + + + +namespace Spec +{ + ct uw Array_Reserve_Num = zpl_kilobytes(4); + ct uw Token_Max_Length = zpl_kilobytes(1); + + namespace StaticData + { + Array_Entry Ignore_Includes; + Array_Entry Ignore_Words; + Array_Entry Ignore_Regexes; + Array_Entry Ignore_Namespaces; + + Array_Entry Includes; + Array_Entry Words; + Array_Entry Regexes; + Array_Entry Namespaces; + + u32 Sig_Smallest = Token_Max_Length; + } + using namespace StaticData; + + void cleanup() + { + zpl_array_free( Ignore_Includes ); + zpl_array_free( Ignore_Words ); + zpl_array_free( Ignore_Namespaces ); + zpl_array_free( Includes ); + zpl_array_free( Words ); + zpl_array_free( Namespaces ); + } + + + // Helper function for process(). + forceinline + void find_next_token( zpl_string& token, char*& line, u32& length ) + { + zpl_string_clear( token ); + length = 0; + + while ( zpl_char_is_alphanumeric( line[length] ) || line[length] == '_' ) + { + length++; + } + + if ( length == 0 ) + { + fatal("Failed to find valid initial token"); + } + + token = zpl_string_append_length( token, line, length ); + line += length; + } + + void parse() + { + static zpl_string token = zpl_string_make_reserve( g_allocator, zpl_kilobytes(1)); + + static bool Done = false; + if (Done) + { + zpl_array_clear( Ignore_Includes ); + zpl_array_clear( Ignore_Words ); + zpl_array_clear( Ignore_Namespaces ); + zpl_array_clear( Includes ); + zpl_array_clear( Words ); + zpl_array_clear( Namespaces ); + } + else + { + Done = true; + + zpl_array_init_reserve( Ignore_Includes, zpl_heap(), Array_Reserve_Num ); + zpl_array_init_reserve( Ignore_Words, zpl_heap(), Array_Reserve_Num ); + zpl_array_init_reserve( Ignore_Namespaces, zpl_heap(), Array_Reserve_Num ); + zpl_array_init_reserve( Includes, zpl_heap(), Array_Reserve_Num ); + zpl_array_init_reserve( Words, zpl_heap(), Array_Reserve_Num ); + zpl_array_init_reserve( Namespaces, zpl_heap(), Array_Reserve_Num ); + } + + Array_Line lines = IO::get_specification(); + + sw left = zpl_array_count( lines ); + + if ( left == 0 ) + { + fatal("Spec::parse: lines array imporoperly setup"); + } + + // Skip the first line as its the version number and we only support __VERSION 1. + left--; + lines++; + + char token[ Token_Max_Length ]; + + do + { + char* line = * lines; + + // Ignore line if its a comment + if ( line[0] == '/' && line[1] == '/') + { + lines++; + continue; + } + + // Remove indent + { + while ( zpl_char_is_space( line[0] ) ) + line++; + + if ( line[0] == '\0' ) + { + lines++; + continue; + } + } + + u32 length = 0; + + // Find a valid token + find_next_token( token, line, length ); + + Tok type = Tok::Num_Tok; + bool ignore = false; + Entry entry {}; + + // Will be reguarded as an ignore. + if ( is_tok( Tok::Not, token, length )) + { + ignore = true; + + while ( zpl_char_is_space( line[0] ) ) + line++; + + if ( line[0] == '\0' ) + { + lines++; + continue; + } + + // Find the category token + find_next_token( token, line, length ); + } + + if ( is_tok( Tok::Word, token, length ) ) + { + type = Tok::Word; + } + else if ( is_tok( Tok::Namespace, token, length ) ) + { + type = Tok::Namespace; + } + else if ( is_tok( Tok::Include, token, length )) + { + type = Tok::Include; + } + else + { + log_fmt( "Sec::Parse - Unsupported keyword: %s on line: %d", token, zpl_array_count(lines) - left ); + lines++; + continue; + } + + // Find the first argument + while ( zpl_char_is_space( line[0] ) ) + line++; + + if ( line[0] == '\0' ) + { + lines++; + continue; + } + + find_next_token( token, line, length ); + + // First argument is signature. + entry.Sig = zpl_string_make_length( g_allocator, token, length ); + + if ( length < StaticData::Sig_Smallest ) + StaticData::Sig_Smallest = length; + + if ( line[0] == '\0' || ignore ) + { + switch ( type ) + { + case Tok::Word: + if ( ignore) + zpl_array_append( Ignore_Words, entry ); + + else + zpl_array_append( Words, entry ); + break; + + case Tok::Namespace: + if ( ignore) + zpl_array_append( Ignore_Namespaces, entry ); + + else + zpl_array_append( Namespaces, entry ); + break; + + case Tok::Include: + if ( ignore) + zpl_array_append( Ignore_Includes, entry ); + + else + zpl_array_append( Includes, entry ); + break; + } + + lines++; + continue; + } + + // Look for second argument indicator + { + bool bSkip = false; + + while ( line[0] != ',' ) + { + if ( line[0] == '\0' ) + { + switch ( type ) + { + case Tok::Word: + zpl_array_append( Words, entry ); + break; + + case Tok::Namespace: + zpl_array_append( Namespaces, entry ); + break; + + case Tok::Include: + zpl_array_append( Includes, entry ); + break; + } + + bSkip = true; + break; + } + + line++; + } + + if ( bSkip ) + { + lines++; + continue; + } + } + + // Eat the argument delimiter. + line++; + + // Remove spacing + { + bool bSkip = true; + + while ( zpl_char_is_space( line[0] ) ) + line++; + + if ( line[0] == '\0' ) + { + switch ( type ) + { + case Tok::Word: + zpl_array_append( Words, entry ); + break; + + case Tok::Namespace: + zpl_array_append( Namespaces, entry ); + break; + + case Tok::Include: + zpl_array_append( Includes, entry ); + break; + } + + lines++; + continue; + } + } + + find_next_token( token, line, length ); + + // Second argument is substitute. + entry.Sub = zpl_string_make_length( g_allocator, token, length ); + + switch ( type ) + { + case Tok::Word: + zpl_array_append( Words, entry ); + lines++; + continue; + + case Tok::Namespace: + zpl_array_append( Namespaces, entry ); + lines++; + continue; + + case Tok::Include: + zpl_array_append( Includes, entry ); + lines++; + continue; + } + } + while ( --left ); + } +} diff --git a/project/Spec.hpp b/project/Spec.hpp new file mode 100644 index 0000000..c3e158d --- /dev/null +++ b/project/Spec.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "Bloat.hpp" + + +namespace Spec +{ + enum Tok + { + Not, + Include, + Namespace, + Word, + + Num_Tok + }; + + forceinline + char const* str_tok( Tok tok ) + { + static + char const* tok_to_str[ Tok::Num_Tok ] = + { + "not", + "include", + "namespace", + "word", + }; + + return tok_to_str[ tok ]; + } + + forceinline + char strlen_tok( Tok tok ) + { + static + const u8 tok_to_len[ Tok::Num_Tok ] = + { + 3, + 7, + 9, + 4, + }; + + return tok_to_len[ tok ]; + } + + forceinline + bool is_tok( Tok tok, zpl_string str, u32 length ) + { + char const* tok_str = str_tok(tok); + const u8 tok_len = strlen_tok(tok); + + if ( tok_len != length) + return false; + + s32 result = zpl_strncmp( tok_str, str, tok_len ); + + return result == 0; + } + + struct Entry + { + zpl_string Sig = nullptr; // Signature + zpl_string Sub = nullptr; // Substitute + }; + + using Array_Entry = zpl_array( Entry ); + + void cleanup(); + + // Extract the specificication from the provided file. + void parse(); +} diff --git a/project/_Docs.md b/project/_Docs.md new file mode 100644 index 0000000..dc7194a --- /dev/null +++ b/project/_Docs.md @@ -0,0 +1,41 @@ +# Documentation + +The current implementation is divided into 4 parts: + +* Bloat : General library provider. +* IO : File I/O processing. +* Spec : Specification parsing. +* Refactor : Entrypoint, argument parsing, and refactoring process. + +The files are setup to compile as one unit. As such the source files for Bloat, IO, and Spec are located within `refactor.cpp`. + +Bloat contains some aliasing of some C++ keywords and does not use the standard library. Instead a library called ZPL is used (Single header replacement). + +The program has pretty much no optimizations made to it, its just regular loops with no threading. +Just tried to keep the memory at reasonable size of what it does. + +The program execution is pretty much outlined quite clearly in `int main()`. + +1. Setup initial reserve of global memory in an arena. +2. Parse the arguments provided. +3. Prepare IO's memory for retreviing content. +4. Reserve memory for the refactor buffer. +5. Parse the specification file +6. Iterate through all provided files to refactor and write the refactored content to the specificed destintation files. +7. Cleanup all reserves of memory`*` + + +`*` This technically can be skipped on windows, may be worth doing to reduce latency of process shutdown. + +There are constraints of specific sizes of variables; + +* `Path_Size_Largest` : Longest path size is set to 1 KB of characters. +* `Token_Max_Length` : Set to 1 KB characters as well. +* `Array_Reserve_Num` : Is set to 4 KB. +* Initial Global arena size : Set to 2 megabytes. + +The `Path_Size_Largest` and `Token_Max_Length` are compile-time constraints that the runtime will not have a fallback for, if 1 KB is not enough it will need to be changed for your use case. + +`Array_Reserve_Num` is used to dictate the assumed amount of tokens will be held in total for any of spec's arrays holding ignores and refactor entries. If any of the array's exceed 4 KB they will grow trigigng a resize which will bog down the speed of the refactor. Adjust if you think you can increase or lower for use case. + +Initial Global arena size is a finicy thing, its most likely going to be custom allocator at one point so that it can handle growing properly, right now its just grows if the amount of memory file paths will need for sources is greater than 1 MB. diff --git a/project/bloat.hpp b/project/bloat.hpp index 2be7815..1cfd188 100644 --- a/project/bloat.hpp +++ b/project/bloat.hpp @@ -1,13 +1,13 @@ /* BLOAT. - - ZPL requires ZPL_IMPLEMENTATION whereever this library is included. - - This file assumes it will be included in one compilation unit. */ #pragma once +#ifdef BLOAT_IMPL +# define ZPL_IMPLEMEntATION +#endif + #if __clang__ # pragma clang diagnostic ignored "-Wunused-const-variable" # pragma clang diagnostic ignored "-Wswitch" @@ -33,14 +33,13 @@ // # define ZPL_MODULE_REGEX // # define ZPL_MODULE_EVENT // # define ZPL_MODULE_DLL -# define ZPL_MODULE_OPTS +# define ZPL_MODULE_OPTS // # define ZPL_MODULE_PROCESS // # define ZPL_MODULE_MAT // # define ZPL_MODULE_THREADING // # define ZPL_MODULE_JOBS // # define ZPL_MODULE_PARSER #include "zpl.h" -// } #if __clang__ # pragma clang diagnostic pop @@ -59,16 +58,16 @@ #define rcast( Type_, Value_ ) reinterpret_cast< Type_ >( Value_ ) #define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) ) -#define do_once() \ -do \ -{ \ - static \ - bool Done = true; \ - if ( Done ) \ - return; \ - Done = false; \ -} \ -while(0) \ +#define do_once() \ +do \ +{ \ + static \ + bool Done = false; \ + if ( Done ) \ + return; \ + Done = true; \ +} \ +while(0) \ using s8 = zpl_i8; @@ -81,39 +80,34 @@ using f64 = zpl_f64; using uw = zpl_usize; using sw = zpl_isize; +using Line = char*; +using Array_Line = zpl_array( Line ); + ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED"; namespace Memory { - zpl_arena Global_Arena {}; + extern zpl_arena Global_Arena; #define g_allocator zpl_arena_allocator( & Memory::Global_Arena) - void setup() - { - zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) ); - - if ( Global_Arena.total_size == 0 ) - { - zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" ); - } - } - - void cleanup() - { - zpl_arena_free( & Global_Arena); - } + void setup(); + void resize( uw new_size ); + void cleanup(); } - sw log_fmt(char const *fmt, ...) - { +inline +sw log_fmt(char const *fmt, ...) +{ #if Build_Debug sw res; va_list va; + va_start(va, fmt); res = zpl_printf_va(fmt, va); va_end(va); + return res; #else @@ -121,6 +115,7 @@ namespace Memory #endif } +inline void fatal(char const *fmt, ...) { zpl_local_persist zpl_thread_local @@ -139,6 +134,6 @@ void fatal(char const *fmt, ...) zpl_printf_err_va( fmt, va); va_end(va); - exit(1); + zpl_exit(1); #endif } diff --git a/project/refactor.cpp b/project/refactor.cpp index 5a79920..a9fdd48 100644 --- a/project/refactor.cpp +++ b/project/refactor.cpp @@ -1,467 +1,238 @@ -#define ZPL_IMPLEMENTATION +#define BLOAT_IMPL #include "bloat.hpp" +#include "IO.cpp" +#include "Spec.cpp" -namespace File +#define Build_Debug 1 + + +void parse_options( int num, char** arguments ) { - zpl_string Source = nullptr; - zpl_string Destination = nullptr; - zpl_file_contents Content {}; + zpl_opts opts; + zpl_opts_init( & opts, g_allocator, "refactor"); + zpl_opts_add( & opts, "num", "num" , "Number of files to refactor" , ZPL_OPTS_INT ); + zpl_opts_add( & opts, "src" , "src" , "File/s to refactor" , ZPL_OPTS_STRING); + zpl_opts_add( & opts, "dst" , "dst" , "File/s post refactor" , ZPL_OPTS_STRING); + zpl_opts_add( & opts, "spec", "spec", "Specification for refactoring", ZPL_OPTS_STRING); - zpl_arena Buffer; - - void cleanup() + if (zpl_opts_compile( & opts, num, arguments)) { - zpl_arena_free( & Buffer ); - } - - void read() - { - zpl_file file_src = {}; - - Content.allocator = g_allocator; - - zpl_file_error error_src = zpl_file_open( & file_src, Source ); - - if ( error_src == ZPL_FILE_ERROR_NONE ) + sw num = 0; + + if ( zpl_opts_has_arg( & opts, "num" ) ) { - zpl_isize fsize = cast(zpl_isize) zpl_file_size( & file_src); - - if ( fsize > 0 ) + num = zpl_opts_integer( & opts, "num", -1 ); + uw global_reserve = num * sizeof(zpl_string) * IO::Path_Size_Largest * 2 + 8; + + if ( global_reserve > zpl_megabytes(1) ) { - zpl_arena_init_from_allocator( & Buffer, zpl_heap(), (fsize + fsize % 64) * 4 ); - - Content.data = zpl_alloc( zpl_arena_allocator( & Buffer), fsize); - Content.size = fsize; - - zpl_file_read_at ( & file_src, Content.data, Content.size, 0); + Memory::resize( global_reserve + zpl_megabytes(2) ); } - - zpl_file_close( & file_src); + + zpl_array_init_reserve( IO::Sources, g_allocator, num ); + zpl_array_init_reserve( IO::Destinations, g_allocator, num ); } - - if ( Content.data == nullptr ) + else { - fatal( "Unable to open source file: %s\n", Source ); - } - } - - void write(zpl_string refactored) - { - if ( refactored == nullptr) - return; - - zpl_file file_dest {}; - zpl_file_error error = zpl_file_create( & file_dest, Destination ); - - if ( error != ZPL_FILE_ERROR_NONE ) - { - fatal( "Unable to open destination file: %s\n", Destination ); - } - - zpl_file_write( & file_dest, refactored, zpl_string_length(refactored) ); - } -} - -namespace Spec -{ - zpl_string File; - - enum Tok - { - Not, - Namespace, - Word, - - Num_Tok - }; - - ct - char const* str_tok( Tok tok ) - { - ct - char const* tok_to_str[ Tok::Num_Tok ] = - { - "not", - "namespace", - "word", - }; - - return tok_to_str[ tok ]; - } - - ct - char strlen_tok( Tok tok ) - { - ct - const u8 tok_to_len[ Tok::Num_Tok ] = - { - 3, - 9, - 4, - }; - - return tok_to_len[ tok ]; - } - - forceinline - bool is_tok( Tok tok, zpl_string str, u32 length ) - { - char const* tok_str = str_tok(tok); - const u8 tok_len = strlen_tok(tok); - - if ( tok_len != length) - return false; - - s32 result = zpl_strncmp( tok_str, str, tok_len ); - - return result == 0; - } - - struct Entry - { - zpl_string Sig = nullptr; // Signature - zpl_string Sub = nullptr; // Substitute - }; - - zpl_arena Buffer {}; - zpl_array(Entry) Word_Ignores; - zpl_array(Entry) Namespace_Ignores; - zpl_array(Entry) Words; - zpl_array(Entry) Namespaces; - - u32 Sig_Smallest = zpl_kilobytes(1); - - forceinline - void find_next_token( zpl_string& token, char*& line, u32& length ) - { - zpl_string_clear( token ); - length = 0; - while ( zpl_char_is_alphanumeric( line[length] ) || line[length] == '_' ) - { - length++; - } - - if ( length == 0 ) - { - fatal("Failed to find valid initial token"); - } - - token = zpl_string_append_length( token, line, length ); - line += length; - } - - void process() - { - char* content; - - zpl_array(char*) lines; - - // Get the contents of the file. - { - zpl_file file {}; - zpl_file_error error = zpl_file_open( & file, File); - - if ( error != ZPL_FILE_ERROR_NONE ) - { - fatal("Could not open the specification file: %s", File); - } - - sw fsize = scast( sw, zpl_file_size( & file ) ); - - if ( fsize <= 0 ) - { - fatal("No content in specificaiton to process"); - } - - zpl_arena_init_from_allocator( & Buffer, zpl_heap(), (fsize + fsize % 64) * 10 + zpl_kilobytes(1) ); - - char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & Buffer), fsize + 1) ); - - zpl_file_read( & file, content, fsize); - - content[fsize] = 0; - - lines = zpl_str_split_lines( zpl_arena_allocator( & Buffer ), content, false ); - - zpl_file_close( & file ); + num = 1; } - sw left = zpl_array_count( lines ); - - if ( left == 0 ) + if ( zpl_opts_has_arg( & opts, "src" ) ) { - fatal("Spec::process: lines array imporoperly setup"); + zpl_string opt = zpl_opts_string( & opts, "src", "INVALID SRC ARGUMENT" ); + + if ( num == 1 ) + { + IO::Sources[0] = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) ); + } + else + { + char buffer[ IO::Path_Size_Largest ]; + + uw left = num; + do + { + char* path = buffer; + sw length = 0; + + do + { + path[length] = *opt; + } + while ( length++, opt++, *opt != ' ' ); + + IO::Sources[num - left] = zpl_string_make_length( g_allocator, path, length ); + + opt++; + } + while ( --left ); + } + } + else + { + fatal( "-source not provided\n" ); } - // Skip the first line as its the version number and we only support __VERSION 1. - left--; - lines++; - - zpl_array_init( Word_Ignores, zpl_arena_allocator( & Buffer)); - zpl_array_init( Namespace_Ignores, zpl_arena_allocator( & Buffer)); - zpl_array_init( Words, zpl_arena_allocator( & Buffer)); - zpl_array_init( Namespaces, zpl_arena_allocator( & Buffer)); - - // Limiting the maximum output of a token to 1 KB - zpl_string token = zpl_string_make_reserve( zpl_arena_allocator( & Buffer), zpl_kilobytes(1)); - - while ( left-- ) + if ( zpl_opts_has_arg( & opts, "dst" ) ) { - char* line = * lines; + zpl_string opt = zpl_opts_string( & opts, "dst", "INVALID DST ARGUMENT" ); - // Ignore line if its a comment - if ( line[0] == '/' && line[1] == '/') + if ( num == 1 ) { - lines++; - continue; + IO::Destinations[0] = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) ); } - - // Remove indent + else { - while ( zpl_char_is_space( line[0] ) ) - line++; + char buffer[ IO::Path_Size_Largest ]; - if ( line[0] == '\0' ) + uw left = num; + do { - lines++; - continue; - } - } + char* path = buffer; + sw length = 0; - u32 length = 0; - - // Find a valid token - find_next_token( token, line, length ); - - Tok type = Tok::Num_Tok; - bool ignore = false; - Entry entry {}; - - // Will be reguarded as an ignore. - if ( is_tok( Tok::Not, token, length )) - { - ignore = true; - - while ( zpl_char_is_space( line[0] ) ) - line++; - - if ( line[0] == '\0' ) - { - lines++; - continue; - } - - // Find the category token - find_next_token( token, line, length ); - } - - if ( is_tok( Tok::Namespace, token, length ) ) - { - type = Tok::Namespace; - } - else if ( is_tok( Tok::Word, token, length ) ) - { - type = Tok::Word; - } - - // Parse line. - { - // Find first argument - { - - while ( zpl_char_is_space( line[0] ) ) - line++; - - if ( line[0] == '\0' ) + do { - lines++; - continue; - } - } + path[length] = *opt; + } + while ( length++, opt++, *opt != ' ' ); + + IO::Destinations[num - left] = zpl_string_make_length( g_allocator, path, length ); - find_next_token( token, line, length ); - - // First argument is signature. - entry.Sig = zpl_string_make_length( g_allocator, token, length ); - - if ( length < Sig_Smallest ) - Sig_Smallest = length; - - if ( line[0] == '\0' || ignore ) - { - switch ( type ) - { - case Tok::Namespace: - if ( ignore) - zpl_array_append( Namespace_Ignores, entry ); - - else - zpl_array_append( Namespaces, entry ); - break; - - case Tok::Word: - if ( ignore) - { - zpl_array_append( Word_Ignores, entry ); - u32 test = zpl_array_count( Word_Ignores ); - } - - - else - zpl_array_append( Words, entry ); - break; - } - - lines++; - continue; - } - - // Look for second argument indicator - { - bool bSkip = false; - - while ( line[0] != ',' ) - { - if ( line[0] == '\0' ) - { - switch ( type ) - { - case Tok::Namespace: - zpl_array_append( Namespaces, entry ); - break; - - case Tok::Word: - zpl_array_append( Words, entry ); - break; - } - - bSkip = true; - break; - } - - line++; - } - - if ( bSkip ) - { - lines++; - continue; - } - } - - // Eat the argument delimiter. - line++; - - // Remove spacing - { - bool bSkip = true; - - while ( zpl_char_is_space( line[0] ) ) - line++; - - if ( line[0] == '\0' ) - { - switch ( type ) - { - case Tok::Namespace: - zpl_array_append( Namespaces, entry ); - break; - - case Tok::Word: - zpl_array_append( Words, entry ); - break; - } - - lines++; - continue; - } - } - - find_next_token( token, line, length ); - - // Second argument is substitute. - entry.Sub = zpl_string_make_length( g_allocator, token, length ); - - switch ( type ) - { - case Tok::Namespace: - zpl_array_append( Namespaces, entry ); - lines++; - continue; - - case Tok::Word: - zpl_array_append( Words, entry ); - lines++; - continue; - } + opt++; + } + while ( --left ); } + } - log_fmt("Specification Line: %d is missing valid keyword", zpl_array_count(lines) - left); - lines++; + if ( zpl_opts_has_arg( & opts, "spec" ) ) + { + zpl_string opt = zpl_opts_string( & opts, "spec", "INVALID PATH" ); + + IO::Specification = zpl_string_make( g_allocator, "" ); + IO::Specification = zpl_string_append( IO::Specification, opt ); } } - - void cleanup() + else { - zpl_arena_free( & Buffer ); + fatal( "Failed to parse arguments\n" ); } + + zpl_opts_free( & opts); } -struct Token -{ - u32 Start; - u32 End; - - zpl_string Sig; - zpl_string Sub; -}; +zpl_arena Refactor_Buffer; void refactor() { - sw buffer_size = File::Content.size; - - zpl_array(Token) tokens; - zpl_array_init( tokens, g_allocator); - - char* content = rcast( char*, File::Content.data ); - - zpl_string current = zpl_string_make( g_allocator, ""); - zpl_string preview = zpl_string_make( g_allocator, ""); - - sw left = File::Content.size; - sw line = 0; - - while ( left ) + ct char const* include_sig = "#include \""; + + struct Token { - if ( content[0] == '\n' ) + u32 Start; + u32 End; + + zpl_string Sig; + zpl_string Sub; + }; + + static zpl_array(Token) tokens = nullptr; + static zpl_string current = zpl_string_make( g_allocator, ""); + +#if Build_Debug + static zpl_string preview = zpl_string_make( g_allocator, ""); +#endif + + static bool Done = false; + if (! Done) + { + zpl_array_init( tokens, g_allocator ); + Done = true; + } + else + { + zpl_array_clear( tokens ); + } + + // Prepare data and trackers. + Array_Line src = IO::get_next_source(); + Array_Line lines = src; + + if ( src == nullptr ) + return; + + const sw num_lines = zpl_array_count( lines); + + sw buffer_size = IO::Current_Size; + + sw left = num_lines; + Line line = *lines; + uw pos = 0; + + do + { + Continue_Line: + + // Includes to ignore { - line++; + Spec::Entry* ignore = Spec::Ignore_Words; + sw ignores_left = zpl_array_count( Spec::Ignore_Words); + + do + { + if ( include_sig[0] != line[0] ) + continue; + + u32 sig_length = zpl_string_length( ignore->Sig ); + + current = zpl_string_set( current, include_sig ); + current = zpl_string_append_length( current, line, sig_length ); + current = zpl_string_append_length( current, "\"", 2 ); + // Formats current into: #include "Sig>" + + if ( zpl_string_are_equal( ignore->Sig, current ) ) + { + log_fmt("\nIgnored %-81s line %d", current, num_lines - left ); + + const sw length = zpl_string_length( current ); + + line += length; + pos += length; + + // Force end of line. + while ( line != '\0' ) + { + line++; + pos++; + } + + goto Skip; + } + } + while ( ignore++, --ignores_left ); } // Word Ignores { - Spec::Entry* ignore = Spec::Word_Ignores; - - sw ignores_left = zpl_array_count( Spec::Word_Ignores); + Spec::Entry* ignore = Spec::Ignore_Words; + sw ignores_left = zpl_array_count( Spec::Ignore_Words); do { - if ( ignore->Sig[0] != content[0] ) - { + if ( ignore->Sig[0] != line[0] ) continue; - } zpl_string_clear( current ); u32 sig_length = zpl_string_length( ignore->Sig ); - current = zpl_string_append_length( current, content, sig_length ); + current = zpl_string_append_length( current, line, sig_length ); if ( zpl_string_are_equal( ignore->Sig, current ) ) { - char before = content[-1]; - char after = content[sig_length]; + char before = line[-1]; + char after = line[sig_length]; if ( zpl_char_is_alphanumeric( before ) || before == '_' || zpl_char_is_alphanumeric( after ) || after == '_' ) @@ -469,10 +240,10 @@ void refactor() continue; } - log_fmt("\nIgnored %-81s line %d", current, line ); + log_fmt("\nIgnored %-81s line %d", current, num_lines - left ); - content += sig_length; - left -= sig_length; + line += sig_length; + pos += sig_length; goto Skip; } } @@ -481,26 +252,23 @@ void refactor() // Namespace Ignores { - Spec::Entry* ignore = Spec::Namespace_Ignores; - - sw ignores_left = zpl_array_count( Spec::Namespace_Ignores); + Spec::Entry* ignore = Spec::Ignore_Namespaces; + sw ignores_left = zpl_array_count( Spec::Ignore_Namespaces); do { - if ( ignore->Sig[0] != content[0] ) - { + if ( ignore->Sig[0] != line[0] ) continue; - } zpl_string_clear( current ); u32 sig_length = zpl_string_length( ignore->Sig ); - current = zpl_string_append_length( current, content, sig_length ); + current = zpl_string_append_length( current, line, sig_length ); if ( zpl_string_are_equal( ignore->Sig, current ) ) { u32 length = sig_length; - char* ns_content = content + sig_length; + char* ns_content = line + sig_length; while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' ) { @@ -508,40 +276,93 @@ void refactor() ns_content++; } + #if Build_Debug zpl_string_clear( preview ); - preview = zpl_string_append_length( preview, content, length ); - log_fmt("\nIgnored %-40s %-40s line %d", preview, ignore->Sig, line); + preview = zpl_string_append_length( preview, line, length ); + log_fmt("\nIgnored %-40s %-40s line %d", preview, ignore->Sig, - left); + #endif - content += length; - left -= length; + line += length; + pos += length; goto Skip; } } while ( ignore++, --ignores_left ); } - // Words to match + // Includes to match { - Spec::Entry* word = Spec::Words; + Spec::Entry* include = Spec::Includes; - sw words_left = zpl_array_count ( Spec::Words); + sw includes_left = zpl_array_count ( Spec::Includes); do { - if ( word->Sig[0] != content[0] ) - { + if ( include_sig[0] != line[0] ) continue; + + u32 sig_length = zpl_string_length( include->Sig ); + + current = zpl_string_set( current, include_sig ); + current = zpl_string_append_length( current, line, sig_length ); + current = zpl_string_append_length( current, "\"", 2 ); + // Formats current into: #include "Sig>" + + if ( zpl_string_are_equal( include->Sig, current ) ) + { + Token entry {}; + + const sw length = zpl_string_length( current ); + + entry.Start = pos; + entry.End = pos + length; + entry.Sig = include->Sig; + + if ( include->Sub != nullptr ) + { + entry.Sub = include->Sub; + buffer_size += zpl_string_length( entry.Sub) - sig_length; + } + + zpl_array_append( tokens, entry ); + + log_fmt("\nFound %-81s line %d", current, num_lines - left); + + line += length; + pos += length; + + // Force end of line. + while ( line != '\0' ) + { + line++; + pos++; + } + + goto Skip; } + } + while ( include++, --includes_left ); + } + + // Words to match + { + Spec::Entry* word = Spec::Words; + sw words_left = zpl_array_count ( Spec::Words); + + do + { + if ( word->Sig[0] != line[0] ) + continue; zpl_string_clear( current ); sw sig_length = zpl_string_length( word->Sig); - current = zpl_string_append_length( current, content, sig_length ); + current = zpl_string_append_length( current, line, sig_length ); if ( zpl_string_are_equal( word->Sig, current ) ) { - char before = content[-1]; - char after = content[sig_length]; + char before = line[-1]; + char after = line[sig_length]; if ( zpl_char_is_alphanumeric( before ) || before == '_' || zpl_char_is_alphanumeric( after ) || after == '_' ) @@ -551,8 +372,8 @@ void refactor() Token entry {}; - entry.Start = File::Content.size - left; - entry.End = entry.Start + sig_length; + entry.Start = pos; + entry.End = pos + sig_length; entry.Sig = word->Sig; if ( word->Sub != nullptr ) @@ -563,10 +384,10 @@ void refactor() zpl_array_append( tokens, entry ); - log_fmt("\nFound %-81s line %d", current, line); + log_fmt("\nFound %-81s line %d", current, num_lines - left); - content += sig_length; - left -= sig_length; + line += sig_length; + pos += sig_length; goto Skip; } } @@ -581,20 +402,18 @@ void refactor() do { - if ( nspace->Sig[0] != content[0] ) - { + if ( nspace->Sig[0] != line[0] ) continue; - } zpl_string_clear( current ); u32 sig_length = zpl_string_length( nspace->Sig ); - current = zpl_string_append_length( current, content, sig_length ); + current = zpl_string_append_length( current, line, sig_length ); if ( zpl_string_are_equal( nspace->Sig, current ) ) { u32 length = sig_length; - char* ns_content = content + sig_length; + char* ns_content = line + sig_length; while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' ) { @@ -604,8 +423,8 @@ void refactor() Token entry {}; - entry.Start = File::Content.size - left; - entry.End = entry.Start + length; + entry.Start = pos; + entry.End = pos + length; entry.Sig = nspace->Sig; buffer_size += sig_length; @@ -618,53 +437,46 @@ void refactor() zpl_array_append( tokens, entry ); + #if Build_Debug zpl_string_clear( preview ); - preview = zpl_string_append_length( preview, content, length); - log_fmt("\nFound %-40s %-40s line %d", preview, nspace->Sig, line); + preview = zpl_string_append_length( preview, line, length); + log_fmt("\nFound %-40s %-40s line %d", preview, nspace->Sig, num_lines - left); + #endif - content += length; - left -= length; + line += length; + pos += length; + goto Skip; } } while ( nspace++, --nspaces_left ); } - content++; - left--; - Skip: - continue; - } + if ( line != '\0' ) + goto Continue_Line; + } + while ( lines++, line = *lines, left ); + + // Prep data for building the content + left = IO::Current_Size; + + char* content = IO::Current_Content; - left = zpl_array_count( tokens); - content = rcast( char*, File::Content.data); - // Generate the refactored file content. - zpl_arena buffer; - zpl_string refactored = nullptr; + static zpl_string + refactored = zpl_string_make_reserve( zpl_arena_allocator( & Refactor_Buffer ), buffer_size ); { - Token* entry = tokens; + Token* entry = tokens; + sw previous_end = 0; - if ( entry == nullptr) - return; - - zpl_arena_init_from_allocator( & buffer, zpl_heap(), buffer_size * 2 ); - - zpl_string - new_string = zpl_string_make_reserve( zpl_arena_allocator( & buffer), zpl_kilobytes(1) ); - refactored = zpl_string_make_reserve( zpl_arena_allocator( & buffer), buffer_size ); - - sw previous_end = 0; - - while ( left-- ) + do { sw segment_length = entry->Start - previous_end; - - sw sig_length = zpl_string_length( entry->Sig ); + sw sig_length = zpl_string_length( entry->Sig ); // Append between tokens - refactored = zpl_string_append_length( refactored, content, segment_length ); - content += segment_length + sig_length; + refactored = zpl_string_append_length( refactored, line, segment_length ); + line += segment_length + sig_length; segment_length = entry->End - entry->Start - sig_length; @@ -672,97 +484,48 @@ void refactor() if ( entry->Sub ) refactored = zpl_string_append( refactored, entry->Sub ); - refactored = zpl_string_append_length( refactored, content, segment_length ); - content += segment_length; + refactored = zpl_string_append_length( refactored, line, segment_length ); + line += segment_length; previous_end = entry->End; entry++; } + while ( --left ); entry--; - if ( entry->End < File::Content.size ) + if ( entry->End < IO::Current_Size ) { - refactored = zpl_string_append_length( refactored, content, File::Content.size - entry->End ); + refactored = zpl_string_append_length( refactored, line, IO::Current_Size - entry->End ); } } - - // Write refactored content to destination. - File::write( refactored ); - zpl_arena_free( & buffer ); + IO::write( refactored ); } - -inline -void parse_options( int num, char** arguments ) -{ - zpl_opts opts; - zpl_opts_init( & opts, g_allocator, "refactor"); - zpl_opts_add( & opts, "src" , "src" , "File to refactor" , ZPL_OPTS_STRING); - zpl_opts_add( & opts, "dst" , "dst" , "File post refactor" , ZPL_OPTS_STRING); - zpl_opts_add( & opts, "spec", "spec", "Specification for refactoring", ZPL_OPTS_STRING); - - if (zpl_opts_compile( & opts, num, arguments)) - { - if ( zpl_opts_has_arg( & opts, "src" ) ) - { - zpl_string opt = zpl_opts_string( & opts, "src", "INVALID PATH" ); - - File::Source = zpl_string_make( g_allocator, "" ); - File::Source = zpl_string_append( File::Source, opt ); - } - else - { - fatal( "-source not provided\n" ); - } - - if ( zpl_opts_has_arg( & opts, "dst" ) ) - { - zpl_string opt = zpl_opts_string( & opts, "dst", "INVALID PATH" ); - - File::Destination = zpl_string_make( g_allocator, "" ); - File::Destination = zpl_string_append( File::Destination, opt ); - } - else if ( File::Source ) - { - File::Destination = zpl_string_make( g_allocator, "" ); - File::Destination = zpl_string_append( File::Destination, File::Source ); - } - - if ( zpl_opts_has_arg( & opts, "spec" ) ) - { - zpl_string opt = zpl_opts_string( & opts, "spec", "INVALID PATH" ); - - Spec::File = zpl_string_make( g_allocator, "" ); - Spec::File = zpl_string_append( Spec::File, opt ); - } - } - else - { - fatal( "Failed to parse arguments\n" ); - } - - zpl_opts_free( & opts); -} - -int main( int num, char** arguments) +int main( int num, char** arguments ) { Memory::setup(); + + parse_options( num, arguments); - parse_options( num, arguments ); + IO::prepare(); - if ( Spec::File ) - Spec::process(); + // Just reserving more than we'll ever problably need. + zpl_arena_init_from_allocator( & Refactor_Buffer, zpl_heap(), IO::Largest_Src_Size * 4 + 8); - File::read(); + Spec::parse(); - refactor(); + sw left = zpl_array_count( IO::Sources ); + do + { + refactor(); + } + while ( --left ); - log_fmt("\n"); - zpl_printf("Refacotred: %s using %s\n", File::Source, Spec::File); + zpl_arena_free( & Refactor_Buffer ); Spec:: cleanup(); - File:: cleanup(); + IO:: cleanup(); Memory::cleanup(); } diff --git a/refactor.10x b/refactor.10x new file mode 100644 index 0000000..fc30d17 --- /dev/null +++ b/refactor.10x @@ -0,0 +1,63 @@ + + + + *.*, + *.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate, + true + true + true + false + false + + + + + + + + + + + false + + Debug + Release + + + x64 + + + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\include + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\ATLMFC\include + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include + C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt + C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um + .\thirdparty + + + ZPL_IMPLEMENTATION + + + + Debug:x64 + + + C:\projects\refactor\thirdparty + + + + Debug + + + + x64 + + + + + +