WIP - Got it somewhat working, still have issues with multiple files.

This commit is contained in:
Edward R. Gonzalez 2023-03-17 18:12:20 -04:00
parent 7e120ae5e9
commit 97967e56d9
15 changed files with 356 additions and 1089 deletions

27
.vscode/launch.json vendored
View File

@ -13,13 +13,34 @@
"-src=./thirdparty/zpl.h",
"-dst=./Test/zpl.refactored.h",
"-spec=./Test/zpl.h.refactor"
"-spec=./Test/zpl.refactor"
],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"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",
"type": "cppvsdbg",
@ -29,7 +50,7 @@
"-source=./refactor.cpp",
"-destination=./Test/refactor.cpp",
"-specification=./Test/zpl.h.refactor"
"-specification=./Test/zpl.refactor"
],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",

View File

@ -2,14 +2,14 @@
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
* `-dst` : Destination file after the refactor (omit to use the same as source)
* `-spec` : Specification containing rules to use for the refactor.
Syntax :
## Syntax :
* `not` Omit word or namespace.
* `include` Preprocessor include <file> related identifiers.
@ -30,7 +30,7 @@ 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**
### 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).
@ -40,6 +40,8 @@ Make sure to have the code backed up on a VCS or in some other way.
* 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:
* Possibly come up with a better name.
* Test to see how much needs to be ported for other platforms (if at all)
* Setup as api.
* Provide binaries in the release page for github. (debug and release builds)

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(1) );
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
}

0
Test/project.refactor Normal file
View File

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,17 @@
__VERSION 1
// not : Ignore
// word : Alphanumeric or underscore
// regex : Unavailable in __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
// Header files
not word zpl_hedley
not include zpl_hedley
//not word zpl_hedley
// Removes the namespace.
namespace zpl_
@ -16,30 +19,32 @@ namespace zpl_
// Don't expose internals
not namespace zpl__
not word ZPL_IMPLEMENTATION
// Macro exposure
//namespace ZPL_
//not word ZPL_IMPLEMENTATION
word cast, zpl_cast
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_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
word zpl_usize, uw
word zpl_isize, sw
// Undesired exposures.
//not word zpl_allocator
//not word zpl_arena
not word zpl_array
//not word zpl_array
//not word zpl_file
//not word zpl_list
//not word zpl_pool
@ -47,6 +52,7 @@ not word zpl_array
// Conflicts with refactor
word arena, a_arena
word array, a_array
word alloc, a_allocator
word file, a_file
word file_size, fsize

View File

@ -1,5 +1,5 @@
#define BLOAT_IMPL
#include "bloat.hpp"
#include "Bloat.hpp"
@ -35,3 +35,133 @@ namespace Memory
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 = cast(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 = cast(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;
}

View File

@ -13,23 +13,12 @@ namespace IO
// Current source and destination index.
// Used to keep track of which file get_next_source or write refer to.
uw Current = 0;
sw Current = -1;
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;
@ -48,7 +37,7 @@ namespace IO
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("Could not open source file: %s", *path );
fatal("IO::Prepare - Could not open source file: %s", *path );
}
const sw fsize = zpl_file_size( & src );
@ -60,18 +49,16 @@ namespace IO
zpl_file_close( & src );
}
while ( --left );
while ( left--, left > 1 );
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()
@ -102,25 +89,24 @@ namespace IO
return lines;
}
Array_Line get_next_source()
char* 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;
Current++;
zpl_file file {};
zpl_file_error error = zpl_file_open( & file, Specification);
zpl_file_error error = zpl_file_open( & file, Sources[Current]);
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("Could not open the source file: %s", Sources[Current]);
fatal("IO::get_next_source - Could not open the source file: %s", Sources[Current]);
}
Current_Size = scast( sw, zpl_file_size( & file ) );
auto size = zpl_file_size( & file );
Current_Size = scast( sw, size );
if ( Current_Size <= 0 )
return nullptr;
@ -133,8 +119,7 @@ namespace IO
Current_Content[Current_Size] = 0;
Current_Size++;
Array_Line lines = zpl_str_split_lines( zpl_arena_allocator( & MemPerist), Current_Content, ' ' );
return lines;
return Current_Content;
}
void write( zpl_string refacotred )

View File

@ -1,6 +1,6 @@
#pragma once
#include "bloat.hpp"
#include "Bloat.hpp"
namespace IO
@ -18,7 +18,7 @@ namespace IO
Array_Line get_specification();
// Provides the content of the next source, broken up as a series of lines.
Array_Line get_next_source();
char* get_next_source();
// Writes the refactored content ot the current corresponding destination.
void write( zpl_string refactored );

View File

@ -38,4 +38,4 @@ The `Path_Size_Largest` and `Token_Max_Length` are compile-time constraints that
`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.
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.

View File

@ -96,8 +96,6 @@ namespace Spec
left--;
lines++;
char token[ Token_Max_Length ];
do
{
char* line = * lines;

View File

@ -5,7 +5,7 @@
#pragma once
#ifdef BLOAT_IMPL
# define ZPL_IMPLEMEntATION
# define ZPL_IMPLEMENTATION
#endif
#if __clang__
@ -70,6 +70,7 @@ do \
while(0) \
using b32 = zpl_b32;
using s8 = zpl_i8;
using s32 = zpl_i32;
using s64 = zpl_i64;
@ -97,6 +98,9 @@ namespace Memory
void cleanup();
}
// 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, ...)
{

View File

@ -1,5 +1,4 @@
#define BLOAT_IMPL
#include "bloat.hpp"
#include "Bloat.cpp"
#include "IO.cpp"
#include "Spec.cpp"
@ -16,7 +15,7 @@ void parse_options( int num, char** arguments )
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);
if (zpl_opts_compile( & opts, num, arguments))
if (opts_custom_compile( & opts, num, arguments))
{
sw num = 0;
@ -36,7 +35,12 @@ void parse_options( int num, char** arguments )
else
{
num = 1;
zpl_array_init_reserve( IO::Sources, g_allocator, 1 );
zpl_array_init_reserve( IO::Destinations, g_allocator, 1 );
}
zpl_printf("NUM IS: %d", num);
if ( zpl_opts_has_arg( & opts, "src" ) )
{
@ -44,7 +48,8 @@ void parse_options( int num, char** arguments )
if ( num == 1 )
{
IO::Sources[0] = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) );
zpl_string path = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt ));
zpl_array_append( IO::Sources, path );
}
else
{
@ -60,9 +65,10 @@ void parse_options( int num, char** arguments )
{
path[length] = *opt;
}
while ( length++, opt++, *opt != ' ' );
while ( length++, opt++, *opt != ' ' && *opt != '\0' );
IO::Sources[num - left] = zpl_string_make_length( g_allocator, path, length );
zpl_string path_string = zpl_string_make_length( g_allocator, path, length );
zpl_array_append( IO::Sources, path_string );
opt++;
}
@ -71,7 +77,7 @@ void parse_options( int num, char** arguments )
}
else
{
fatal( "-source not provided\n" );
fatal( "-src not provided\n" );
}
if ( zpl_opts_has_arg( & opts, "dst" ) )
@ -80,7 +86,8 @@ void parse_options( int num, char** arguments )
if ( num == 1 )
{
IO::Destinations[0] = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) );
zpl_string path = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) );
zpl_array_append( IO::Destinations, path );
}
else
{
@ -96,15 +103,30 @@ void parse_options( int num, char** arguments )
{
path[length] = *opt;
}
while ( length++, opt++, *opt != ' ' );
while ( length++, opt++, *opt != ' ' && *opt != '\0' );
IO::Destinations[num - left] = zpl_string_make_length( g_allocator, path, length );
zpl_string path_string = zpl_string_make_length( g_allocator, path, length );
zpl_array_append( IO::Destinations, path_string );
opt++;
}
while ( --left );
if ( zpl_array_count(IO::Destinations) != zpl_array_count( IO::Sources ) )
{
fatal("-dst count must match -src count");
}
}
}
else
{
uw left = num;
do
{
zpl_array_append( IO::Destinations, IO::Sources[num - left] );
}
while ( --left );
}
if ( zpl_opts_has_arg( & opts, "spec" ) )
{
@ -113,9 +135,18 @@ void parse_options( int num, char** arguments )
IO::Specification = zpl_string_make( g_allocator, "" );
IO::Specification = zpl_string_append( IO::Specification, opt );
}
else
{
fatal( "-spec not provided\n" );
}
}
else
{
zpl_printf("\nArguments: ");
for ( int index = 0; index < num; index++)
{
zpl_printf("\nArg[%d]: %s", index, arguments[index]);
}
fatal( "Failed to parse arguments\n" );
}
@ -127,7 +158,7 @@ zpl_arena Refactor_Buffer;
void refactor()
{
ct char const* include_sig = "#include \"";
ct static char const* include_sig = "#include \"";
struct Token
{
@ -157,61 +188,62 @@ void refactor()
}
// Prepare data and trackers.
Array_Line src = IO::get_next_source();
Array_Line lines = src;
char const* src = IO::get_next_source();
if ( src == nullptr )
return;
const sw num_lines = zpl_array_count( lines);
log_fmt("\n\nRefactoring: %s", IO::Sources[IO::Current]);
sw buffer_size = IO::Current_Size;
sw left = num_lines;
Line line = *lines;
uw pos = 0;
sw left = buffer_size;
uw col = 0;
uw line = 0;
#define pos (IO::Current_Size - left)
#define move_forward( Amount_ ) \
left -= Amount_; \
col += Amount_; \
src += Amount_ \
do
{
Continue_Line:
// Includes to ignore
{
Spec::Entry* ignore = Spec::Ignore_Words;
sw ignores_left = zpl_array_count( Spec::Ignore_Words);
Spec::Entry* ignore = Spec::Ignore_Includes;
sw ignores_left = zpl_array_count( Spec::Ignore_Includes);
do
for ( ; ignores_left; ignores_left--, ignore++ )
{
if ( include_sig[0] != line[0] )
if ( include_sig[0] != src[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 );
current = zpl_string_append_length( current, src, sig_length );
current = zpl_string_append_length( current, "\"", 1 );
// Formats current into: #include "<ignore->Sig>"
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
log_fmt("\nIgnored %-81s line %d", current, num_lines - left );
log_fmt("\nIgnored %-81s line %d, col %d", current, line, col );
const sw length = zpl_string_length( current );
line += length;
pos += length;
move_forward( length );
// Force end of line.
while ( line != '\0' )
while ( src[0] != '\n' )
{
line++;
pos++;
move_forward( 1 );
}
goto Skip;
}
}
while ( ignore++, --ignores_left );
}
// Word Ignores
@ -219,20 +251,20 @@ void refactor()
Spec::Entry* ignore = Spec::Ignore_Words;
sw ignores_left = zpl_array_count( Spec::Ignore_Words);
do
for ( ; ignores_left; ignores_left--, ignore++ )
{
if ( ignore->Sig[0] != line[0] )
if ( ignore->Sig[0] != src[0] )
continue;
zpl_string_clear( current );
u32 sig_length = zpl_string_length( ignore->Sig );
current = zpl_string_append_length( current, line, sig_length );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
char before = line[-1];
char after = line[sig_length];
char before = src[-1];
char after = src[sig_length];
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|| zpl_char_is_alphanumeric( after ) || after == '_' )
@ -240,14 +272,12 @@ void refactor()
continue;
}
log_fmt("\nIgnored %-81s line %d", current, num_lines - left );
log_fmt("\nIgnored %-81s line %d, col %d", current, line, col );
line += sig_length;
pos += sig_length;
move_forward( sig_length );
goto Skip;
}
}
while ( ignore++, --ignores_left );
}
// Namespace Ignores
@ -255,20 +285,23 @@ void refactor()
Spec::Entry* ignore = Spec::Ignore_Namespaces;
sw ignores_left = zpl_array_count( Spec::Ignore_Namespaces);
do
for ( ; ignores_left; ignores_left--, ignore++ )
{
if ( ignore->Sig[0] != line[0] )
if ( ignore->Sig[0] != src[0] )
{
ignore++;
continue;
}
zpl_string_clear( current );
u32 sig_length = zpl_string_length( ignore->Sig );
current = zpl_string_append_length( current, line, sig_length );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
u32 length = sig_length;
char* ns_content = line + sig_length;
u32 length = sig_length;
char const* ns_content = src + sig_length;
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
@ -278,16 +311,14 @@ void refactor()
#if Build_Debug
zpl_string_clear( preview );
preview = zpl_string_append_length( preview, line, length );
log_fmt("\nIgnored %-40s %-40s line %d", preview, ignore->Sig, - left);
preview = zpl_string_append_length( preview, src, length );
log_fmt("\nIgnored %-40s %-40s line %d, column %d", preview, ignore->Sig, line, col );
#endif
line += length;
pos += length;
move_forward( length );
goto Skip;
}
}
while ( ignore++, --ignores_left );
}
// Includes to match
@ -296,16 +327,16 @@ void refactor()
sw includes_left = zpl_array_count ( Spec::Includes);
do
for ( ; includes_left; includes_left--, include++ )
{
if ( include_sig[0] != line[0] )
if ( include_sig[0] != src[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 );
current = zpl_string_append_length( current, src, sig_length );
current = zpl_string_append_length( current, "\"", 1 );
// Formats current into: #include "<ignore->Sig>"
if ( zpl_string_are_equal( include->Sig, current ) )
@ -326,22 +357,19 @@ void refactor()
zpl_array_append( tokens, entry );
log_fmt("\nFound %-81s line %d", current, num_lines - left);
log_fmt("\nFound %-81s line %d, column %d", current, line, col );
line += length;
pos += length;
move_forward( length );
// Force end of line.
while ( line != '\0' )
while ( src[0] != '\0' )
{
line++;
pos++;
move_forward( 1 );
}
goto Skip;
}
}
while ( include++, --includes_left );
}
// Words to match
@ -349,20 +377,20 @@ void refactor()
Spec::Entry* word = Spec::Words;
sw words_left = zpl_array_count ( Spec::Words);
do
for ( ; words_left; words_left--, word++ )
{
if ( word->Sig[0] != line[0] )
if ( word->Sig[0] != src[0] )
continue;
zpl_string_clear( current );
sw sig_length = zpl_string_length( word->Sig);
current = zpl_string_append_length( current, line, sig_length );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( word->Sig, current ) )
{
char before = line[-1];
char after = line[sig_length];
char before = src[-1];
char after = src[sig_length];
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|| zpl_char_is_alphanumeric( after ) || after == '_' )
@ -384,14 +412,12 @@ void refactor()
zpl_array_append( tokens, entry );
log_fmt("\nFound %-81s line %d", current, num_lines - left);
log_fmt("\nFound %-81s line %d, column %d", current, line, col );
line += sig_length;
pos += sig_length;
move_forward( sig_length );
goto Skip;
}
}
while ( word++, --words_left );
}
// Namespaces to match
@ -400,20 +426,20 @@ void refactor()
sw nspaces_left = zpl_array_count( Spec::Namespaces);
do
for ( ; nspaces_left; nspaces_left--, nspace++ )
{
if ( nspace->Sig[0] != line[0] )
if ( nspace->Sig[0] != src[0] )
continue;
zpl_string_clear( current );
u32 sig_length = zpl_string_length( nspace->Sig );
current = zpl_string_append_length( current, line, sig_length );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( nspace->Sig, current ) )
{
u32 length = sig_length;
char* ns_content = line + sig_length;
u32 length = sig_length;
char const* ns_content = src + sig_length;
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
@ -439,26 +465,29 @@ void refactor()
#if Build_Debug
zpl_string_clear( preview );
preview = zpl_string_append_length( preview, line, length);
log_fmt("\nFound %-40s %-40s line %d", preview, nspace->Sig, num_lines - left);
preview = zpl_string_append_length( preview, src, length);
log_fmt("\nFound %-40s %-40s line %d, column %d", preview, nspace->Sig, line, col );
#endif
line += length;
pos += length;
move_forward( length );
goto Skip;
}
}
while ( nspace++, --nspaces_left );
}
Skip:
if ( line != '\0' )
goto Continue_Line;
if ( src[0] == '\n' )
{
line++;
col = 0;
}
src++;
}
while ( lines++, line = *lines, left );
while ( --left );
// Prep data for building the content
left = IO::Current_Size;
left = zpl_array_count( tokens);
char* content = IO::Current_Content;
@ -475,17 +504,19 @@ void refactor()
sw sig_length = zpl_string_length( entry->Sig );
// Append between tokens
refactored = zpl_string_append_length( refactored, line, segment_length );
line += segment_length + sig_length;
refactored = zpl_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 = zpl_string_append( refactored, entry->Sub );
{
refactored = zpl_string_append( refactored, entry->Sub );
}
refactored = zpl_string_append_length( refactored, line, segment_length );
line += segment_length;
refactored = zpl_string_append_length( refactored, content, segment_length );
content += segment_length;
previous_end = entry->End;
entry++;
@ -496,11 +527,13 @@ void refactor()
if ( entry->End < IO::Current_Size )
{
refactored = zpl_string_append_length( refactored, line, IO::Current_Size - entry->End );
refactored = zpl_string_append_length( refactored, content, IO::Current_Size - 1 - entry->End );
}
}
IO::write( refactored );
zpl_string_clear( refactored );
}
int main( int num, char** arguments )
@ -520,6 +553,8 @@ int main( int num, char** arguments )
do
{
refactor();
zpl_printf("\nRefactored: %s", IO::Sources[IO::Current]);
}
while ( --left );

View File

@ -42,46 +42,39 @@ if ( $type )
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 += "-C"
$args_ninja += $path_build
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 -and (Test-Path $path_build) )
{
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_scripts
}
$args_ninja = @()
$args_ninja += "-C"
$args_ninja += $path_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

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