mirror of
https://github.com/Ed94/refactor.git
synced 2024-12-22 15:04:45 -08:00
First working prototype.
TODO: I need to cleanup memory.
This commit is contained in:
commit
581afa9154
40
.vscode/launch.json
vendored
Normal file
40
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Refactor ZPL",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/build/refactor.exe",
|
||||||
|
"args": [
|
||||||
|
"-source=./thirdparty/zpl.h",
|
||||||
|
"-destination=./Test/zpl.refactored.h",
|
||||||
|
|
||||||
|
"-specification=./Test/zpl.h.refactor"
|
||||||
|
],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"environment": [],
|
||||||
|
"console": "externalTerminal"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"name": "Refactor refactor.c",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/build/refactor.exe",
|
||||||
|
"args": [
|
||||||
|
"-source=./refactor.cpp",
|
||||||
|
"-destination=./Test/refactor.cpp",
|
||||||
|
|
||||||
|
"-specification=./Test/zpl.h.refactor"
|
||||||
|
],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"environment": [],
|
||||||
|
"console": "externalTerminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
Readme.md
Normal file
23
Readme.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# refactor
|
||||||
|
|
||||||
|
A code identifier refactoring app. Intended for c/c++ like identifiers.
|
||||||
|
|
||||||
|
Parameters :
|
||||||
|
|
||||||
|
* `-source`, `-src` : Source file to refactor
|
||||||
|
* `-destination`, `-dst` : Destination file after the refactor (omit to use the same as source)
|
||||||
|
* `-specification`, `-spec` : Specification containing rules to use for the refactor.
|
||||||
|
|
||||||
|
Syntax :
|
||||||
|
|
||||||
|
* `not` Omit word or namespace.
|
||||||
|
* `word` Fixed sized identifier.
|
||||||
|
* `namespace` Variable sized identifiers, mainly intended to redefine c-namespace of an identifier.
|
||||||
|
* `,` is used to delimit arguments to word or namespace.
|
||||||
|
* `L-Value` is the signature to modify.
|
||||||
|
* `R-Value` is the substitute ( only available if rule does not use `not` keyword )
|
||||||
|
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* Possibly come up with a better name.
|
||||||
|
* Cleanup memory usage (it hogs quite a bit or what it does..)
|
117
Test/bloat.hpp
Normal file
117
Test/bloat.hpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
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_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) \
|
||||||
|
|
||||||
|
|
||||||
|
using c8 = char;
|
||||||
|
using u8 = zpl_u8;
|
||||||
|
using u16 = zpl_u16;
|
||||||
|
using u32 = zpl_u32;
|
||||||
|
using u64 = zpl_u64;
|
||||||
|
using s8 = zpl_i8;
|
||||||
|
using s16 = zpl_i16;
|
||||||
|
using s32 = zpl_i32;
|
||||||
|
using s64 = zpl_i64;
|
||||||
|
using uw = zpl_usize;
|
||||||
|
using sw = zpl_isize;
|
||||||
|
|
||||||
|
|
||||||
|
ct c8 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 )
|
||||||
|
{
|
||||||
|
assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
arena_free( & Global_Arena);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fatal()
|
||||||
|
{
|
||||||
|
Memory::cleanup();
|
||||||
|
assert_crash("FATAL");
|
||||||
|
}
|
13
Test/meson.build
Normal file
13
Test/meson.build
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
project( 'refactor', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
||||||
|
|
||||||
|
# add_global_arguments('-E', language : 'cpp')
|
||||||
|
|
||||||
|
if get_option('buildtype').startswith('debug')
|
||||||
|
|
||||||
|
add_project_arguments('-DBuild_Debug', language : 'cpp')
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
executable( 'refactor', 'refactor.cpp' )
|
||||||
|
|
775
Test/refactor.cpp
Normal file
775
Test/refactor.cpp
Normal file
@ -0,0 +1,775 @@
|
|||||||
|
#define ZPL_IMPLEMENTATION
|
||||||
|
#include "bloat.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace File
|
||||||
|
{
|
||||||
|
string Source = nullptr;
|
||||||
|
string Destination = nullptr;
|
||||||
|
|
||||||
|
file_contents Content {};
|
||||||
|
|
||||||
|
zpl_arena Buffer;
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void read()
|
||||||
|
{
|
||||||
|
zpl_file file_src = {};
|
||||||
|
|
||||||
|
Content.allocator = g_allocator;
|
||||||
|
|
||||||
|
file_error error_src = file_open( & file_src, Source );
|
||||||
|
|
||||||
|
if ( error_src == ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_isize fsize = zpl_cast(zpl_isize) file_size( & file_src);
|
||||||
|
|
||||||
|
if ( fsize > 0 )
|
||||||
|
{
|
||||||
|
arena_init_from_allocator( & Buffer, heap(), (fsize % 64) * 2 );
|
||||||
|
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open source file: %s\n", Source );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(string refactored)
|
||||||
|
{
|
||||||
|
if ( refactored == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_file file_dest {};
|
||||||
|
file_error error = file_create( & file_dest, Destination );
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open destination file: %s\n", Destination );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
file_write( & file_dest, refactored, string_length(refactored) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Spec
|
||||||
|
{
|
||||||
|
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
|
||||||
|
c8 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
|
||||||
|
};
|
||||||
|
|
||||||
|
zpl_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 )
|
||||||
|
{
|
||||||
|
zpl_printf("Failed to find valid initial token");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
token = string_append_length( token, line, length );
|
||||||
|
line += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process()
|
||||||
|
{
|
||||||
|
char* content;
|
||||||
|
|
||||||
|
zpl_array(char*) lines;
|
||||||
|
|
||||||
|
// Get the contents of the file.
|
||||||
|
{
|
||||||
|
zpl_file file {};
|
||||||
|
file_error error = file_open( & file, File);
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf("Could not open the specification file: %s", File);
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
sw fsize = scast( sw, file_size( & file ) );
|
||||||
|
|
||||||
|
if ( fsize <= 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("No content in specificaiton to process");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
zpl_printf("Spec::process: lines array imporoperly setup");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_printf("Specification Line: %d is missing valid keyword", array_count(lines) - left);
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// bool match = false;
|
||||||
|
// if ( str_compare( "zpl_printf", current, sig_length ) == 0 )
|
||||||
|
// {
|
||||||
|
// match = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ( string_are_equal( ignore->Sig, current ) )
|
||||||
|
{
|
||||||
|
char after = content[sig_length];
|
||||||
|
|
||||||
|
if ( char_is_alphanumeric( after ) || after == '_' )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_printf("\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 );
|
||||||
|
zpl_printf("\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 after = content[sig_length];
|
||||||
|
|
||||||
|
if ( 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 );
|
||||||
|
|
||||||
|
zpl_printf("\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);
|
||||||
|
zpl_printf("\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.
|
||||||
|
zpl_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 )
|
||||||
|
{
|
||||||
|
zpl_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
|
||||||
|
{
|
||||||
|
zpl_printf( "-source not provided\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
zpl_printf( "Failed to parse arguments\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
68
Test/zpl.h.refactor
Normal file
68
Test/zpl.h.refactor
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
__VERSION 1
|
||||||
|
|
||||||
|
// not : Ignore
|
||||||
|
// word : Alphanumeric or underscore
|
||||||
|
// regex : Unavailable in __VERSION 1.
|
||||||
|
|
||||||
|
// Precedence (highest to lowest):
|
||||||
|
// word, namespace, regex
|
||||||
|
|
||||||
|
// Header files
|
||||||
|
not word zpl_hedley
|
||||||
|
|
||||||
|
// Removes the namespace.
|
||||||
|
namespace zpl_
|
||||||
|
|
||||||
|
// Don't expose internals
|
||||||
|
not namespace zpl__
|
||||||
|
|
||||||
|
not word ZPL_IMPLEMENTATION
|
||||||
|
|
||||||
|
word cast, zpl_cast
|
||||||
|
word zpl_strncmp, str_compare
|
||||||
|
word zpl_strcmp, str_compare
|
||||||
|
|
||||||
|
// Undesired typedefs
|
||||||
|
not word zpl_i8
|
||||||
|
not word zpl_i16
|
||||||
|
not word zpl_i32
|
||||||
|
not word zpl_i64
|
||||||
|
not word zpl_u8
|
||||||
|
not word zpl_u16
|
||||||
|
not word zpl_u32
|
||||||
|
not word zpl_u64
|
||||||
|
not word zpl_intptr
|
||||||
|
not word zpl_uintptr
|
||||||
|
not word zpl_usize
|
||||||
|
not word zpl_isize
|
||||||
|
|
||||||
|
// Undesired exposures.
|
||||||
|
not word zpl_allocator
|
||||||
|
not word zpl_arena
|
||||||
|
not word zpl_array
|
||||||
|
not word zpl_file
|
||||||
|
not word zpl_list
|
||||||
|
not word zpl_pool
|
||||||
|
not word zpl_opts
|
||||||
|
|
||||||
|
// Conflicts with refactor
|
||||||
|
word alloc, allocator
|
||||||
|
word file_size, fsize
|
||||||
|
|
||||||
|
// Conflicts with std.
|
||||||
|
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_strlen
|
||||||
|
not word zpl_strnlen
|
||||||
|
not word zpl_exit
|
18369
Test/zpl.refactored.h
Normal file
18369
Test/zpl.refactored.h
Normal file
File diff suppressed because it is too large
Load Diff
115
bloat.hpp
Normal file
115
bloat.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
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_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.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 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) \
|
||||||
|
|
||||||
|
|
||||||
|
using c8 = char;
|
||||||
|
using s8 = zpl_i8;
|
||||||
|
using s32 = zpl_i32;
|
||||||
|
using s64 = zpl_i64;
|
||||||
|
using u8 = zpl_u8;
|
||||||
|
using u16 = zpl_u16;
|
||||||
|
using u32 = zpl_u32;
|
||||||
|
using f64 = zpl_f64;
|
||||||
|
using uw = zpl_usize;
|
||||||
|
using sw = zpl_isize;
|
||||||
|
|
||||||
|
|
||||||
|
ct c8 const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
||||||
|
|
||||||
|
|
||||||
|
namespace Memory
|
||||||
|
{
|
||||||
|
zpl_arena Global_Arena {};
|
||||||
|
#define g_allocator zpl_arena_allocator( & Memory::Global_Arena)
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) );
|
||||||
|
|
||||||
|
if ( Global_Arena.total_size == 0 )
|
||||||
|
{
|
||||||
|
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
zpl_arena_free( & Global_Arena);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fatal()
|
||||||
|
{
|
||||||
|
Memory::cleanup();
|
||||||
|
zpl_assert_crash("FATAL");
|
||||||
|
}
|
8
build.bat
Normal file
8
build.bat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
if not exist build\nul (
|
||||||
|
meson setup build
|
||||||
|
)
|
||||||
|
|
||||||
|
echo:
|
||||||
|
ninja -C build
|
15
meson.build
Normal file
15
meson.build
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
project( 'refactor', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
||||||
|
|
||||||
|
include_thirdparty = include_directories( '../thirdparty' )
|
||||||
|
|
||||||
|
# add_global_arguments('-E', language : 'cpp')
|
||||||
|
|
||||||
|
if get_option('buildtype').startswith('debug')
|
||||||
|
|
||||||
|
add_project_arguments('-DBuild_Debug', language : 'cpp')
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
executable( 'refactor', 'refactor.cpp', include_directories : include_thirdparty )
|
||||||
|
|
885
other/refactor.cpp
Normal file
885
other/refactor.cpp
Normal file
@ -0,0 +1,885 @@
|
|||||||
|
#define ZPL_IMPLEMENTATION
|
||||||
|
#include "bloat.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace File
|
||||||
|
{
|
||||||
|
zpl_string Source = nullptr;
|
||||||
|
zpl_string Destination = nullptr;
|
||||||
|
|
||||||
|
zpl_file_contents Content {};
|
||||||
|
|
||||||
|
zpl_arena Buffer;
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
zpl_arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void read()
|
||||||
|
{
|
||||||
|
zpl_file file_src = {};
|
||||||
|
|
||||||
|
Content.allocator = g_allocator;
|
||||||
|
|
||||||
|
zpl_file_error error_src = zpl_file_open( & file_src, Source );
|
||||||
|
|
||||||
|
if ( error_src == ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_isize file_size = cast(zpl_isize) zpl_file_size( & file_src);
|
||||||
|
|
||||||
|
if ( file_size > 0 )
|
||||||
|
{
|
||||||
|
zpl_arena_init_from_allocator( & Buffer, zpl_heap(), file_size + file_size % 64 );
|
||||||
|
|
||||||
|
Content.data = zpl_alloc( zpl_arena_allocator( & Buffer), file_size);
|
||||||
|
Content.size = file_size;
|
||||||
|
|
||||||
|
zpl_file_read_at ( & file_src, Content.data, Content.size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_file_close( & file_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Content.data == nullptr )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open source file: %s\n", Source );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(zpl_string refactored)
|
||||||
|
{
|
||||||
|
if ( refactored == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_file file_dest {};
|
||||||
|
zpl_file_error error = zpl_file_create( & file_dest, Destination );
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open destination file: %s\n", Destination );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_file_write( & file_dest, refactored, zpl_string_length(refactored) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Spec
|
||||||
|
{
|
||||||
|
zpl_string File;
|
||||||
|
|
||||||
|
enum Tok
|
||||||
|
{
|
||||||
|
Not,
|
||||||
|
Namespace,
|
||||||
|
Word,
|
||||||
|
|
||||||
|
Num_Tok
|
||||||
|
};
|
||||||
|
|
||||||
|
ct
|
||||||
|
char const* str_tok( Tok tok )
|
||||||
|
{
|
||||||
|
ct
|
||||||
|
char const* tok_to_str[ Tok::Num_Tok ] =
|
||||||
|
{
|
||||||
|
"not",
|
||||||
|
"namespace",
|
||||||
|
"word",
|
||||||
|
};
|
||||||
|
|
||||||
|
return tok_to_str[ tok ];
|
||||||
|
}
|
||||||
|
|
||||||
|
ct
|
||||||
|
c8 strlen_tok( Tok tok )
|
||||||
|
{
|
||||||
|
ct
|
||||||
|
const u8 tok_to_len[ Tok::Num_Tok ] =
|
||||||
|
{
|
||||||
|
3,
|
||||||
|
9,
|
||||||
|
4,
|
||||||
|
};
|
||||||
|
|
||||||
|
return tok_to_len[ tok ];
|
||||||
|
}
|
||||||
|
|
||||||
|
forceinline
|
||||||
|
bool is_tok( Tok tok, zpl_string str, u32 length )
|
||||||
|
{
|
||||||
|
char const* tok_str = str_tok(tok);
|
||||||
|
const u8 tok_len = strlen_tok(tok);
|
||||||
|
|
||||||
|
if ( tok_len != length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
s32 result = zpl_strncmp( tok_str, str, tok_len );
|
||||||
|
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
zpl_string Sig = nullptr; // Signature
|
||||||
|
zpl_string Sub = nullptr; // Substitute
|
||||||
|
};
|
||||||
|
|
||||||
|
zpl_arena Buffer {};
|
||||||
|
zpl_array(Entry) Word_Ignores;
|
||||||
|
zpl_array(Entry) Namespace_Ignores;
|
||||||
|
zpl_array(Entry) Words;
|
||||||
|
zpl_array(Entry) Namespaces;
|
||||||
|
|
||||||
|
u32 Sig_Smallest = zpl_kilobytes(1);
|
||||||
|
|
||||||
|
forceinline
|
||||||
|
void find_next_token( zpl_string& token, char*& line, u32& length )
|
||||||
|
{
|
||||||
|
zpl_string_clear( token );
|
||||||
|
length = 0;
|
||||||
|
while ( zpl_char_is_alphanumeric( line[length] ) || line[length] == '_' )
|
||||||
|
{
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( length == 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("Failed to find valid initial token");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
token = zpl_string_append_length( token, line, length );
|
||||||
|
line += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process()
|
||||||
|
{
|
||||||
|
char* content;
|
||||||
|
|
||||||
|
zpl_array(char*) lines;
|
||||||
|
|
||||||
|
// Get the contents of the file.
|
||||||
|
{
|
||||||
|
zpl_file file {};
|
||||||
|
zpl_file_error error = zpl_file_open( & file, File);
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf("Could not open the specification file: %s", File);
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
sw fsize = scast( sw, zpl_file_size( & file ) );
|
||||||
|
|
||||||
|
if ( fsize <= 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("No content in specificaiton to process");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_arena_init_from_allocator( & Buffer, zpl_heap(), (fsize + fsize % 64) * 3 + zpl_kilobytes(1) );
|
||||||
|
|
||||||
|
char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & Buffer), fsize + 1) );
|
||||||
|
|
||||||
|
zpl_file_read( & file, content, fsize);
|
||||||
|
|
||||||
|
content[fsize] = 0;
|
||||||
|
|
||||||
|
lines = zpl_str_split_lines( zpl_arena_allocator( & Buffer ), content, false );
|
||||||
|
|
||||||
|
zpl_file_close( & file );
|
||||||
|
}
|
||||||
|
|
||||||
|
sw left = zpl_array_count( lines );
|
||||||
|
|
||||||
|
if ( left == 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("Spec::process: lines array imporoperly setup");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the first line as its the version number and we only support __VERSION 1.
|
||||||
|
left--;
|
||||||
|
lines++;
|
||||||
|
|
||||||
|
zpl_array_init( Word_Ignores, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Namespace_Ignores, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Words, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Namespaces, zpl_arena_allocator( & Buffer));
|
||||||
|
|
||||||
|
// Limiting the maximum output of a token to 1 KB
|
||||||
|
zpl_string token = zpl_string_make_reserve( zpl_arena_allocator( & Buffer), zpl_kilobytes(1));
|
||||||
|
|
||||||
|
while ( left-- )
|
||||||
|
{
|
||||||
|
char* line = * lines;
|
||||||
|
|
||||||
|
// Ignore line if its a comment
|
||||||
|
if ( line[0] == '/' && line[1] == '/')
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove indent
|
||||||
|
{
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 length = 0;
|
||||||
|
|
||||||
|
// Find a valid token
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
Tok type = Tok::Num_Tok;
|
||||||
|
bool ignore = false;
|
||||||
|
Entry entry {};
|
||||||
|
|
||||||
|
// Will be reguarded as an ignore.
|
||||||
|
if ( is_tok( Tok::Not, token, length ))
|
||||||
|
{
|
||||||
|
ignore = true;
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the category token
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_tok( Tok::Namespace, token, length ) )
|
||||||
|
{
|
||||||
|
type = Tok::Namespace;
|
||||||
|
}
|
||||||
|
else if ( is_tok( Tok::Word, token, length ) )
|
||||||
|
{
|
||||||
|
type = Tok::Word;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse line.
|
||||||
|
{
|
||||||
|
// Find first argument
|
||||||
|
{
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
// First argument is signature.
|
||||||
|
entry.Sig = zpl_string_make_length( g_allocator, token, length );
|
||||||
|
|
||||||
|
if ( length < Sig_Smallest )
|
||||||
|
Sig_Smallest = length;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' || ignore )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
if ( ignore)
|
||||||
|
zpl_array_append( Namespace_Ignores, entry );
|
||||||
|
|
||||||
|
else
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
if ( ignore)
|
||||||
|
zpl_array_append( Word_Ignores, entry );
|
||||||
|
|
||||||
|
else
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for second argument indicator
|
||||||
|
{
|
||||||
|
bool bSkip = false;
|
||||||
|
|
||||||
|
while ( line[0] != ',' )
|
||||||
|
{
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bSkip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bSkip )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat the argument delimiter.
|
||||||
|
line++;
|
||||||
|
|
||||||
|
// Remove spacing
|
||||||
|
{
|
||||||
|
bool bSkip = true;
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
// Second argument is substitute.
|
||||||
|
entry.Sub = zpl_string_make_length( g_allocator, token, length );
|
||||||
|
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_printf("Specification Line: %d is missing valid keyword", zpl_array_count(lines) - left);
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
zpl_arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Token
|
||||||
|
{
|
||||||
|
u32 Start;
|
||||||
|
u32 End;
|
||||||
|
|
||||||
|
zpl_string Sig;
|
||||||
|
zpl_string Sub;
|
||||||
|
};
|
||||||
|
|
||||||
|
zpl_string NSpace_Old = nullptr;
|
||||||
|
zpl_string NSpace_New = nullptr;
|
||||||
|
|
||||||
|
void refactor()
|
||||||
|
{
|
||||||
|
sw buffer_size = File::Content.size;
|
||||||
|
|
||||||
|
zpl_array(Token) tokens;
|
||||||
|
zpl_array_init( tokens, g_allocator);
|
||||||
|
|
||||||
|
char* content = rcast( char*, File::Content.data );
|
||||||
|
|
||||||
|
zpl_string current = zpl_string_make( g_allocator, "");
|
||||||
|
zpl_string preview = zpl_string_make( g_allocator, "");
|
||||||
|
|
||||||
|
sw left = File::Content.size;
|
||||||
|
|
||||||
|
sw line = 0;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
if ( content[0] == '\n' )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
// Word Ignores
|
||||||
|
{
|
||||||
|
Spec::Entry* ignore = Spec::Word_Ignores;
|
||||||
|
|
||||||
|
sw ignores_left = zpl_array_count( Spec::Word_Ignores);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( ignore->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( ignore->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( ignore->Sig, current ) && ! zpl_char_is_alphanumeric( content[sig_length] ) )
|
||||||
|
{
|
||||||
|
zpl_printf("\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 = zpl_array_count( Spec::Namespace_Ignores);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( ignore->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( ignore->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( ignore->Sig, current ) )
|
||||||
|
{
|
||||||
|
u32 length = sig_length;
|
||||||
|
char* ns_content = content + sig_length;
|
||||||
|
|
||||||
|
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
|
||||||
|
{
|
||||||
|
length++;
|
||||||
|
ns_content++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( preview );
|
||||||
|
preview = zpl_string_append_length( preview, content, length );
|
||||||
|
zpl_printf("\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 = zpl_array_count ( Spec::Words);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( word->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
sw sig_length = zpl_string_length( word->Sig);
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( word->Sig, current ) )
|
||||||
|
{
|
||||||
|
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 += zpl_string_length( entry.Sub) - sig_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_array_append( tokens, entry );
|
||||||
|
|
||||||
|
zpl_printf("\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 = zpl_array_count( Spec::Namespaces);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( nspace->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( nspace->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( nspace->Sig, current ) )
|
||||||
|
{
|
||||||
|
u32 length = sig_length;
|
||||||
|
char* ns_content = content + sig_length;
|
||||||
|
|
||||||
|
while ( zpl_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 += zpl_string_length( entry.Sub ) - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_array_append( tokens, entry );
|
||||||
|
|
||||||
|
zpl_string_clear( preview );
|
||||||
|
preview = zpl_string_append_length( preview, content, length);
|
||||||
|
zpl_printf("\nFound %-40s %-40s line %d", preview, nspace->Sig, line);
|
||||||
|
|
||||||
|
content += length;
|
||||||
|
left -= length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( nspace++, --nspaces_left );
|
||||||
|
}
|
||||||
|
|
||||||
|
Skip:
|
||||||
|
// content += Spec::Sig_Smallest;
|
||||||
|
// left -= Spec::Sig_Smallest;
|
||||||
|
content++;
|
||||||
|
left--;
|
||||||
|
// zpl_sleep_ms( 10 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = zpl_array_count( tokens);
|
||||||
|
content = rcast( char*, File::Content.data);
|
||||||
|
|
||||||
|
// Generate the refactored file content.
|
||||||
|
zpl_arena buffer;
|
||||||
|
zpl_string refactored = nullptr;
|
||||||
|
{
|
||||||
|
Token* entry = tokens;
|
||||||
|
|
||||||
|
if ( entry == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_arena_init_from_allocator( & buffer, zpl_heap(), buffer_size * 2 );
|
||||||
|
|
||||||
|
zpl_string
|
||||||
|
new_string = zpl_string_make_reserve( zpl_arena_allocator( & buffer), zpl_kilobytes(1) );
|
||||||
|
refactored = zpl_string_make_reserve( zpl_arena_allocator( & buffer), buffer_size );
|
||||||
|
|
||||||
|
sw previous_end = 0;
|
||||||
|
|
||||||
|
while ( left-- )
|
||||||
|
{
|
||||||
|
sw segment_length = entry->Start - previous_end;
|
||||||
|
|
||||||
|
sw sig_length = zpl_string_length( entry->Sig );
|
||||||
|
|
||||||
|
// Append between tokens
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length + sig_length;
|
||||||
|
|
||||||
|
segment_length = entry->End - entry->Start - sig_length;
|
||||||
|
|
||||||
|
// Append token
|
||||||
|
if ( entry->Sub )
|
||||||
|
refactored = zpl_string_append( refactored, entry->Sub );
|
||||||
|
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length;
|
||||||
|
|
||||||
|
previous_end = entry->End;
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry--;
|
||||||
|
|
||||||
|
if ( entry->End < File::Content.size )
|
||||||
|
{
|
||||||
|
refactored = zpl_string_append_length( refactored, content, File::Content.size - entry->End );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write refactored content to destination.
|
||||||
|
File::write( refactored );
|
||||||
|
|
||||||
|
zpl_arena_free( & buffer );
|
||||||
|
|
||||||
|
#else
|
||||||
|
u32 nspace_length = zpl_string_length( NSpace_Old );
|
||||||
|
|
||||||
|
// Gather all tokens.
|
||||||
|
while ( (left - nspace_length) > 0 )
|
||||||
|
{
|
||||||
|
while ( left && * content != NSpace_Old[0] )
|
||||||
|
{
|
||||||
|
content++;
|
||||||
|
left--;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = zpl_string_append_length( current, content, nspace_length );
|
||||||
|
left -= nspace_length;
|
||||||
|
content += nspace_length;
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( NSpace_Old, current ) )
|
||||||
|
{
|
||||||
|
u32 index = scast(u32, File::Content.size - left);
|
||||||
|
|
||||||
|
Token token =
|
||||||
|
{
|
||||||
|
index - nspace_length,
|
||||||
|
index
|
||||||
|
};
|
||||||
|
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
const char element = * content;
|
||||||
|
|
||||||
|
if ( element == '_' || zpl_char_is_alphanumeric( element ) )
|
||||||
|
{
|
||||||
|
token.End++;
|
||||||
|
content++;
|
||||||
|
left--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_size += token.End - token.Start + zpl_string_length( NSpace_New ) - nspace_length;
|
||||||
|
|
||||||
|
zpl_array_append( tokens, token );
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current);
|
||||||
|
}
|
||||||
|
|
||||||
|
left = zpl_array_count( tokens);
|
||||||
|
content = rcast( char*, File::Content.data);
|
||||||
|
|
||||||
|
// Generate the refactored file content.
|
||||||
|
zpl_arena buffer;
|
||||||
|
zpl_string refactored = nullptr;
|
||||||
|
{
|
||||||
|
Token* token = tokens;
|
||||||
|
|
||||||
|
if ( token == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_arena_init_from_allocator( & buffer, zpl_heap(), buffer_size * 2 );
|
||||||
|
|
||||||
|
zpl_string
|
||||||
|
new_string = zpl_string_make_reserve( zpl_arena_allocator( & buffer), 1024 );
|
||||||
|
refactored = zpl_string_make_reserve( zpl_arena_allocator( & buffer), buffer_size );
|
||||||
|
|
||||||
|
u32 previous_end = 0;
|
||||||
|
|
||||||
|
while ( left-- )
|
||||||
|
{
|
||||||
|
u32 segment_length = token->Start - previous_end;
|
||||||
|
|
||||||
|
// Append between tokens
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length + nspace_length;
|
||||||
|
|
||||||
|
segment_length = token->End - token->Start - nspace_length;
|
||||||
|
|
||||||
|
// Append token
|
||||||
|
refactored = zpl_string_append( refactored, NSpace_New );
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length;
|
||||||
|
|
||||||
|
previous_end = token->End;
|
||||||
|
token++;
|
||||||
|
}
|
||||||
|
|
||||||
|
token--;
|
||||||
|
|
||||||
|
if ( token->End < File::Content.size )
|
||||||
|
{
|
||||||
|
refactored = zpl_string_append_length( refactored, content, File::Content.size - token->End );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write refactored content to destination.
|
||||||
|
File::write( refactored );
|
||||||
|
|
||||||
|
zpl_arena_free( & buffer );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
void parse_options( int num, char** arguments )
|
||||||
|
{
|
||||||
|
zpl_opts opts;
|
||||||
|
zpl_opts_init( & opts, g_allocator, "refactor");
|
||||||
|
zpl_opts_add( & opts, "source" , "src" , "File to refactor" , ZPL_OPTS_STRING);
|
||||||
|
zpl_opts_add( & opts, "destination" , "dst" , "File post refactor" , ZPL_OPTS_STRING);
|
||||||
|
zpl_opts_add( & opts, "specification", "spec", "Specification for refactoring", ZPL_OPTS_STRING);
|
||||||
|
#if 0
|
||||||
|
zpl_opts_add( & opts, "ns_old" , "old" , "Namespace to refactor" , ZPL_OPTS_STRING);
|
||||||
|
zpl_opts_add( & opts, "ns_new" , "new" , "Namespace to refactor to" , ZPL_OPTS_STRING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (zpl_opts_compile( & opts, num, arguments))
|
||||||
|
{
|
||||||
|
if ( zpl_opts_has_arg( & opts, "src" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "src", "INVALID PATH" );
|
||||||
|
|
||||||
|
File::Source = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Source = zpl_string_append( File::Source, opt );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zpl_printf( "-source not provided\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( zpl_opts_has_arg( & opts, "dst" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "dst", "INVALID PATH" );
|
||||||
|
|
||||||
|
File::Destination = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Destination = zpl_string_append( File::Destination, opt );
|
||||||
|
}
|
||||||
|
else if ( File::Source && File::Destination )
|
||||||
|
{
|
||||||
|
File::Destination = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Destination = zpl_string_append( File::Destination, File::Source );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( zpl_opts_has_arg( & opts, "spec" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "spec", "INVALID PATH" );
|
||||||
|
|
||||||
|
Spec::File = zpl_string_make( g_allocator, "" );
|
||||||
|
Spec::File = zpl_string_append( Spec::File, opt );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ( zpl_opts_has_arg( & opts, "old" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "old", "INVALID NAMESPACE" );
|
||||||
|
|
||||||
|
NSpace_Old = zpl_string_make( g_allocator, "" );
|
||||||
|
NSpace_Old = zpl_string_append( NSpace_Old, opt );
|
||||||
|
}
|
||||||
|
if ( Spec::File == nullptr && NSpace_Old == nullptr )
|
||||||
|
{
|
||||||
|
zpl_printf( "Eitehr -ns_old or -specification must be provided\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
NSpace_New = zpl_string_make( g_allocator, "" );
|
||||||
|
if ( zpl_opts_has_arg( & opts, "new" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "new", "INVALID NAMESPACE" );
|
||||||
|
|
||||||
|
NSpace_New = zpl_string_append( NSpace_New , opt );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zpl_printf( "Failed to parse arguments\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_opts_free( & opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int num, char** arguments)
|
||||||
|
{
|
||||||
|
Memory::setup();
|
||||||
|
|
||||||
|
parse_options( num, arguments );
|
||||||
|
|
||||||
|
if ( Spec::File )
|
||||||
|
Spec::process();
|
||||||
|
|
||||||
|
File::read();
|
||||||
|
|
||||||
|
refactor();
|
||||||
|
|
||||||
|
File:: cleanup();
|
||||||
|
Memory::cleanup();
|
||||||
|
}
|
779
refactor.cpp
Normal file
779
refactor.cpp
Normal file
@ -0,0 +1,779 @@
|
|||||||
|
#define ZPL_IMPLEMENTATION
|
||||||
|
#include "bloat.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace File
|
||||||
|
{
|
||||||
|
zpl_string Source = nullptr;
|
||||||
|
zpl_string Destination = nullptr;
|
||||||
|
|
||||||
|
zpl_file_contents Content {};
|
||||||
|
|
||||||
|
zpl_arena Buffer;
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
zpl_arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void read()
|
||||||
|
{
|
||||||
|
zpl_file file_src = {};
|
||||||
|
|
||||||
|
Content.allocator = g_allocator;
|
||||||
|
|
||||||
|
zpl_file_error error_src = zpl_file_open( & file_src, Source );
|
||||||
|
|
||||||
|
if ( error_src == ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_isize fsize = cast(zpl_isize) zpl_file_size( & file_src);
|
||||||
|
|
||||||
|
if ( fsize > 0 )
|
||||||
|
{
|
||||||
|
zpl_arena_init_from_allocator( & Buffer, zpl_heap(), (fsize + fsize % 64) * 4 );
|
||||||
|
|
||||||
|
Content.data = zpl_alloc( zpl_arena_allocator( & Buffer), fsize);
|
||||||
|
Content.size = fsize;
|
||||||
|
|
||||||
|
zpl_file_read_at ( & file_src, Content.data, Content.size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_file_close( & file_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Content.data == nullptr )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open source file: %s\n", Source );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(zpl_string refactored)
|
||||||
|
{
|
||||||
|
if ( refactored == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_file file_dest {};
|
||||||
|
zpl_file_error error = zpl_file_create( & file_dest, Destination );
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf( "Unable to open destination file: %s\n", Destination );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_file_write( & file_dest, refactored, zpl_string_length(refactored) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Spec
|
||||||
|
{
|
||||||
|
zpl_string File;
|
||||||
|
|
||||||
|
enum Tok
|
||||||
|
{
|
||||||
|
Not,
|
||||||
|
Namespace,
|
||||||
|
Word,
|
||||||
|
|
||||||
|
Num_Tok
|
||||||
|
};
|
||||||
|
|
||||||
|
ct
|
||||||
|
char const* str_tok( Tok tok )
|
||||||
|
{
|
||||||
|
ct
|
||||||
|
char const* tok_to_str[ Tok::Num_Tok ] =
|
||||||
|
{
|
||||||
|
"not",
|
||||||
|
"namespace",
|
||||||
|
"word",
|
||||||
|
};
|
||||||
|
|
||||||
|
return tok_to_str[ tok ];
|
||||||
|
}
|
||||||
|
|
||||||
|
ct
|
||||||
|
c8 strlen_tok( Tok tok )
|
||||||
|
{
|
||||||
|
ct
|
||||||
|
const u8 tok_to_len[ Tok::Num_Tok ] =
|
||||||
|
{
|
||||||
|
3,
|
||||||
|
9,
|
||||||
|
4,
|
||||||
|
};
|
||||||
|
|
||||||
|
return tok_to_len[ tok ];
|
||||||
|
}
|
||||||
|
|
||||||
|
forceinline
|
||||||
|
bool is_tok( Tok tok, zpl_string str, u32 length )
|
||||||
|
{
|
||||||
|
char const* tok_str = str_tok(tok);
|
||||||
|
const u8 tok_len = strlen_tok(tok);
|
||||||
|
|
||||||
|
if ( tok_len != length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
s32 result = zpl_strncmp( tok_str, str, tok_len );
|
||||||
|
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
zpl_string Sig = nullptr; // Signature
|
||||||
|
zpl_string Sub = nullptr; // Substitute
|
||||||
|
};
|
||||||
|
|
||||||
|
zpl_arena Buffer {};
|
||||||
|
zpl_array(Entry) Word_Ignores;
|
||||||
|
zpl_array(Entry) Namespace_Ignores;
|
||||||
|
zpl_array(Entry) Words;
|
||||||
|
zpl_array(Entry) Namespaces;
|
||||||
|
|
||||||
|
u32 Sig_Smallest = zpl_kilobytes(1);
|
||||||
|
|
||||||
|
forceinline
|
||||||
|
void find_next_token( zpl_string& token, char*& line, u32& length )
|
||||||
|
{
|
||||||
|
zpl_string_clear( token );
|
||||||
|
length = 0;
|
||||||
|
while ( zpl_char_is_alphanumeric( line[length] ) || line[length] == '_' )
|
||||||
|
{
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( length == 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("Failed to find valid initial token");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
token = zpl_string_append_length( token, line, length );
|
||||||
|
line += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process()
|
||||||
|
{
|
||||||
|
char* content;
|
||||||
|
|
||||||
|
zpl_array(char*) lines;
|
||||||
|
|
||||||
|
// Get the contents of the file.
|
||||||
|
{
|
||||||
|
zpl_file file {};
|
||||||
|
zpl_file_error error = zpl_file_open( & file, File);
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
zpl_printf("Could not open the specification file: %s", File);
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
sw fsize = scast( sw, zpl_file_size( & file ) );
|
||||||
|
|
||||||
|
if ( fsize <= 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("No content in specificaiton to process");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_arena_init_from_allocator( & Buffer, zpl_heap(), (fsize + fsize % 64) * 10 + zpl_kilobytes(1) );
|
||||||
|
|
||||||
|
char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & Buffer), fsize + 1) );
|
||||||
|
|
||||||
|
zpl_file_read( & file, content, fsize);
|
||||||
|
|
||||||
|
content[fsize] = 0;
|
||||||
|
|
||||||
|
lines = zpl_str_split_lines( zpl_arena_allocator( & Buffer ), content, false );
|
||||||
|
|
||||||
|
zpl_file_close( & file );
|
||||||
|
}
|
||||||
|
|
||||||
|
sw left = zpl_array_count( lines );
|
||||||
|
|
||||||
|
if ( left == 0 )
|
||||||
|
{
|
||||||
|
zpl_printf("Spec::process: lines array imporoperly setup");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the first line as its the version number and we only support __VERSION 1.
|
||||||
|
left--;
|
||||||
|
lines++;
|
||||||
|
|
||||||
|
zpl_array_init( Word_Ignores, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Namespace_Ignores, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Words, zpl_arena_allocator( & Buffer));
|
||||||
|
zpl_array_init( Namespaces, zpl_arena_allocator( & Buffer));
|
||||||
|
|
||||||
|
// Limiting the maximum output of a token to 1 KB
|
||||||
|
zpl_string token = zpl_string_make_reserve( zpl_arena_allocator( & Buffer), zpl_kilobytes(1));
|
||||||
|
|
||||||
|
while ( left-- )
|
||||||
|
{
|
||||||
|
char* line = * lines;
|
||||||
|
|
||||||
|
// Ignore line if its a comment
|
||||||
|
if ( line[0] == '/' && line[1] == '/')
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove indent
|
||||||
|
{
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 length = 0;
|
||||||
|
|
||||||
|
// Find a valid token
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
Tok type = Tok::Num_Tok;
|
||||||
|
bool ignore = false;
|
||||||
|
Entry entry {};
|
||||||
|
|
||||||
|
// Will be reguarded as an ignore.
|
||||||
|
if ( is_tok( Tok::Not, token, length ))
|
||||||
|
{
|
||||||
|
ignore = true;
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the category token
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_tok( Tok::Namespace, token, length ) )
|
||||||
|
{
|
||||||
|
type = Tok::Namespace;
|
||||||
|
}
|
||||||
|
else if ( is_tok( Tok::Word, token, length ) )
|
||||||
|
{
|
||||||
|
type = Tok::Word;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse line.
|
||||||
|
{
|
||||||
|
// Find first argument
|
||||||
|
{
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
// First argument is signature.
|
||||||
|
entry.Sig = zpl_string_make_length( g_allocator, token, length );
|
||||||
|
|
||||||
|
if ( length < Sig_Smallest )
|
||||||
|
Sig_Smallest = length;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' || ignore )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
if ( ignore)
|
||||||
|
zpl_array_append( Namespace_Ignores, entry );
|
||||||
|
|
||||||
|
else
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
if ( ignore)
|
||||||
|
{
|
||||||
|
zpl_array_append( Word_Ignores, entry );
|
||||||
|
u32 test = zpl_array_count( Word_Ignores );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for second argument indicator
|
||||||
|
{
|
||||||
|
bool bSkip = false;
|
||||||
|
|
||||||
|
while ( line[0] != ',' )
|
||||||
|
{
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bSkip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bSkip )
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat the argument delimiter.
|
||||||
|
line++;
|
||||||
|
|
||||||
|
// Remove spacing
|
||||||
|
{
|
||||||
|
bool bSkip = true;
|
||||||
|
|
||||||
|
while ( zpl_char_is_space( line[0] ) )
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if ( line[0] == '\0' )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_next_token( token, line, length );
|
||||||
|
|
||||||
|
// Second argument is substitute.
|
||||||
|
entry.Sub = zpl_string_make_length( g_allocator, token, length );
|
||||||
|
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case Tok::Namespace:
|
||||||
|
zpl_array_append( Namespaces, entry );
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Tok::Word:
|
||||||
|
zpl_array_append( Words, entry );
|
||||||
|
lines++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_printf("Specification Line: %d is missing valid keyword", zpl_array_count(lines) - left);
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
zpl_arena_free( & Buffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Token
|
||||||
|
{
|
||||||
|
u32 Start;
|
||||||
|
u32 End;
|
||||||
|
|
||||||
|
zpl_string Sig;
|
||||||
|
zpl_string Sub;
|
||||||
|
};
|
||||||
|
|
||||||
|
void refactor()
|
||||||
|
{
|
||||||
|
sw buffer_size = File::Content.size;
|
||||||
|
|
||||||
|
zpl_array(Token) tokens;
|
||||||
|
zpl_array_init( tokens, g_allocator);
|
||||||
|
|
||||||
|
char* content = rcast( char*, File::Content.data );
|
||||||
|
|
||||||
|
zpl_string current = zpl_string_make( g_allocator, "");
|
||||||
|
zpl_string preview = zpl_string_make( g_allocator, "");
|
||||||
|
|
||||||
|
sw left = File::Content.size;
|
||||||
|
sw line = 0;
|
||||||
|
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
if ( content[0] == '\n' )
|
||||||
|
{
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Word Ignores
|
||||||
|
{
|
||||||
|
Spec::Entry* ignore = Spec::Word_Ignores;
|
||||||
|
|
||||||
|
sw ignores_left = zpl_array_count( Spec::Word_Ignores);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( ignore->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( ignore->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
// bool match = false;
|
||||||
|
// if ( zpl_strncmp( "zpl_printf", current, sig_length ) == 0 )
|
||||||
|
// {
|
||||||
|
// match = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( ignore->Sig, current ) )
|
||||||
|
{
|
||||||
|
char before = content[-1];
|
||||||
|
char after = content[sig_length];
|
||||||
|
|
||||||
|
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|
||||||
|
|| zpl_char_is_alphanumeric( after ) || after == '_' )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_printf("\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 = zpl_array_count( Spec::Namespace_Ignores);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( ignore->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( ignore->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( ignore->Sig, current ) )
|
||||||
|
{
|
||||||
|
u32 length = sig_length;
|
||||||
|
char* ns_content = content + sig_length;
|
||||||
|
|
||||||
|
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
|
||||||
|
{
|
||||||
|
length++;
|
||||||
|
ns_content++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( preview );
|
||||||
|
preview = zpl_string_append_length( preview, content, length );
|
||||||
|
zpl_printf("\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 = zpl_array_count ( Spec::Words);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( word->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
sw sig_length = zpl_string_length( word->Sig);
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( word->Sig, current ) )
|
||||||
|
{
|
||||||
|
char before = content[-1];
|
||||||
|
char after = content[sig_length];
|
||||||
|
|
||||||
|
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|
||||||
|
|| zpl_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 += zpl_string_length( entry.Sub) - sig_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_array_append( tokens, entry );
|
||||||
|
|
||||||
|
zpl_printf("\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 = zpl_array_count( Spec::Namespaces);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( nspace->Sig[0] != content[0] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_string_clear( current );
|
||||||
|
|
||||||
|
u32 sig_length = zpl_string_length( nspace->Sig );
|
||||||
|
current = zpl_string_append_length( current, content, sig_length );
|
||||||
|
|
||||||
|
if ( zpl_string_are_equal( nspace->Sig, current ) )
|
||||||
|
{
|
||||||
|
u32 length = sig_length;
|
||||||
|
char* ns_content = content + sig_length;
|
||||||
|
|
||||||
|
while ( zpl_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 += zpl_string_length( entry.Sub ) - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_array_append( tokens, entry );
|
||||||
|
|
||||||
|
zpl_string_clear( preview );
|
||||||
|
preview = zpl_string_append_length( preview, content, length);
|
||||||
|
zpl_printf("\nFound %-40s %-40s line %d", preview, nspace->Sig, line);
|
||||||
|
|
||||||
|
content += length;
|
||||||
|
left -= length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( nspace++, --nspaces_left );
|
||||||
|
}
|
||||||
|
|
||||||
|
content++;
|
||||||
|
left--;
|
||||||
|
Skip:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = zpl_array_count( tokens);
|
||||||
|
content = rcast( char*, File::Content.data);
|
||||||
|
|
||||||
|
// Generate the refactored file content.
|
||||||
|
zpl_arena buffer;
|
||||||
|
zpl_string refactored = nullptr;
|
||||||
|
{
|
||||||
|
Token* entry = tokens;
|
||||||
|
|
||||||
|
if ( entry == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zpl_arena_init_from_allocator( & buffer, zpl_heap(), buffer_size * 2 );
|
||||||
|
|
||||||
|
zpl_string
|
||||||
|
new_string = zpl_string_make_reserve( zpl_arena_allocator( & buffer), zpl_kilobytes(1) );
|
||||||
|
refactored = zpl_string_make_reserve( zpl_arena_allocator( & buffer), buffer_size );
|
||||||
|
|
||||||
|
sw previous_end = 0;
|
||||||
|
|
||||||
|
while ( left-- )
|
||||||
|
{
|
||||||
|
sw segment_length = entry->Start - previous_end;
|
||||||
|
|
||||||
|
sw sig_length = zpl_string_length( entry->Sig );
|
||||||
|
|
||||||
|
// Append between tokens
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length + sig_length;
|
||||||
|
|
||||||
|
segment_length = entry->End - entry->Start - sig_length;
|
||||||
|
|
||||||
|
// Append token
|
||||||
|
if ( entry->Sub )
|
||||||
|
refactored = zpl_string_append( refactored, entry->Sub );
|
||||||
|
|
||||||
|
refactored = zpl_string_append_length( refactored, content, segment_length );
|
||||||
|
content += segment_length;
|
||||||
|
|
||||||
|
previous_end = entry->End;
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry--;
|
||||||
|
|
||||||
|
if ( entry->End < File::Content.size )
|
||||||
|
{
|
||||||
|
refactored = zpl_string_append_length( refactored, content, File::Content.size - entry->End );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write refactored content to destination.
|
||||||
|
File::write( refactored );
|
||||||
|
|
||||||
|
zpl_arena_free( & buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
void parse_options( int num, char** arguments )
|
||||||
|
{
|
||||||
|
zpl_opts opts;
|
||||||
|
zpl_opts_init( & opts, g_allocator, "refactor");
|
||||||
|
zpl_opts_add( & opts, "source" , "src" , "File to refactor" , ZPL_OPTS_STRING);
|
||||||
|
zpl_opts_add( & opts, "destination" , "dst" , "File post refactor" , ZPL_OPTS_STRING);
|
||||||
|
zpl_opts_add( & opts, "specification", "spec", "Specification for refactoring", ZPL_OPTS_STRING);
|
||||||
|
|
||||||
|
if (zpl_opts_compile( & opts, num, arguments))
|
||||||
|
{
|
||||||
|
if ( zpl_opts_has_arg( & opts, "src" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "src", "INVALID PATH" );
|
||||||
|
|
||||||
|
File::Source = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Source = zpl_string_append( File::Source, opt );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zpl_printf( "-source not provided\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( zpl_opts_has_arg( & opts, "dst" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "dst", "INVALID PATH" );
|
||||||
|
|
||||||
|
File::Destination = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Destination = zpl_string_append( File::Destination, opt );
|
||||||
|
}
|
||||||
|
else if ( File::Source )
|
||||||
|
{
|
||||||
|
File::Destination = zpl_string_make( g_allocator, "" );
|
||||||
|
File::Destination = zpl_string_append( File::Destination, File::Source );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( zpl_opts_has_arg( & opts, "spec" ) )
|
||||||
|
{
|
||||||
|
zpl_string opt = zpl_opts_string( & opts, "spec", "INVALID PATH" );
|
||||||
|
|
||||||
|
Spec::File = zpl_string_make( g_allocator, "" );
|
||||||
|
Spec::File = zpl_string_append( Spec::File, opt );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zpl_printf( "Failed to parse arguments\n" );
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
zpl_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();
|
||||||
|
}
|
18369
thirdparty/zpl.h
vendored
Normal file
18369
thirdparty/zpl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user