Merge pull request #2 from Ed94/includes_n_multi-file

Update main with feature updates in includes_n_multi-file
This commit is contained in:
Edward R. Gonzalez 2023-03-30 17:42:11 -04:00 committed by GitHub
commit 2419f407a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1638 additions and 1583 deletions

4
.gitignore vendored
View File

@ -2,4 +2,6 @@
build/* build/*
zpl.refactored.h Test/*.h
Test/*.hpp
Test/*.cpp

27
.vscode/launch.json vendored
View File

@ -13,13 +13,34 @@
"-src=./thirdparty/zpl.h", "-src=./thirdparty/zpl.h",
"-dst=./Test/zpl.refactored.h", "-dst=./Test/zpl.refactored.h",
"-spec=./Test/zpl.h.refactor" "-spec=./Test/zpl.refactor"
], ],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"environment": [], "environment": [],
"console": "integratedTerminal" "console": "integratedTerminal"
} },
// {
// "name": "Refactor ZPL files",
// "type": "cppvsdbg",
// "request": "launch",
// "program": "${workspaceFolder}/build/refactor.exe",
// "args": [
// "-num=2",
// "-src=./thirdparty/zpl.h",
// "./thirdparty/file.h",
// "-dst=./Test/zpl.refactored.h",
// "./thirdparty/file.refactored.h",
// "-spec=./Test/zpl.refactor"
// ],
// "stopAtEntry": false,
// "cwd": "${workspaceRoot}",
// "environment": [],
// "console": "integratedTerminal"
// },
{ {
"name": "Refactor refactor.c", "name": "Refactor refactor.c",
"type": "cppvsdbg", "type": "cppvsdbg",
@ -29,7 +50,7 @@
"-source=./refactor.cpp", "-source=./refactor.cpp",
"-destination=./Test/refactor.cpp", "-destination=./Test/refactor.cpp",
"-specification=./Test/zpl.h.refactor" "-specification=./Test/zpl.refactor"
], ],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",

View File

@ -1,28 +1,49 @@
# refactor # refactor
A code identifier refactoring app. Intended for c/c++ like identifiers. Refactor c/c++ files (and problably others) with ease.
Parameters : ## 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 * `-src` : Source file to refactor
* `-dst` : Destination file after the refactor (omit to use the same as source) * `-dst` : Destination file after the refactor (omit to use the same as source)
* `-spec` : Specification containing rules to use for the refactor. * `-spec` : Specification containing rules to use for the refactor.
* `-debug` : Use only if on debug build and desire to attach to process.
Syntax : ## Syntax :
* `not` Omit word or namespace. * `not` Omit word or namespace.
* `include` Preprocessor include <file> related identifiers.
* `word` Fixed sized identifier. * `word` Fixed sized identifier.
* `namespace` Variable sized identifiers, mainly intended to redefine c-namespace of an identifier. * `namespace` Variable sized identifiers, mainly intended to redefine c-namespace of an identifier.
* `,` is used to delimit arguments to word or namespace. * `,` is used to delimit arguments (if doing a find and replace).
* `L-Value` is the signature to modify. * `L-Value` is the signature to modify.
* `R-Value` is the substitute ( only available if rule does not use `not` keyword ) * `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 <L-Value>`.
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 alts is its problably more ergonomic and performant 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 easy to port these scripts to w/e shell script you'd perfer.
TODO: TODO:
* Possibly come up with a better name. * Possibly come up with a better name.
* Cleanup memory usage (it hogs quite a bit for what it does..) * Test to see how much needs to be ported for other platforms (if at all)
* 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) * Setup as api.
* Accept multiple files at once `-files` * Provide binaries in the release page for github. (debug and release builds)
* Add support for `macro` keyword (single out macro identifiers) * Directive to ignore comments (with a way to specify the comment signature). Right now comments that meet the signature of words or namespaces are refactored.
* Add support for `include` keyword (single out include definitions)
* Add support for auto-translating a namespace in a macro to a cpp namespace

View File

@ -1,137 +0,0 @@
/*
BLOAT.
ZPL requires ZPL_IMPLEMENTATION whereever this library is included.
This file assumes it will be included in one compilation unit.
*/
#pragma once
#if __clang__
# pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wswitch"
# pragma clang diagnostic ignored "-Wunused-variable"
#endif
#pragma region ZPL INCLUDE
#if __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wmissing-braces"
# pragma clang diagnostic ignored "-Wbraced-scalar-init"
#endif
// # define ZPL_HEAP_ANALYSIS
# define ZPL_NO_MATH_H
# define ZPL_DISABLE_C_DECLS
# define ZPL_WRAP_IN_NAMESPACE
# define ZPL_CUSTOM_MODULES
# define ZPL_MODULE_ESSENTIALS
# define ZPL_MODULE_CORE
# define ZPL_MODULE_TIMER
// # define ZPL_MODULE_HASHING
// # define ZPL_MODULE_REGEX
// # define ZPL_MODULE_EVENT
// # define ZPL_MODULE_DLL
# define ZPL_MODULE_OPTS
// # define ZPL_MODULE_PROCESS
// # define ZPL_MODULE_MATH
// # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER
// extern "C" {
#include "zpl.refactored.h"
// }
#if __clang__
# pragma clang diagnostic pop
#endif
#pragma endregion ZPL INCLUDE
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
#define ct constexpr
#define gen( ... ) template< __VA_ARGS__ >
#define forceinline ZPL_ALWAYS_INLINE
#define print_nl( _) zpl_printf("\n")
#define cast( Type_, Value_ ) ( ( Type_ ), ( Value_ ) )
#define scast( Type_, Value_ ) static_cast< Type_ >( Value_ )
#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) \
ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
namespace Memory
{
zpl::arena Global_Arena {};
#define g_allocator arena_allocator( & Memory::Global_Arena)
void setup()
{
arena_init_from_allocator( & Global_Arena, heap(), megabytes(10) );
if ( Global_Arena.total_size == 0 )
{
zpl::assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void cleanup()
{
arena_free( & Global_Arena);
}
}
zpl::sw log_fmt(char const *fmt, ...)
{
#if Build_Debug
zpl::sw res;
va_list va;
va_start(va, fmt);
res = zpl::printf_va(fmt, va);
va_end(va);
return res;
#else
return 0;
#endif
}
void fatal(char const *fmt, ...)
{
local_persist thread_local
char buf[ZPL_PRINTF_MAXLEN] = { 0 };
va_list va;
#if Build_Debug
va_start(va, fmt);
zpl::snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va);
va_end(va);
zpl::assert_crash(buf);
#else
va_start(va, fmt);
zpl::printf_err_va( fmt, va);
va_end(va);
zpl::exit(1);
#endif
}

View File

@ -4,7 +4,7 @@ project( 'refactor', 'c', 'cpp', default_options : ['buildtype=debug'] )
if get_option('buildtype').startswith('debug') if get_option('buildtype').startswith('debug')
add_project_arguments('-DBuild_Debug', language : 'cpp') add_project_arguments('-DBuild_Debug', language : ['c', 'cpp'])
endif endif

71
Test/project.refactor Normal file
View File

@ -0,0 +1,71 @@
__VERSION 1
// not : Ignore
// include : #includes
// word : Alphanumeric or underscore
// namespace : Prefix search and replace (c-namspaces).
// regex : Unavailable in __VERSION 1.
// Precedence (highest to lowest):
// word, namespace, regex
// Comments
not comments
// Includes
include zpl.h, zpl.refactored.h
include Bloat.hpp, Bloat.refactored.hpp
include Bloat.cpp, Bloat.refactored.cpp
include IO.hpp, IO.refactored.hpp
include IO.cpp, IO.refactored.cpp
include Spec.hpp, Spec.refactored.hpp
include Spec.cpp, Spec.refactored.cpp
// Remove the zpl namespace.
namespace zpl_
// Don't expose zpl internals
not namespace zpl__
// Macro exposure
//namespace ZPL_
//not word ZPL_IMPLEMENTATION
// Name conflicts
word opts, options
word zpl_strncmp, str_compare
word zpl_strcmp, str_compare
// Undesired typedefs
word zpl_i8, s8
word zpl_i16, s16
word zpl_i32, s32
word zpl_i64, s64
word zpl_u8, u8
word zpl_u16, u16
word zpl_u32, u32
word zpl_u64, u64
word zpl_intptr, sptr
word zpl_uintptr, uptr
word zpl_usize, uw
word zpl_isize, sw
// Conflicts with std. (Uncomment if using c externs)
not word zpl_memchr
not word zpl_memmove
not word zpl_memset
not word zpl_memswap
not word zpl_memcopy
not word zpl_printf
not word zpl_printf_va
not word zpl_printf_err
not word zpl_printf_err_va
not word zpl_fprintf
not word zpl_fprintf_va
not word zpl_snprintf
not word zpl_snprintf_va
not word zpl_strchr
not word zpl_strlen
not word zpl_strnlen
not word zpl_exit

View File

@ -1,770 +0,0 @@
#define ZPL_IMPLEMENTATION
#include "bloat.refactored.hpp"
namespace File
{
using namespace zpl;
string Source = nullptr;
string Destination = nullptr;
file_contents Content {};
arena Buffer;
void cleanup()
{
arena_free( & Buffer );
}
void read()
{
file file_src = {};
Content.allocator = g_allocator;
file_error error_src = file_open( & file_src, Source );
if ( error_src == ZPL_FILE_ERROR_NONE )
{
sw fsize = zpl_cast(sw) file_size( & file_src);
if ( fsize > 0 )
{
arena_init_from_allocator( & Buffer, heap(), (fsize + fsize % 64) * 4 );
Content.data = alloc( arena_allocator( & Buffer), fsize);
Content.size = fsize;
file_read_at ( & file_src, Content.data, Content.size, 0);
}
file_close( & file_src);
}
if ( Content.data == nullptr )
{
fatal( "Unable to open source file: %s\n", Source );
}
}
void write(string refactored)
{
if ( refactored == nullptr)
return;
file file_dest {};
file_error error = file_create( & file_dest, Destination );
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal( "Unable to open destination file: %s\n", Destination );
}
file_write( & file_dest, refactored, string_length(refactored) );
}
}
namespace Spec
{
using namespace 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, 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 = str_compare( tok_str, str, tok_len );
return result == 0;
}
struct Entry
{
string Sig = nullptr; // Signature
string Sub = nullptr; // Substitute
};
arena Buffer {};
zpl_array(Entry) Word_Ignores;
zpl_array(Entry) Namespace_Ignores;
zpl_array(Entry) Words;
zpl_array(Entry) Namespaces;
u32 Sig_Smallest = kilobytes(1);
forceinline
void find_next_token( string& token, char*& line, u32& length )
{
string_clear( token );
length = 0;
while ( char_is_alphanumeric( line[length] ) || line[length] == '_' )
{
length++;
}
if ( length == 0 )
{
fatal("Failed to find valid initial token");
}
token = string_append_length( token, line, length );
line += length;
}
void process()
{
char* content;
zpl_array(char*) lines;
// Get the contents of the file.
{
file file {};
file_error error = file_open( & file, File);
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("Could not open the specification file: %s", File);
}
sw fsize = scast( sw, file_size( & file ) );
if ( fsize <= 0 )
{
fatal("No content in specificaiton to process");
}
arena_init_from_allocator( & Buffer, heap(), (fsize + fsize % 64) * 10 + kilobytes(1) );
char* content = rcast( char*, alloc( arena_allocator( & Buffer), fsize + 1) );
file_read( & file, content, fsize);
content[fsize] = 0;
lines = str_split_lines( arena_allocator( & Buffer ), content, false );
file_close( & file );
}
sw left = array_count( lines );
if ( left == 0 )
{
fatal("Spec::process: lines array imporoperly setup");
}
// Skip the first line as its the version number and we only support __VERSION 1.
left--;
lines++;
array_init( Word_Ignores, arena_allocator( & Buffer));
array_init( Namespace_Ignores, arena_allocator( & Buffer));
array_init( Words, arena_allocator( & Buffer));
array_init( Namespaces, arena_allocator( & Buffer));
// Limiting the maximum output of a token to 1 KB
string token = string_make_reserve( arena_allocator( & Buffer), kilobytes(1));
while ( left-- )
{
char* line = * lines;
// Ignore line if its a comment
if ( line[0] == '/' && line[1] == '/')
{
lines++;
continue;
}
// Remove indent
{
while ( 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 ( 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 ( char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
lines++;
continue;
}
}
find_next_token( token, line, length );
// First argument is signature.
entry.Sig = 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)
array_append( Namespace_Ignores, entry );
else
array_append( Namespaces, entry );
break;
case Tok::Word:
if ( ignore)
{
array_append( Word_Ignores, entry );
u32 test = array_count( Word_Ignores );
}
else
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:
array_append( Namespaces, entry );
break;
case Tok::Word:
array_append( Words, entry );
break;
}
bSkip = true;
break;
}
line++;
}
if ( bSkip )
{
lines++;
continue;
}
}
// Eat the argument delimiter.
line++;
// Remove spacing
{
bool bSkip = true;
while ( char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
switch ( type )
{
case Tok::Namespace:
array_append( Namespaces, entry );
break;
case Tok::Word:
array_append( Words, entry );
break;
}
lines++;
continue;
}
}
find_next_token( token, line, length );
// Second argument is substitute.
entry.Sub = string_make_length( g_allocator, token, length );
switch ( type )
{
case Tok::Namespace:
array_append( Namespaces, entry );
lines++;
continue;
case Tok::Word:
array_append( Words, entry );
lines++;
continue;
}
}
log_fmt("Specification Line: %d is missing valid keyword", array_count(lines) - left);
lines++;
}
}
void cleanup()
{
arena_free( & Buffer );
}
}
using namespace zpl;
struct Token
{
u32 Start;
u32 End;
string Sig;
string Sub;
};
void refactor()
{
sw buffer_size = File::Content.size;
zpl_array(Token) tokens;
array_init( tokens, g_allocator);
char* content = rcast( char*, File::Content.data );
string current = string_make( g_allocator, "");
string preview = string_make( g_allocator, "");
sw left = File::Content.size;
sw line = 0;
while ( left )
{
if ( content[0] == '\n' )
{
line++;
}
// Word Ignores
{
Spec::Entry* ignore = Spec::Word_Ignores;
sw ignores_left = array_count( Spec::Word_Ignores);
do
{
if ( ignore->Sig[0] != content[0] )
{
continue;
}
string_clear( current );
u32 sig_length = string_length( ignore->Sig );
current = string_append_length( current, content, sig_length );
if ( string_are_equal( ignore->Sig, current ) )
{
char before = content[-1];
char after = content[sig_length];
if ( char_is_alphanumeric( before ) || before == '_'
|| char_is_alphanumeric( after ) || after == '_' )
{
continue;
}
log_fmt("\nIgnored %-81s line %d", current, line );
content += sig_length;
left -= sig_length;
goto Skip;
}
}
while ( ignore++, --ignores_left );
}
// Namespace Ignores
{
Spec::Entry* ignore = Spec::Namespace_Ignores;
sw ignores_left = array_count( Spec::Namespace_Ignores);
do
{
if ( ignore->Sig[0] != content[0] )
{
continue;
}
string_clear( current );
u32 sig_length = string_length( ignore->Sig );
current = string_append_length( current, content, sig_length );
if ( string_are_equal( ignore->Sig, current ) )
{
u32 length = sig_length;
char* ns_content = content + sig_length;
while ( char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
length++;
ns_content++;
}
string_clear( preview );
preview = string_append_length( preview, content, length );
log_fmt("\nIgnored %-40s %-40s line %d", preview, ignore->Sig, line);
content += length;
left -= length;
goto Skip;
}
}
while ( ignore++, --ignores_left );
}
// Words to match
{
Spec::Entry* word = Spec::Words;
sw words_left = array_count ( Spec::Words);
do
{
if ( word->Sig[0] != content[0] )
{
continue;
}
string_clear( current );
sw sig_length = string_length( word->Sig);
current = string_append_length( current, content, sig_length );
if ( string_are_equal( word->Sig, current ) )
{
char before = content[-1];
char after = content[sig_length];
if ( char_is_alphanumeric( before ) || before == '_'
|| char_is_alphanumeric( after ) || after == '_' )
{
continue;
}
Token entry {};
entry.Start = File::Content.size - left;
entry.End = entry.Start + sig_length;
entry.Sig = word->Sig;
if ( word->Sub != nullptr )
{
entry.Sub = word->Sub;
buffer_size += string_length( entry.Sub) - sig_length;
}
array_append( tokens, entry );
log_fmt("\nFound %-81s line %d", current, line);
content += sig_length;
left -= sig_length;
goto Skip;
}
}
while ( word++, --words_left );
}
// Namespaces to match
{
Spec::Entry* nspace = Spec::Namespaces;
sw nspaces_left = array_count( Spec::Namespaces);
do
{
if ( nspace->Sig[0] != content[0] )
{
continue;
}
string_clear( current );
u32 sig_length = string_length( nspace->Sig );
current = string_append_length( current, content, sig_length );
if ( string_are_equal( nspace->Sig, current ) )
{
u32 length = sig_length;
char* ns_content = content + sig_length;
while ( char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
length++;
ns_content++;
}
Token entry {};
entry.Start = File::Content.size - left;
entry.End = entry.Start + length;
entry.Sig = nspace->Sig;
buffer_size += sig_length;
if ( nspace->Sub != nullptr )
{
entry.Sub = nspace->Sub;
buffer_size += string_length( entry.Sub ) - length;
}
array_append( tokens, entry );
string_clear( preview );
preview = string_append_length( preview, content, length);
log_fmt("\nFound %-40s %-40s line %d", preview, nspace->Sig, line);
content += length;
left -= length;
}
}
while ( nspace++, --nspaces_left );
}
content++;
left--;
Skip:
continue;
}
left = array_count( tokens);
content = rcast( char*, File::Content.data);
// Generate the refactored file content.
arena buffer;
string refactored = nullptr;
{
Token* entry = tokens;
if ( entry == nullptr)
return;
arena_init_from_allocator( & buffer, heap(), buffer_size * 2 );
string
new_string = string_make_reserve( arena_allocator( & buffer), kilobytes(1) );
refactored = string_make_reserve( arena_allocator( & buffer), buffer_size );
sw previous_end = 0;
while ( left-- )
{
sw segment_length = entry->Start - previous_end;
sw sig_length = string_length( entry->Sig );
// Append between tokens
refactored = string_append_length( refactored, content, segment_length );
content += segment_length + sig_length;
segment_length = entry->End - entry->Start - sig_length;
// Append token
if ( entry->Sub )
refactored = string_append( refactored, entry->Sub );
refactored = string_append_length( refactored, content, segment_length );
content += segment_length;
previous_end = entry->End;
entry++;
}
entry--;
if ( entry->End < File::Content.size )
{
refactored = string_append_length( refactored, content, File::Content.size - entry->End );
}
}
// Write refactored content to destination.
File::write( refactored );
arena_free( & buffer );
}
inline
void parse_options( int num, char** arguments )
{
opts opts;
opts_init( & opts, g_allocator, "refactor");
opts_add( & opts, "source" , "src" , "File to refactor" , ZPL_OPTS_STRING);
opts_add( & opts, "destination" , "dst" , "File post refactor" , ZPL_OPTS_STRING);
opts_add( & opts, "specification", "spec", "Specification for refactoring", ZPL_OPTS_STRING);
if (opts_compile( & opts, num, arguments))
{
if ( opts_has_arg( & opts, "src" ) )
{
string opt = opts_string( & opts, "src", "INVALID PATH" );
File::Source = string_make( g_allocator, "" );
File::Source = string_append( File::Source, opt );
}
else
{
fatal( "-source not provided\n" );
}
if ( opts_has_arg( & opts, "dst" ) )
{
string opt = opts_string( & opts, "dst", "INVALID PATH" );
File::Destination = string_make( g_allocator, "" );
File::Destination = string_append( File::Destination, opt );
}
else if ( File::Source )
{
File::Destination = string_make( g_allocator, "" );
File::Destination = string_append( File::Destination, File::Source );
}
if ( opts_has_arg( & opts, "spec" ) )
{
string opt = opts_string( & opts, "spec", "INVALID PATH" );
Spec::File = string_make( g_allocator, "" );
Spec::File = string_append( Spec::File, opt );
}
}
else
{
fatal( "Failed to parse arguments\n" );
}
opts_free( & opts);
}
int main( int num, char** arguments)
{
Memory::setup();
parse_options( num, arguments );
if ( Spec::File )
Spec::process();
File::read();
refactor();
Spec:: cleanup();
File:: cleanup();
Memory::cleanup();
}

View File

@ -1,14 +1,27 @@
__VERSION 1 __VERSION 1
// not : Ignore // not : Ignore
// word : Alphanumeric or underscore // include : #includes
// regex : Unavailable in __VERSION 1. // word : Alphanumeric or underscore
// namespace : Prefix search and replace (c-namspaces).
// regex : Unavailable in __VERSION 1.
// Precedence (highest to lowest): // Precedence (highest to lowest):
// word, namespace, regex // word, namespace, regex
// Comments
not comments
// Header files // Header files
not word zpl_hedley not include zpl_hedley.h
not include allocator.h
not include array.h
not include header/essentials/collections/array.h
not include header/essentials/collections/list.h
not include header/core/file.h
not include header/opts.h
not include source/core/file.c
not include source/opts.c
// Removes the namespace. // Removes the namespace.
namespace zpl_ namespace zpl_
@ -16,30 +29,32 @@ namespace zpl_
// Don't expose internals // Don't expose internals
not namespace zpl__ not namespace zpl__
not word ZPL_IMPLEMENTATION // Macro exposure
//namespace ZPL_
//not word ZPL_IMPLEMENTATION
word cast, zpl_cast word cast, zpl_cast
word zpl_strncmp, str_compare word zpl_strncmp, str_compare
word zpl_strcmp, str_compare word zpl_strcmp, str_compare
// Undesired typedefs // Undesired typedefs
word zpl_i8, s8 word zpl_i8, s8
word zpl_i16, s16 word zpl_i16, s16
word zpl_i32, s32 word zpl_i32, s32
word zpl_i64, s64 word zpl_i64, s64
word zpl_u8, u8 word zpl_u8, u8
word zpl_u16, u16 word zpl_u16, u16
word zpl_u32, u32 word zpl_u32, u32
word zpl_u64, u64 word zpl_u64, u64
word zpl_intptr, sptr word zpl_intptr, sptr
word zpl_uintptr, uptr word zpl_uintptr, uptr
word zpl_usize, uw word zpl_usize, uw
word zpl_isize, sw word zpl_isize, sw
// Undesired exposures. // Undesired exposures.
//not word zpl_allocator //not word zpl_allocator
//not word zpl_arena //not word zpl_arena
not word zpl_array //not word zpl_array
//not word zpl_file //not word zpl_file
//not word zpl_list //not word zpl_list
//not word zpl_pool //not word zpl_pool
@ -47,6 +62,7 @@ not word zpl_array
// Conflicts with refactor // Conflicts with refactor
word arena, a_arena word arena, a_arena
word array, a_array
word alloc, a_allocator word alloc, a_allocator
word file, a_file word file, a_file
word file_size, fsize word file_size, fsize
@ -55,20 +71,20 @@ word opts, a_opts
word pool, a_pool word pool, a_pool
// Conflicts with std. (Uncomment if using c externs) // Conflicts with std. (Uncomment if using c externs)
//not word zpl_memchr not word zpl_memchr
//not word zpl_memmove not word zpl_memmove
//not word zpl_memset not word zpl_memset
//not word zpl_memswap not word zpl_memswap
//not word zpl_memcopy not word zpl_memcopy
//not word zpl_printf not word zpl_printf
//not word zpl_printf_va not word zpl_printf_va
//not word zpl_printf_err not word zpl_printf_err
//not word zpl_printf_err_va not word zpl_printf_err_va
//not word zpl_fprintf not word zpl_fprintf
//not word zpl_fprintf_va not word zpl_fprintf_va
//not word zpl_snprintf not word zpl_snprintf
//not word zpl_snprintf_va not word zpl_snprintf_va
//not word zpl_strchr not word zpl_strchr
//not word zpl_strlen not word zpl_strlen
//not word zpl_strnlen not word zpl_strnlen
//not word zpl_exit not word zpl_exit

167
project/Bloat.cpp Normal file
View File

@ -0,0 +1,167 @@
#define BLOAT_IMPL
#include "Bloat.hpp"
namespace Memory
{
static zpl_arena Global_Arena {};
void setup()
{
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), Initial_Reserve );
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);
}
}
bool opts_custom_add(zpl_opts* opts, zpl_opts_entry *t, char* b)
{
if (t->type != ZPL_OPTS_STRING)
{
return false;
}
t->text = zpl_string_append_length(t->text, " ", 1);
t->text = zpl_string_appendc( t->text, b );
return true;
}
b32 opts_custom_compile(zpl_opts *opts, int argc, char **argv)
{
zpl_b32 had_errors = false;
for (int i = 1; i < argc; ++i)
{
char* arg = argv[i];
if (*arg)
{
arg = (char*)zpl_str_trim(arg, false);
if (*arg == '-')
{
zpl_opts_entry* entry = 0;
zpl_b32 checkln = false;
if ( *(arg + 1) == '-')
{
checkln = true;
++arg;
}
char *b = arg + 1, *e = b;
while (zpl_char_is_alphanumeric(*e) || *e == '-' || *e == '_') {
++e;
}
entry = zpl__opts_find(opts, b, (e - b), checkln);
if (entry)
{
char *ob = b;
b = e;
/**/
if (*e == '=')
{
if (entry->type == ZPL_OPTS_FLAG)
{
*e = '\0';
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
b = e = e + 1;
}
else if (*e == '\0')
{
char *sp = argv[i+1];
if (sp && *sp != '-' && (zpl_array_count(opts->positioned) < 1 || entry->type != ZPL_OPTS_FLAG))
{
if (entry->type == ZPL_OPTS_FLAG)
{
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
arg = sp;
b = e = sp;
++i;
}
else
{
if (entry->type != ZPL_OPTS_FLAG)
{
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_MISSING_VALUE);
had_errors = true;
continue;
}
entry->met = true;
continue;
}
}
e = (char *)zpl_str_control_skip(e, '\0');
zpl__opts_set_value(opts, entry, b);
if ( (i + 1) < argc )
{
for ( b = argv[i + 1]; i < argc && b[0] != '-'; i++, b = argv[i + 1] )
{
opts_custom_add(opts, entry, b );
}
}
}
else
{
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_OPTION);
had_errors = true;
}
}
else if (zpl_array_count(opts->positioned))
{
zpl_opts_entry *l = zpl_array_back(opts->positioned);
zpl_array_pop(opts->positioned);
zpl__opts_set_value(opts, l, arg);
}
else
{
zpl__opts_push_error(opts, arg, ZPL_OPTS_ERR_VALUE);
had_errors = true;
}
}
}
return !had_errors;
}

146
project/IO.cpp Normal file
View File

@ -0,0 +1,146 @@
#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.
sw Current = -1;
char* Current_Content = nullptr;
uw Current_Size = 0;
uw Largest_Src_Size = 0;
zpl_arena MemSpec;
zpl_arena MemSrc;
}
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("IO::Prepare - 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 ( path++, left--, left > 1 );
uw persist_size = Largest_Src_Size * 2 + 8;
zpl_arena_init_from_allocator( & MemSrc, zpl_heap(), persist_size );
}
void cleanup()
{
zpl_arena_free( & MemSpec );
zpl_arena_free( & MemSrc );
}
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");
}
zpl_arena_init_from_allocator( & MemSpec, zpl_heap(), fsize * 3 + 8 );
char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & MemSpec), 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( & MemSpec ), content, false );
return lines;
}
char* get_next_source()
{
zpl_memset( MemSrc.physical_start, 0, MemSrc.total_allocated);
zpl_free_all( zpl_arena_allocator( & MemSrc) );
Current++;
zpl_file file {};
zpl_file_error error = zpl_file_open( & file, Sources[Current]);
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("IO::get_next_source - Could not open the source file: %s", Sources[Current]);
}
auto size = zpl_file_size( & file );
Current_Size = scast( sw, size );
if ( Current_Size <= 0 )
return nullptr;
Current_Content = rcast( char* , zpl_alloc( zpl_arena_allocator( & MemSrc), Current_Size + 1) );
zpl_file_read( & file, Current_Content, Current_Size );
zpl_file_close( & file );
Current_Content[Current_Size] = 0;
Current_Size++;
return Current_Content;
}
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 );
}
}

25
project/IO.hpp Normal file
View File

@ -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.
char* get_next_source();
// Writes the refactored content ot the current corresponding destination.
void write( zpl_string refactored );
}

41
project/Readme.md Normal file
View File

@ -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 a reasonable size for 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 for specific 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 triggering 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.

341
project/Spec.cpp Normal file
View File

@ -0,0 +1,341 @@
#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
{
// Custom comment signatures not supported yet (only C/C++ comments for now)
bool Ignore_Comments = false;
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( Tok& type, zpl_string& token, char*& line, u32& length )
{
zpl_string_clear( token );
length = 0;
#define current line[length]
if (type == Tok::Include)
{
// Allows for '.'
while ( zpl_char_is_alphanumeric( current )
|| current == '_'
|| current == '.'
|| current == '/'
|| current == '\\' )
{
length++;
}
}
else
{
while ( zpl_char_is_alphanumeric( current ) || current == '_' )
{
length++;
}
}
#undef current
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++;
do
{
char* line = * lines;
// Ignore line if its a comment
if ( line[0] == '/' && line[1] == '/')
{
continue;
}
// Remove indent
{
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
continue;
}
}
u32 length = 0;
Tok type = Tok::Num_Tok;
bool ignore = false;
Entry entry {};
log_fmt("\nIGNORE WORD COUNT: %d", zpl_array_count(Ignore_Words));
// Find a valid token
find_next_token( type, token, line, length );
// 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' )
{
continue;
}
// Find the category token
find_next_token( type, token, line, length );
}
if ( is_tok( Tok::Comment, token, length ) )
{
// Custom comment signatures not supported yet (only C/C++ comments for now)
Ignore_Comments = true;
continue;
}
else 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 );
continue;
}
// Find the first argument
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
continue;
}
find_next_token( type, 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;
}
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 )
{
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;
}
continue;
}
}
find_next_token( type, 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 );
continue;
case Tok::Namespace:
zpl_array_append( Namespaces, entry );
continue;
case Tok::Include:
zpl_array_append( Includes, entry );
continue;
}
}
while ( lines++, left--, left > 0 );
Spec::Entry* ignore = Spec::Ignore_Words;
sw ignores_left = zpl_array_count( Spec::Ignore_Words);
zpl_printf("\nIgnores: ");
for ( ; ignores_left; ignores_left--, ignore++ )
{
zpl_printf("\n%s", ignore->Sig);
}
zpl_printf("\n");
}
}

76
project/Spec.hpp Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include "Bloat.hpp"
namespace Spec
{
enum Tok
{
Not,
Comment,
Include,
Namespace,
Word,
Num_Tok
};
forceinline
char const* str_tok( Tok tok )
{
static
char const* tok_to_str[ Tok::Num_Tok ] =
{
"not",
"comments",
"include",
"namespace",
"word",
};
return tok_to_str[ tok ];
}
forceinline
char strlen_tok( Tok tok )
{
static
const u8 tok_to_len[ Tok::Num_Tok ] =
{
3,
8,
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();
}

View File

@ -1,13 +1,13 @@
/* /*
BLOAT. BLOAT.
ZPL requires ZPL_IMPLEMENTATION whereever this library is included.
This file assumes it will be included in one compilation unit.
*/ */
#pragma once #pragma once
#ifdef BLOAT_IMPL
# define ZPL_IMPLEMENTATION
#endif
#if __clang__ #if __clang__
# pragma clang diagnostic ignored "-Wunused-const-variable" # pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wswitch" # pragma clang diagnostic ignored "-Wswitch"
@ -33,14 +33,13 @@
// # define ZPL_MODULE_REGEX // # define ZPL_MODULE_REGEX
// # define ZPL_MODULE_EVENT // # define ZPL_MODULE_EVENT
// # define ZPL_MODULE_DLL // # define ZPL_MODULE_DLL
# define ZPL_MODULE_OPTS # define ZPL_MODULE_OPTS
// # define ZPL_MODULE_PROCESS // # define ZPL_MODULE_PROCESS
// # define ZPL_MODULE_MAT // # define ZPL_MODULE_MAT
// # define ZPL_MODULE_THREADING // # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS // # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER // # define ZPL_MODULE_PARSER
#include "zpl.h" #include "zpl.h"
// }
#if __clang__ #if __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
@ -59,18 +58,19 @@
#define rcast( Type_, Value_ ) reinterpret_cast< Type_ >( Value_ ) #define rcast( Type_, Value_ ) reinterpret_cast< Type_ >( Value_ )
#define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) ) #define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) )
#define do_once() \ #define do_once() \
do \ do \
{ \ { \
static \ static \
bool Done = true; \ bool Done = false; \
if ( Done ) \ if ( Done ) \
return; \ return; \
Done = false; \ Done = true; \
} \ } \
while(0) \ while(0) \
using b32 = zpl_b32;
using s8 = zpl_i8; using s8 = zpl_i8;
using s32 = zpl_i32; using s32 = zpl_i32;
using s64 = zpl_i64; using s64 = zpl_i64;
@ -81,39 +81,39 @@ using f64 = zpl_f64;
using uw = zpl_usize; using uw = zpl_usize;
using sw = zpl_isize; using sw = zpl_isize;
using Line = char*;
using Array_Line = zpl_array( Line );
ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED"; ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
namespace Memory namespace Memory
{ {
zpl_arena Global_Arena {}; ct uw Initial_Reserve = zpl_megabytes(2);
extern zpl_arena Global_Arena;
#define g_allocator zpl_arena_allocator( & Memory::Global_Arena) #define g_allocator zpl_arena_allocator( & Memory::Global_Arena)
void setup() void setup();
{ void resize( uw new_size );
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) ); void cleanup();
if ( Global_Arena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void cleanup()
{
zpl_arena_free( & Global_Arena);
}
} }
sw log_fmt(char const *fmt, ...) // Had to be made to support multiple sub-arguments per "opt" argument.
{ b32 opts_custom_compile(zpl_opts *opts, int argc, char **argv);
inline
sw log_fmt(char const *fmt, ...)
{
#if Build_Debug #if Build_Debug
sw res; sw res;
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
res = zpl_printf_va(fmt, va); res = zpl_printf_va(fmt, va);
va_end(va); va_end(va);
return res; return res;
#else #else
@ -121,6 +121,7 @@ namespace Memory
#endif #endif
} }
inline
void fatal(char const *fmt, ...) void fatal(char const *fmt, ...)
{ {
zpl_local_persist zpl_thread_local zpl_local_persist zpl_thread_local
@ -139,6 +140,6 @@ void fatal(char const *fmt, ...)
zpl_printf_err_va( fmt, va); zpl_printf_err_va( fmt, va);
va_end(va); va_end(va);
exit(1); zpl_exit(1);
#endif #endif
} }

File diff suppressed because it is too large Load Diff

63
refactor.10x Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.*,</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate,.git,.idea,.vscode,</ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<ShowEmptyFolders>true</ShowEmptyFolders>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand></BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand></CleanCommand>
<BuildWorkingDirectory></BuildWorkingDirectory>
<CancelBuild></CancelBuild>
<RunCommand></RunCommand>
<DebugCommand></DebugCommand>
<ExePathCommand></ExePathCommand>
<DebugSln></DebugSln>
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
</Platforms>
<AdditionalIncludePaths>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\ATLMFC\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
</AdditionalIncludePaths>
<Defines>
<Define></Define>
</Defines>
<ConfigProperties>
<ConfigAndPlatform>
<Name>Debug:x64</Name>
<Defines></Defines>
<ForceIncludes>
<ForceInclude>./project</ForceInclude>
<ForceInclude>./thirdparty</ForceInclude>
</ForceIncludes>
</ConfigAndPlatform>
<Config>
<Name>Debug</Name>
<Defines></Defines>
</Config>
<Platform>
<Name>x64</Name>
<Defines></Defines>
</Platform>
</ConfigProperties>
<Children></Children>
</Workspace>
</N10X>

View File

@ -42,46 +42,39 @@ if ( $type )
Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_scripts Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_scripts
} }
#endregion Regular Build
#region Test Build
write-host "`n`nBuilding Test`n"
if ( -not( Test-Path $path_build ) )
{
return;
}
$args_ninja = @() $args_ninja = @()
$args_ninja += "-C" $args_ninja += "-C"
$args_ninja += $path_build $args_ninja += $path_build
Start-Process ninja $args_ninja -Wait -NoNewWindow -WorkingDirectory $path_root Start-Process ninja $args_ninja -Wait -NoNewWindow -WorkingDirectory $path_root
#endregion Regular Build
# Refactor thirdparty libraries
& .\refactor_and_format.ps1
if ( $test -eq $false ) if ( $test -eq $true )
{ {
return; #region Test Build
write-host "`n`nBuilding Test`n"
# Refactor thirdparty libraries
& .\refactor_and_format.ps1
$path_test = Join-Path $path_root test
$path_test_build = Join-Path $path_test build
if ( -not( Test-Path $path_test_build ) )
{
$args_meson = @()
$args_meson += "setup"
$args_meson += $path_test_build
Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_test
}
$args_ninja = @()
$args_ninja += "-C"
$args_ninja += $path_test_build
Start-Process ninja $args_ninja -Wait -NoNewWindow -WorkingDirectory $path_test
#endregion Test Build
} }
$path_test = Join-Path $path_root test
$path_test_build = Join-Path $path_test build
if ( -not( Test-Path $path_test_build ) )
{
$args_meson = @()
$args_meson += "setup"
$args_meson += $path_test_build
Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_scripts
}
$args_ninja = @()
$args_ninja += "-C"
$args_ninja += $path_build
Start-Process ninja $args_ninja -Wait -NoNewWindow -WorkingDirectory $path_test
#endregion Test Build

View File

@ -12,3 +12,10 @@ if ( Test-Path $path_test_build )
{ {
Remove-Item $path_test_build -Recurse Remove-Item $path_test_build -Recurse
} }
[string[]] $include = '*.h', '*.hpp', '*.cpp'
[string[]] $exclude =
$files = Get-ChildItem -Recurse -Path $path_test -Include $include -Exclude $exclude
Remove-Item $files

View File

@ -1,5 +1,5 @@
[string[]] $include = '*.c', '*.cc', '*.cpp' [string[]] $include = 'refactor.cpp' #'*.c', '*.cc', '*.cpp'
# [stirng[]] $exclude = # [string[]] $exclude =
$path_root = git rev-parse --show-toplevel $path_root = git rev-parse --show-toplevel
$path_proj = Join-Path $path_root project $path_proj = Join-Path $path_root project

View File

@ -1,4 +1,4 @@
project( 'refactor', 'c', 'cpp', default_options : ['buildtype=debug'] ) project( 'refactor', 'c', 'cpp', default_options : ['buildtype=release'] )
# add_global_arguments('-E', language : 'cpp') # add_global_arguments('-E', language : 'cpp')

View File

@ -1,9 +1,10 @@
[string[]] $include = '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp' [string[]] $include = '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp'
[string[]] $exclude = '*.g.*', '*.refactor', 'bloat.refactored.hpp', 'refactor.refactored.cpp' [string[]] $exclude = '*.g.*', '*.refactor'
$path_root = git rev-parse --show-toplevel $path_root = git rev-parse --show-toplevel
$path_build = Join-Path $path_root build $path_build = Join-Path $path_root build
$path_project = Join-Path $path_root project
$path_test = Join-Path $path_root test $path_test = Join-Path $path_root test
$path_thirdparty = Join-Path $path_root thirdparty $path_thirdparty = Join-Path $path_root thirdparty
@ -11,25 +12,48 @@ $file_spec = Join-Path $path_test zpl.refactor
$refactor = Join-Path $path_build refactor.exe $refactor = Join-Path $path_build refactor.exe
# Gather the files to be formatted. # Gather the files to be formatted.
$targetFiles = @(Get-ChildItem -Recurse -Path $path_thirdparty -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName) $targetFiles = @(Get-ChildItem -Recurse -Path $path_thirdparty -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
$refactoredFiles = @()
write-host "Beginning refactor...`n"
$refactors = @(@())
foreach ( $file in $targetFiles ) foreach ( $file in $targetFiles )
{ {
$destination = Join-Path $path_test (Split-Path $file -leaf) $destination = Join-Path $path_test (Split-Path $file -leaf)
$destination = $destination.Replace( '.h', '.refactored.h' ) $destination = $destination.Replace( '.h', '.refactored.h' )
$destination = $destination.Replace( '.c', '.refactored.c' )
$refactoredFiles += $destination
}
write-host "Beginning thirdpary refactor...`n"
$refactors = @(@())
if ( $false ){
foreach ( $file in $targetFiles )
{
$destination = Join-Path $path_test (Split-Path $file -leaf)
$destination = $destination.Replace( '.h', '.refactored.h' )
$refactorParams = @(
"-src=$($file)",
"-dst=$($destination)"
"-spec=$($file_spec)"
)
$refactors += (Start-Process $refactor $refactorParams -NoNewWindow -PassThru)
}
}
else {
$refactorParams = @( $refactorParams = @(
"-src=$($file)", "-debug",
"-dst=$($destination)" "-num=$($targetFiles.Count)"
"-src=$($targetFiles)",
"-dst=$($refactoredFiles)",
"-spec=$($file_spec)" "-spec=$($file_spec)"
) )
$refactors += (Start-Process $refactor $refactorParams -NoNewWindow -PassThru) Start-Process $refactor $refactorParams -NoNewWindow -PassThru -Wait
} }
foreach ( $process in $refactors ) foreach ( $process in $refactors )
@ -42,10 +66,40 @@ foreach ( $process in $refactors )
Write-Host "`nRefactoring complete`n`n" Write-Host "`nRefactoring complete`n`n"
write-host "Beginning project refactor...`n"
# Gather the files to be formatted.
$targetFiles = @(Get-ChildItem -Recurse -Path $path_project -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
$refactoredFiles = @()
$file_spec = Join-Path $path_test project.refactor
write-host "FILE SPEC:" $file_spec
foreach ( $file in $targetFiles )
{
$destination = Join-Path $path_test (Split-Path $file -leaf)
$destination = $destination.Replace( '.hpp', '.refactored.hpp' )
$destination = $destination.Replace( '.cpp', '.refactored.cpp' )
$refactoredFiles += $destination
}
$refactorParams = @(
"-debug",
"-num=$($targetFiles.Count)"
"-src=$($targetFiles)",
"-dst=$($refactoredFiles)",
"-spec=$($file_spec)"
)
Start-Process $refactor $refactorParams -NoNewWindow -PassThru -Wait
write-host "`nRefactoring complete`n`n"
# Can't format zpl library... (It hangs clang format) # Can't format zpl library... (It hangs clang format)
if ( $false ) if ( $false ) {
{
Write-Host "Beginning format...`n" Write-Host "Beginning format...`n"
# Format the files. # Format the files.