62 Commits

Author SHA1 Message Date
Ed_
5efd14322e Updated zpl to latest, update refactor scripts based on convention used in gencpp 2023-04-19 15:53:01 -04:00
Ed_
c4efd1890d Misc changes 2023-04-03 03:53:59 -04:00
Ed_
063a3a972c Workflow script update (attempt to use env vars) 2023-03-31 17:32:47 -04:00
Ed_
e301b400ba More readme additions and another debug line out fix. 2023-03-31 17:27:59 -04:00
Ed_
6bc4346652 Update readme, fix an issue with stb_image.refactor script (needed newline at eof), some script changes. 2023-03-31 16:17:02 -04:00
Ed_
6e91555a20 Script additions and improvements, fix IO bug. 2023-03-31 01:04:56 -04:00
Ed_
1b0c5d176c Addeed stb_image header
Going to use as another test case.
2023-03-30 23:19:40 -04:00
Ed_
ea09b27b3b ok 2023-03-30 22:52:58 -04:00
Ed_
d344043c44 ok 2023-03-30 22:50:01 -04:00
Ed_
bdc272cc2b Added release tag.. 2023-03-30 22:41:46 -04:00
Ed_
8d5cdec586 ok 2023-03-30 22:34:32 -04:00
Ed_
1d807eaf0a Another release attempt 2023-03-30 22:31:07 -04:00
Ed_
2fe7ded7ec Ok. 2023-03-30 21:58:31 -04:00
Ed_
1f2d3cdd42 Attempt to add release versioning again... 2023-03-30 21:53:24 -04:00
Ed_
03f5441b25 Attempting to use avakar's release action 2023-03-30 21:37:53 -04:00
Ed_
b05ee03609 Workflow: Remove step "Create GitHub release" 2023-03-30 21:21:31 -04:00
Ed_
e30539fe32 Workflow : Removing body file. 2023-03-30 21:14:24 -04:00
Ed_
935bfe63ad Hopefully workflow works. 2023-03-30 21:07:10 -04:00
Ed_
d95d4a8d06 Attempting workflow error fix. 2023-03-30 20:50:31 -04:00
Ed_
7d7c34d157 Update release name to just use commit #. 2023-03-30 20:47:25 -04:00
Ed_
25df998dc2 Remove the readme upload. 2023-03-30 20:44:57 -04:00
Ed_
9479a28282 Change workflow release tag name and release_name 2023-03-30 20:40:56 -04:00
Ed_
0246b8419a Fixed workflow error with readme upload. 2023-03-30 20:35:31 -04:00
Ed_
0da1505190 Update to scripts and readme, workflow added release publishing. 2023-03-30 20:14:51 -04:00
Ed_
d73d22282b Some code cleanup 2023-03-30 19:54:19 -04:00
Ed_
78cdfcd7b3 Made a separate build script for CI. 2023-03-30 19:43:44 -04:00
Ed_
018286be6f Some refinement to the gh-workflow 2023-03-30 19:34:07 -04:00
Ed_
a0a3e42e6a Various updates to scripts 2023-03-30 19:33:46 -04:00
Ed_
f9b8f02351 Corrections to debug code for release builds. 2023-03-30 19:33:35 -04:00
Ed_
5bfa8395db Fixing issue with build script not being able to find refactor script in gh-actions. 2023-03-30 18:50:45 -04:00
Ed_
048fcac1bf Bloat.cpp: Bad static on Global_Arena 2023-03-30 18:46:22 -04:00
Ed_
eccbdac3b2 Powershell is dumb 2023-03-30 18:43:22 -04:00
Ed_
2933393f55 Still dumb 2023-03-30 18:39:39 -04:00
Ed_
61880e8dee I'm dumb 2023-03-30 18:37:01 -04:00
Ed_
9bf6af8ce5 Fix issue with cls command on gh-actions. 2023-03-30 18:34:55 -04:00
Ed_
20dd92a684 Possible fix for gh-action yml error. 2023-03-30 18:32:33 -04:00
Ed_
be6b37ae00 attempting to just run the pwsh script with just hardcoded command. 2023-03-30 18:31:41 -04:00
Ed_
e867768862 GH-Actions: Installing meson with pip instead. 2023-03-30 18:28:06 -04:00
Ed_
b08ff787a8 Switching to chocolately as for some reason gh-actions doesn't support winget... 2023-03-30 18:20:33 -04:00
Ed_
263fa66f7f GH-Actions: Using winget instead, win-server 2019. 2023-03-30 18:13:45 -04:00
Ed_
6e9d35cb37 Attempt to fix issue with scoop usage in admin mode. 2023-03-30 18:08:33 -04:00
Ed_
2176314adf Merge pull request #3 from Ed94/build_workflow
Create main.yml
2023-03-30 18:04:00 -04:00
Ed_
484c2ac35c Create main.yml 2023-03-30 18:02:57 -04:00
Ed_
2419f407a8 Merge pull request #2 from Ed94/includes_n_multi-file
Update main with feature updates in includes_n_multi-file
2023-03-30 17:42:11 -04:00
Ed_
503df85733 Setup new test and sucessfuly compiles! 2023-03-30 17:36:36 -04:00
Ed_
c4f0b35a30 Fixed bugs with spec file parsing related to word ignores. 2023-03-30 17:35:57 -04:00
Ed_
17458b4b4c Got include refactors (sig to sub) to work.
Just need to make sure the test case works with the refactored zpl file
2023-03-30 13:59:49 -04:00
Ed_
1cd4287eb2 Fixed issue with ignoring multi-line comments. 2023-03-27 20:14:04 -04:00
Ed_
87c939e2b6 Got include ignores to work, comment ignores work
Not sure yet if include renames work just yet (need to test)

Comment signatures are currently hardcoded for C/C++.
2023-03-25 22:44:36 -04:00
Ed_
d0fad572bc Non-include refactors work. Multi-file works. 2023-03-18 03:10:43 -04:00
Ed_
97967e56d9 WIP - Got it somewhat working, still have issues with multiple files. 2023-03-17 18:12:20 -04:00
Ed_
7e120ae5e9 fixing grammatical mistakes 2023-03-17 02:19:32 -04:00
Ed_
231c893c6b Rework of project implementation
For include and multi-file support. I still need to debug it,
Test will be adjusted as well; I want to get all the files not just zpl refactored using a powershell script.

I dropped the idea of semantically identifiying macros. While it may be possible, I don't see the utility vs the regular idendentifier distinction.
I want to keep the refactoring as simple as possible, where it just takes one pass to go through a file without any context to other files.

So far the ignores behave as a good guard filter for unwanted refactors and the only true weak area was the includes (which should be aleviated with the coming support for it.
2023-03-17 02:09:19 -04:00
Ed_
d44f7ed6fa Updated test to use latest from my fork of zpl. 2023-03-14 02:31:18 -04:00
Ed_
892d0cba64 Updated clang format. 2023-03-13 22:45:45 -04:00
Ed_
aec095a9f0 did some reorganization, build script changes
Moved header and source to code

Changed all build scripts to just be powershell (preferred)
Added clang format (but forgot that you cannot format zpl because it hangs clang format)

Code changes:
* Removed long names just using short names (there is an issue with the opts_compile...)
* Removed zpl.refactored.h (its generated now when `.\build.ps1 test` is run
* Modified zpl.h to just have the radix sort modification.
2023-03-13 20:17:12 -04:00
Ed_
9129b5a9fc renamed test files to make a clearer distinction between the regular files.
Removed c8 typedef.
2023-03-12 22:46:08 -04:00
Ed_
d01625d464 fixed up debug logs and fatal asserts. 2023-03-12 22:38:21 -04:00
Ed_
71d9aa79eb Remove other dir; added gitignore 2023-03-12 22:19:00 -04:00
Ed_
d6345c58bf Merge branch 'main' of https://github.com/Ed94/refactor 2023-03-12 22:13:30 -04:00
Ed_
3e6ede0fbe Update zpl.h.refactor to expose chang ehte native typedefs.
Updated zpl to original state. (Will require minor refactor of the radix sort to compile in the processed version).
2023-03-12 22:13:18 -04:00
Ed_
6f76b43c12 Merge pull request #1 from Ed94/add-license-1
Create LICENSE
2023-03-12 21:47:30 -04:00
37 changed files with 27744 additions and 37857 deletions

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
[*.md]
indent_style = tab
indent_size = 4
[*.c]
indent_style = tab
indent_size = 4
[*.cpp]
indent_style = tab
indent_size = 4

110
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,110 @@
# Name of the workflow
name: Build
# Events used by github actions to know when to execute this workflow
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
inputs:
type:
description: 'Meson buildtype (release, debug, etc.)'
default: release
required: false
test:
description: 'Run tests (test)'
default: test
required: true
jobs:
build:
runs-on:
windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Install Meson, Ninja, and Clang with Chocolatey and pip
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
if (-not (Get-Command choco -ErrorAction SilentlyContinue))
{
Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
}
if (-not (choco list --local-only | Select-String "python"))
{
choco install -y python
}
if (-not (choco list --local-only | Select-String "ninja"))
{
choco install -y ninja
}
if (-not (choco list --local-only | Select-String "llvm"))
{
choco install -y llvm
}
python -m pip install meson
- name: Run PowerShell build script
shell: pwsh
env:
CC: clang
CXX: clang++
BUILD_TYPE: ${{ github.event.inputs.type }}
RUN_TESTS: ${{ github.event.inputs.test }}
run: |
$ErrorActionPreference = "Stop"
$type = $env:BUILD_TYPE
$test = $env:RUN_TESTS
$args = @()
if (-not [string]::IsNullOrEmpty($type)) { $args += $type }
if (-not [string]::IsNullOrEmpty($test)) { $args += $test }
Invoke-Expression "& .\scripts\build.ci.ps1 $args"
- name: Get Short Commit SHA
shell: pwsh
run: |
$shortSHA = $env:github_sha.Substring(0, 7)
echo "Short SHA: $shortSHA"
echo "SHORT_SHA=$shortSHA" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Create Package
shell: pwsh
run: |
New-Item -ItemType Directory -Path "./artifact"
Copy-Item "./build/refactor.exe" -Destination "./artifact/refactor.exe"
Compress-Archive -Path "./artifact/*" -DestinationPath "./artifact/refactor-$($env:SHORT_SHA).zip"
- name: Upload Release
uses: ncipollo/release-action@v1
with:
tag: Release
artifacts: ./artifact/refactor-${{ env.SHORT_SHA }}.zip
omitBody: true
# bodyFile: "body.md"
allowUpdates: true

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.idea
build/*
Test/*.h
Test/*.hpp
Test/*.cpp

35
.vscode/launch.json vendored
View File

@ -10,16 +10,37 @@
"request": "launch",
"program": "${workspaceFolder}/build/refactor.exe",
"args": [
"-source=./thirdparty/zpl.h",
"-destination=./Test/zpl.refactored.h",
"-src=./thirdparty/zpl.h",
"-dst=./Test/zpl.refactored.h",
"-specification=./Test/zpl.h.refactor"
"-spec=./Test/zpl.refactor"
],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"console": "externalTerminal"
}
"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,12 +50,12 @@
"-source=./refactor.cpp",
"-destination=./Test/refactor.cpp",
"-specification=./Test/zpl.h.refactor"
"-specification=./Test/zpl.refactor"
],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"console": "externalTerminal"
"console": "integratedTerminal"
}
]
}

View File

@ -1,23 +1,91 @@
# refactor
A code identifier refactoring app. Intended for c/c++ like identifiers.
Refactor c/c++ files (and problably others) with ease.
Parameters :
## 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.
* `-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.
* `-debug` : Use if on debug build and desire to attach to process, or to get a more verbose log.
Syntax :
## Syntax
* `not` Omit word or namespace.
* `not` Omit an a signature. (Modifies include, word, namespace, etc)
* `include` Preprocessor include `<file path>` related identifiers.
* `word` Fixed sized identifier.
* `namespace` Variable sized identifiers, mainly intended to redefine c-namespace of an identifier.
* `,` is used to delimit arguments to word or namespace.
* `,` is used to delimit arguments (if doing a find and replace).
* `L-Value` is the signature to modify.
* `R-Value` is the substitute ( only available if rule does not use `not` keyword )
The only keyword here excluisve to c/c++ is the `include` as it does search specifically for `#include <L-Value>`.
However, the rest of the categorical keywords (word, namespace), can really be used for any langauge.
TODO:
* Possibly come up with a better name.
* Cleanup memory usage (it hogs quite a bit or what it does..)
There is no semantic awareness this is truely just a simple find and replace, but with some filters specifiable, and
words/namespaces only being restricted to the rules for C/C++ identifiers (alphanumeric or underscores only)
The main benefit for using this over alts is its problably more ergonomic and performant for large refactors on libraries 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.
### Example scripts
See `scripts/template_reafactor.ps1` and the `test/*.refactor` related scripts on intended usage.
This app is not very nice to use directly from CLI. Instead run from a script after gathering the arguments.
There is a desire also to get this setup as a single-header library and also alternative with a minimalist GUI for simple refactors.
### Notes
* Building for debug provides some nice output with context on a per-line basis.
* Release will only show errors for asserts (that will kill the refactor early).
* If the refactor crashes, the files previously written to will retain their changes.
* Make sure to have the code backed up on a VCS or in some other way.
* 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.
## Building
The project has all build configuration in the `scripts` directory.
* `build.ci.ps1` is intended for a continuous intergration setup (GH-worfklow for now).
* `build.ps1` is just a wrap of build.ci that just calls cls.
* `clean.ps1` will clean the workspace of all generated files.
* `get_sources.ps1` is used to gather sources since meson devs refuse to add dynamic retrival of sources for a build.
The project uses [meson](https://github.com/mesonbuild/meson) as the build tool.
Compiler : clang
OS: Windows 11 (windows-latest for github actions)
There should theoretically not be anything stopping it from building on other plaforms.
The library's main dependency is [zpl](https://github.com/zpl-c) which seems to support all major platforms.
## Testing
If the `test` parameter is provided to the build scripts, the project and thirdparty code will be refactored based on the specificiation files `*.refactor` residing in `test`.
With the refactors applied a meson configuraiton is setup (`meson.build` in test) and run to build. So long as it compiles, the feature set of the current version should work fine.
* There is an extra file `stb_image` that is parsed but unused during compilation.
* Planned for use in the namespace addition todo.
## TODO:
* Provide binaries in the release page for github. (debug and release builds)
* Ability to run and not emit any changes to files unless all files sucessfully are refactored.
* Would fix issue where a refactor overwrites files but failed to complete
* Can have a heavy memory cost, so most likely do not want on by default.
* Make comments ignored by default, and just have ability to specify custom comments.
* Would need a directive to add refactors to comments.
* Directive to add cpp namespaces on specific lines of a file, or near specific signatures.
* This can honestly be done also with placing words on specific lines..
* Provide a GUI build.
* Provide as a single-header library.
* Could add a test case where this library is refactored into pure C (most likely c99 or c11).
* Better tests:
* Automatically pull the zpl repo, refactor and format the library, and package the single header before using it in testing.
* Use gencpp editor/scanner functionality to give it more rich context refactors.
* Port to other platforms.
* Ability to change the naming convention of a signature (snake_case to PascalCase, etc)

163
Test/.clang-format Normal file
View File

@ -0,0 +1,163 @@
# Format Style Options - Created with Clang Power Tools
---
AccessModifierOffset: -4
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: Right
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AlignCompound: true
PadOperators: true
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
AlignConsecutiveMacros: AcrossComments
AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortLambdasOnASingleLine: None
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BeforeLambdaBody: false
BeforeWhile: false
# BreakAfterAttributes: Always
# BreakArrays: false
# BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: true
BreakInheritanceList: BeforeComma
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakStringLiterals: true
ColumnLimit: 180
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseBlocks: true
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentRequires: true
IndentWidth: 4
IndentWrappedFunctionNames: false
# InsertNewlineAtEOF: true
InsertTrailingCommas: Wrapped
LambdaBodyIndentation: OuterScope
Language: Cpp
MaxEmptyLinesToKeep: 4
NamespaceIndentation: All
PointerAlignment: Left
QualifierAlignment: Leave
ReferenceAlignment: Left
ReflowComments: true
# RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 40
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: true
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptControlMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpacesBeforeTrailingComments: 4
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesInAngles: true
SpacesInCStyleCastParentheses: true
SpacesInConditionalStatement: true
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 20
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: c++17
TabWidth: 4
UseTab: ForIndentation
...

View File

@ -1,117 +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_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");
}

View File

@ -1,13 +1,11 @@
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')
add_project_arguments('-DBuild_Debug', language : ['c', 'cpp'])
endif
executable( 'refactor', 'refactor.cpp' )
executable( 'refactor', 'refactor.refactored.cpp' )

204
Test/project.refactor Normal file
View File

@ -0,0 +1,204 @@
__VERSION 1
// not : Ignore
// include : #includes
// word : Alphanumeric or underscore
// namespace : Prefix search and replace (c-namspaces).
// regex : Unavailable in __VERSION 1.
// Precedence (highest to lowest):
// word, namespace, regex
// Comments
not comments
// Includes
include zpl.h, zpl.refactored.h
include Bloat.hpp, Bloat.refactored.hpp
include Bloat.cpp, Bloat.refactored.cpp
include IO.hpp, IO.refactored.hpp
include IO.cpp, IO.refactored.cpp
include Spec.hpp, Spec.refactored.hpp
include Spec.cpp, Spec.refactored.cpp
// Removes the namespace.
namespace zpl_
namespace zpl_re_, regex_
namespace zpl_random_, rng_
namespace zpl_pr, process_
namespace zpl__, __
namespace ZPL_ADT_, EADT
namespace ZPL_ALLOCATION_, EAllocation
namespace ZPL_CSV_ERROR, ECSV_Error
namespace ZPL_FILE_MODE_, EFileMode_
namespace ZPL_FILE_ERROR_, EFileError_
namespace ZPL_SEEK_WHENCE_, ESeekWhence_
namespace ZPL_FILE_STANDARD_, EFileStandard_
namespace ZPL_FILE_STREAM_, EFileStream_
namespace ZPL_JSON_ERROR_, EJSON_Error_
namespace ZPL_RE_ERROR_, ERegexError_
namespace ZPL_OPTS_, EOpts_
namespace ZPL_OPTS_ERR, EOptsError_
namespace ZPL_PR_OPTS_, EProcessOpts_
// Macro exposure
//namespace ZPL_
//not word ZPL_IMPLEMENTATION
// Type Renames
word zpl_aabb2, AABB2
word zpl_aabb3, AABB3
word zpl_adt_assign_style, ADT_AssignStyle
word zpl_adt_delim_style, ADT_DelimStyle
word zpl_adt_error, ADT_Error
word zpl_adt_naming_style, ADT_NamingStyle
word zpl_adt_node, ADT_Node
word zpl_adt_props, ADT_Props
word zpl_adt_type, ADT_Type
word zpl_affinity, Affinity
word zpl_allocation_header_event, AllocationHeaderEvent
word zpl_allocator, AllocatorInfo
word zpl_allocator_proc, AllocatorProc
word zpl_alloc_flags, AllocFlags
word zpl_alloc_type, AllocType
word zpl_arena, Arena
word zpl_arena_snapshot, ArenaSnapshot
word zpl_array, Array
word zpl_array_header, ArrayHeader
word zpl_buffer, Buffer
word zpl_buffer_header, BufferHeader
word zpl_compare_proc, CompareProc
word zpl_csv_error, CSV_Error
word zpl_csv_object, CSV_Object
word zpl_dll_handle, DLLHandle
word zpl_dll_proc, DLLProc
word zpl_dir_type, DirType
word zpl_dir_entry, DirEntry
word zpl_dir_info, DirInfo
word zpl_file_contents, FileContents
word zpl_file_descriptor, FileDescriptor
word zpl_file_error, FileError
word zpl_file, FileInfo
word zpl_file_mode, FileMode
word zpl_file_mode_flag, FileModeFlag
word zpl_file_operations, FileOperations
word zpl_file_close_proc, FileCloseProc
word zpl_file_read_proc, FileReadProc
word zpl_file_seek_proc, FileSeekProc
word zpl_file_write_proc, FileWriteProc
word zpl_file_standard_type, FileStandardType
word zpl_file_stream_flags, FileStreamFlags
word zpl_float2, Float2
word zpl_float3, Float3
word zpl_float4, Float4
word zpl_frustum, Frustum
word zpl_half, Half
word zpl_jobs_priority, JobsPriority
word zpl_jobs_status, JobsStatus
word zpl_jobs_system, JobsSystem
word zpl_json_error, JSON_Error
word zpl_json_object, JSON_Object
word zpl_list, List
word zpl_mat2, Mat2
word zpl_mat3, Mat3
word zpl_mat4, Mat4
word zpl_mutex, Mutex
word zpl_plane, Plane
word zpl_pool, Pool
word zpl_pr, Process
word zpl_pr_si, ProcessStartupInfo
word zpl_quat, Quat
word zpl_rect2, Rect2
word zpl_rect3, Rect3
word zpl_re, Regex
word zpl_re_capture, RegexCapture
word zpl_regex_error, RegexError
wrod zpl_random, RNG
word zpl_rune, Rune
word zpl_scratch_memory, ScratchMemory
word zpl_seek_whence_type, SeekWhenceType
word zpl_semaphore, Semaphore
word zpl_string, String
word zpl_string_header, StringHeader
word zpl_sync, Sync
word zpl_opts, Opts
word zpl_opts_entry, OptsEntry
word zpl_opts_err, OptsError
word zpl_opts_err_type, OptsErrorType
word zpl_opts_types, OptsTypes
word zpl_tar_errors, TarErrors
word zpl_tar_file_type, TarFileType
word zpl_tar_record, TarRecord
word zpl_tar_unpack_proc, TarUnpackProc
word zpl_thread, Thread
word zpl_thread_job, ThreadJob
word zpl_thread_proc, ThreadProc
word zpl_thread_queue, ThreadQueue
word zpl_thread_worker, ThreadWorker
word zpl_vec2, Vec2
word zpl_vec3, Vec3
word zpl_vec4, Vec4
word zpl_virtual_memory, VirtualMemory
// Function Renames
word zpl_lfence, fence_load
word zpl_mfence, fence_memory
word zpl_sfence, fence_store
word zpl_memchr, mem_find
word zpl_memcopy, mem_copy
word zpl_memmove, mem_move
word zpl_memset, mem_set
word zpl_memswap, mem_swap
word zpl_exit, process_exit
word zpl_rdtsc, read_cpu_time_stamp_counter
word zpl_strcmp, str_compare
word zpl_strncmp, str_compare
word zpl_strcat, str_concat
word zpl_strcpy, str_copy
word zpl_strncpy, str_copy
word zpl_strlcpy, str_copy_nulpad
word zpl_strdup, str_dup
word zpl_strchr, str_find
word zpl_strrchr, str_find_last
word zpl_strstr, str_find_substr
word zpl_snprintf, str_fmt
word zpl_snprintf_va, str_fmt_va
word zpl_asprintf, str_fmt_alloc
word zpl_asprintf_va, str_fmt_alloc_va
word zpl_bprintf, str_fmt_buf
word zpl_bprintf_va, str_fmt_buf_va
word zpl_printf, str_fmt_out
word zpl_printf_va, str_fmt_out_va
word zpl_printf_err, str_fmt_out_err
word zpl_printf_err_va, str_fmt_out_err_va
word zpl_fprintf, str_fmt_file
word zpl_fprintf_va, str_fmt_file_va
word zpl_strlen, str_len
word zpl_strnlen, str_len
word zpl_strrev, str_reverse
word zpl_strtok, str_tok
word zpl_strtok_r, str_tok_reentrant
word zpl_sleep, thread_sleep
word zpl_sleep_ms, thread_sleep_ms
word zpl_yield_thread, thread_yield
word zpl_utf8_strlen, utf8_len
word zpl_utf8_strnlen, utf8_len
// Undesired typedefs
word zpl_i8, s8
word zpl_i16, s16
word zpl_i32, s32
word zpl_i64, s64
word zpl_u8, u8
word zpl_u16, u16
word zpl_u32, u32
word zpl_u64, u64
word zpl_intptr, sptr
word zpl_uintptr, uptr
word zpl_usize, uw
word zpl_isize, sw
// Undesired exposures.
word cast, zpl_cast
not word zpl_thread_local

View File

@ -1,775 +0,0 @@
#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();
}

6
Test/stb_image.refactor Normal file
View File

@ -0,0 +1,6 @@
__VERSION 1
not comments
namespace stbi_
not namepsace stbi__

View File

@ -1,68 +0,0 @@
__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

214
Test/zpl.refactor Normal file
View File

@ -0,0 +1,214 @@
__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
// This is a cpp refactor specification for zpl.h
// Its intended that the content will be within a cpp namesapce
// Comments
not comments
// Header files
not include zpl_hedley.h
not include allocator.h
not include array.h
not include header/essentials/collections/array.h
not include header/essentials/collections/list.h
not include header/core/file.h
not include header/opts.h
not include header/regex.h
not include source/core/file.c
not include source/opts.c
// Removes the namespace.
namespace zpl_
namespace zpl_re_, regex_
namespace zpl_random_, rng_
namespace zpl_pr, process_
namespace zpl__, __
namespace ZPL_ADT_, EADT
namespace ZPL_ALLOCATION_, EAllocation
namespace ZPL_CSV_ERROR, ECSV_Error
namespace ZPL_FILE_MODE_, EFileMode_
namespace ZPL_FILE_ERROR_, EFileError_
namespace ZPL_SEEK_WHENCE_, ESeekWhence_
namespace ZPL_FILE_STANDARD_, EFileStandard_
namespace ZPL_FILE_STREAM_, EFileStream_
namespace ZPL_JSON_ERROR_, EJSON_Error_
namespace ZPL_RE_ERROR_, ERegexError_
namespace ZPL_OPTS_, EOpts_
namespace ZPL_OPTS_ERR, EOptsError_
namespace ZPL_PR_OPTS_, EProcessOpts_
// Macro exposure
//namespace ZPL_
//not word ZPL_IMPLEMENTATION
// Type Renames
word zpl_aabb2, AABB2
word zpl_aabb3, AABB3
word zpl_adt_assign_style, ADT_AssignStyle
word zpl_adt_delim_style, ADT_DelimStyle
word zpl_adt_error, ADT_Error
word zpl_adt_naming_style, ADT_NamingStyle
word zpl_adt_node, ADT_Node
word zpl_adt_props, ADT_Props
word zpl_adt_type, ADT_Type
word zpl_affinity, Affinity
word zpl_allocation_header_event, AllocationHeaderEvent
word zpl_allocator, AllocatorInfo
word zpl_allocator_proc, AllocatorProc
word zpl_alloc_flags, AllocFlags
word zpl_alloc_type, AllocType
word zpl_arena, Arena
word zpl_arena_snapshot, ArenaSnapshot
word zpl_array, Array
word zpl_array_header, ArrayHeader
word zpl_buffer, Buffer
word zpl_buffer_header, BufferHeader
word zpl_compare_proc, CompareProc
word zpl_csv_error, CSV_Error
word zpl_csv_object, CSV_Object
word zpl_dll_handle, DLLHandle
word zpl_dll_proc, DLLProc
word zpl_dir_type, DirType
word zpl_dir_entry, DirEntry
word zpl_dir_info, DirInfo
word zpl_file_contents, FileContents
word zpl_file_descriptor, FileDescriptor
word zpl_file_error, FileError
word zpl_file, FileInfo
word zpl_file_mode, FileMode
word zpl_file_mode_flag, FileModeFlag
word zpl_file_operations, FileOperations
word zpl_file_close_proc, FileCloseProc
word zpl_file_read_proc, FileReadProc
word zpl_file_seek_proc, FileSeekProc
word zpl_file_write_proc, FileWriteProc
word zpl_file_standard_type, FileStandardType
word zpl_file_stream_flags, FileStreamFlags
word zpl_float2, Float2
word zpl_float3, Float3
word zpl_float4, Float4
word zpl_frustum, Frustum
word zpl_half, Half
word zpl_jobs_priority, JobsPriority
word zpl_jobs_status, JobsStatus
word zpl_jobs_system, JobsSystem
word zpl_json_error, JSON_Error
word zpl_json_object, JSON_Object
word zpl_list, List
word zpl_mat2, Mat2
word zpl_mat3, Mat3
word zpl_mat4, Mat4
word zpl_mutex, Mutex
word zpl_plane, Plane
word zpl_pool, Pool
word zpl_pr, Process
word zpl_pr_si, ProcessStartupInfo
word zpl_quat, Quat
word zpl_rect2, Rect2
word zpl_rect3, Rect3
word zpl_re, Regex
word zpl_re_capture, RegexCapture
word zpl_regex_error, RegexError
wrod zpl_random, RNG
word zpl_rune, Rune
word zpl_scratch_memory, ScratchMemory
word zpl_seek_whence_type, SeekWhenceType
word zpl_semaphore, Semaphore
word zpl_string, String
word zpl_string_header, StringHeader
word zpl_sync, Sync
word zpl_opts, Opts
word zpl_opts_entry, OptsEntry
word zpl_opts_err, OptsError
word zpl_opts_err_type, OptsErrorType
word zpl_opts_types, OptsTypes
word zpl_tar_errors, TarErrors
word zpl_tar_file_type, TarFileType
word zpl_tar_record, TarRecord
word zpl_tar_unpack_proc, TarUnpackProc
word zpl_thread, Thread
word zpl_thread_job, ThreadJob
word zpl_thread_proc, ThreadProc
word zpl_thread_queue, ThreadQueue
word zpl_thread_worker, ThreadWorker
word zpl_vec2, Vec2
word zpl_vec3, Vec3
word zpl_vec4, Vec4
word zpl_virtual_memory, VirtualMemory
// Function Renames
word zpl_lfence, fence_load
word zpl_mfence, fence_memory
word zpl_sfence, fence_store
word zpl_memchr, mem_find
word zpl_memcopy, mem_copy
word zpl_memmove, mem_move
word zpl_memset, mem_set
word zpl_memswap, mem_swap
word zpl_exit, process_exit
word zpl_rdtsc, read_cpu_time_stamp_counter
word zpl_strcmp, str_compare
word zpl_strncmp, str_compare
word zpl_strcat, str_concat
word zpl_strcpy, str_copy
word zpl_strncpy, str_copy
word zpl_strlcpy, str_copy_nulpad
word zpl_strdup, str_dup
word zpl_strchr, str_find
word zpl_strrchr, str_find_last
word zpl_strstr, str_find_substr
word zpl_snprintf, str_fmt
word zpl_snprintf_va, str_fmt_va
word zpl_asprintf, str_fmt_alloc
word zpl_asprintf_va, str_fmt_alloc_va
word zpl_bprintf, str_fmt_buf
word zpl_bprintf_va, str_fmt_buf_va
word zpl_printf, str_fmt_out
word zpl_printf_va, str_fmt_out_va
word zpl_printf_err, str_fmt_out_err
word zpl_printf_err_va, str_fmt_out_err_va
word zpl_fprintf, str_fmt_file
word zpl_fprintf_va, str_fmt_file_va
word zpl_strlen, str_len
word zpl_strnlen, str_len
word zpl_strrev, str_reverse
word zpl_strtok, str_tok
word zpl_strtok_r, str_tok_reentrant
word zpl_sleep, thread_sleep
word zpl_sleep_ms, thread_sleep_ms
word zpl_yield_thread, thread_yield
word zpl_utf8_strlen, utf8_len
word zpl_utf8_strnlen, utf8_len
// Undesired typedefs
word zpl_i8, s8
word zpl_i16, s16
word zpl_i32, s32
word zpl_i64, s64
word zpl_u8, u8
word zpl_u16, u16
word zpl_u32, u32
word zpl_u64, u64
word zpl_intptr, sptr
word zpl_uintptr, uptr
word zpl_usize, uw
word zpl_isize, sw
// Undesired exposures.
word cast, zpl_cast
not word zpl_thread_local
// Name Conflicts
word file_size, fsize
word alloc, allocator

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
@echo off
if not exist build\nul (
meson setup build
)
echo:
ninja -C build

View File

@ -1,5 +0,0 @@
@echo off
if exist build\nul (
@RD /S /Q "build"
)

View File

@ -1,15 +0,0 @@
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 )

View File

@ -1,885 +0,0 @@
#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();
}

170
project/Bloat.cpp Normal file
View File

@ -0,0 +1,170 @@
#define BLOAT_IMPL
#include "Bloat.hpp"
namespace Global
{
bool ShouldShowDebug = false;
}
namespace Memory
{
zpl_arena Global_Arena {};
void setup()
{
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), Initial_Reserve );
if ( Global_Arena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void resize( uw new_size )
{
void* new_memory = zpl_resize( zpl_heap(), Global_Arena.physical_start, Global_Arena.total_size, new_size );
if ( new_memory == nullptr )
{
fatal("Failed to resize global arena!");
}
Global_Arena.physical_start = new_memory;
Global_Arena.total_size = new_size;
}
void cleanup()
{
zpl_arena_free( & Global_Arena);
}
}
bool opts_custom_add(zpl_opts* opts, zpl_opts_entry *t, char* b)
{
if (t->type != ZPL_OPTS_STRING)
{
return false;
}
t->text = zpl_string_append_length(t->text, " ", 1);
t->text = zpl_string_appendc( t->text, b );
return true;
}
b32 opts_custom_compile(zpl_opts *opts, int argc, char **argv)
{
zpl_b32 had_errors = false;
for (int i = 1; i < argc; ++i)
{
char* arg = argv[i];
if (*arg)
{
arg = (char*)zpl_str_trim(arg, false);
if (*arg == '-')
{
zpl_opts_entry* entry = 0;
zpl_b32 checkln = false;
if ( *(arg + 1) == '-')
{
checkln = true;
++arg;
}
char *b = arg + 1, *e = b;
while (zpl_char_is_alphanumeric(*e) || *e == '-' || *e == '_') {
++e;
}
entry = zpl__opts_find(opts, b, (e - b), checkln);
if (entry)
{
char *ob = b;
b = e;
/**/
if (*e == '=')
{
if (entry->type == ZPL_OPTS_FLAG)
{
*e = '\0';
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
b = e = e + 1;
}
else if (*e == '\0')
{
char *sp = argv[i+1];
if (sp && *sp != '-' && (zpl_array_count(opts->positioned) < 1 || entry->type != ZPL_OPTS_FLAG))
{
if (entry->type == ZPL_OPTS_FLAG)
{
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
arg = sp;
b = e = sp;
++i;
}
else
{
if (entry->type != ZPL_OPTS_FLAG)
{
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_MISSING_VALUE);
had_errors = true;
continue;
}
entry->met = true;
continue;
}
}
e = (char *)zpl_str_control_skip(e, '\0');
zpl__opts_set_value(opts, entry, b);
if ( (i + 1) < argc )
{
for ( b = argv[i + 1]; i < argc && b[0] != '-'; i++, b = argv[i + 1] )
{
opts_custom_add(opts, entry, b );
}
}
}
else
{
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_OPTION);
had_errors = true;
}
}
else if (zpl_array_count(opts->positioned))
{
zpl_opts_entry *l = zpl_array_back(opts->positioned);
zpl_array_pop(opts->positioned);
zpl__opts_set_value(opts, l, arg);
}
else
{
zpl__opts_push_error(opts, arg, ZPL_OPTS_ERR_VALUE);
had_errors = true;
}
}
}
return !had_errors;
}

View File

@ -1,21 +1,13 @@
/*
BLOAT.
ZPL requires ZPL_IMPLEMENTATION whereever this library is included.
This file assumes it will be included in one compilation unit.
*/
#pragma once
#if __clang__
# pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wswitch"
# pragma clang diagnostic ignored "-Wunused-variable"
#ifdef BLOAT_IMPL
# define ZPL_IMPLEMENTATION
#endif
#pragma region ZPL INCLUDE
#if __clang__
# pragma clang diagnostic push
@ -35,13 +27,11 @@
// # define ZPL_MODULE_DLL
# define ZPL_MODULE_OPTS
// # define ZPL_MODULE_PROCESS
// # define ZPL_MODULE_MATH
// # define ZPL_MODULE_MAT
// # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER
// extern "C" {
#include "zpl.h"
// }
#if __clang__
# pragma clang diagnostic pop
@ -50,6 +40,15 @@
#if __clang__
# pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wswitch"
# pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic ignored "-Wunknown-pragmas"
#endif
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
#define ct constexpr
@ -64,15 +63,15 @@
do \
{ \
static \
bool Done = true; \
bool Done = false; \
if ( Done ) \
return; \
Done = false; \
Done = true; \
} \
while(0) \
using c8 = char;
using b32 = zpl_b32;
using s8 = zpl_i8;
using s32 = zpl_i32;
using s64 = zpl_i64;
@ -83,33 +82,69 @@ using f64 = zpl_f64;
using uw = zpl_usize;
using sw = zpl_isize;
using Line = char*;
using Array_Line = zpl_array( Line );
ct c8 const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
namespace Global
{
extern bool ShouldShowDebug;
}
namespace Memory
{
zpl_arena Global_Arena {};
ct uw Initial_Reserve = zpl_megabytes(2);
extern zpl_arena Global_Arena;
#define g_allocator zpl_arena_allocator( & Memory::Global_Arena)
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 setup();
void resize( uw new_size );
void cleanup();
}
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, ...)
{
zpl_arena_free( & Global_Arena);
}
if ( Global::ShouldShowDebug == false )
return 0;
sw res;
va_list va;
va_start(va, fmt);
res = zpl_printf_va(fmt, va);
va_end(va);
return res;
}
void fatal()
inline
void fatal(char const *fmt, ...)
{
Memory::cleanup();
zpl_assert_crash("FATAL");
zpl_local_persist zpl_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
}

146
project/IO.cpp Normal file
View File

@ -0,0 +1,146 @@
#include "IO.hpp"
namespace IO
{
using array_string = zpl_array( zpl_string );
namespace StaticData
{
array_string Sources = nullptr;
array_string Destinations = nullptr;
zpl_string Specification = nullptr;
// Current source and destination index.
// Used to keep track of which file get_next_source or write refer to.
sw Current = -1;
char* Current_Content = nullptr;
uw Current_Size = 0;
uw Largest_Src_Size = 0;
zpl_arena MemSpec;
zpl_arena MemSrc;
}
using namespace StaticData;
void prepare()
{
const sw num_srcs = zpl_array_count( Sources );
// Determine the largest content size.
sw left = num_srcs;
zpl_string* path = Sources;
do
{
zpl_file src = {};
zpl_file_error error = zpl_file_open( & src, *path );
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("IO::Prepare - Could not open source file: %s", *path );
}
const sw fsize = zpl_file_size( & src );
if ( fsize > Largest_Src_Size )
{
Largest_Src_Size = fsize;
}
zpl_file_close( & src );
}
while ( path++, left--, left > 0 );
uw persist_size = Largest_Src_Size * 2 + 8;
zpl_arena_init_from_allocator( & MemSrc, zpl_heap(), persist_size );
}
void cleanup()
{
zpl_arena_free( & MemSpec );
zpl_arena_free( & MemSrc );
}
Array_Line get_specification()
{
zpl_file file {};
zpl_file_error error = zpl_file_open( & file, Specification);
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("Could not open the specification file: %s", Specification);
}
sw fsize = scast( sw, zpl_file_size( & file ) );
if ( fsize <= 0 )
{
fatal("No content in specificaiton to process");
}
zpl_arena_init_from_allocator( & MemSpec, zpl_heap(), fsize * 3 + 8 );
char* content = rcast( char*, zpl_alloc( zpl_arena_allocator( & MemSpec), fsize + 1) );
zpl_file_read( & file, content, fsize);
zpl_file_close( & file );
content[fsize] = 0;
Array_Line lines = zpl_str_split_lines( zpl_arena_allocator( & MemSpec ), content, false );
return lines;
}
char* get_next_source()
{
zpl_memset( MemSrc.physical_start, 0, MemSrc.total_allocated);
zpl_free_all( zpl_arena_allocator( & MemSrc) );
Current++;
zpl_file file {};
zpl_file_error error = zpl_file_open( & file, Sources[Current]);
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal("IO::get_next_source - Could not open the source file: %s", Sources[Current]);
}
auto size = zpl_file_size( & file );
Current_Size = scast( sw, size );
if ( Current_Size <= 0 )
return nullptr;
Current_Content = rcast( char* , zpl_alloc( zpl_arena_allocator( & MemSrc), Current_Size + 1) );
zpl_file_read( & file, Current_Content, Current_Size );
zpl_file_close( & file );
Current_Content[Current_Size] = 0;
Current_Size++;
return Current_Content;
}
void write( zpl_string refacotred )
{
if ( refacotred == nullptr)
return;
zpl_string dst = Destinations[Current];
zpl_file file_dest {};
zpl_file_error error = zpl_file_create( & file_dest, dst );
if ( error != ZPL_FILE_ERROR_NONE )
{
fatal( "Unable to open destination file: %s\n", dst );
}
zpl_file_write( & file_dest, refacotred, zpl_string_length(refacotred) );
zpl_file_close( & file_dest );
}
}

25
project/IO.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "Bloat.hpp"
namespace IO
{
ct uw Path_Size_Largest = zpl_kilobytes(1);
// Preps the IO by loading all the files and checking to see what the largest size is.
// The file with the largest size is used to determine the size of the persistent memory.
void prepare();
// Frees the persistent and transient memory arenas.
void cleanup();
// Provides the content of the specification.
Array_Line get_specification();
// Provides the content of the next source, broken up as a series of lines.
char* get_next_source();
// Writes the refactored content ot the current corresponding destination.
void write( zpl_string refactored );
}

41
project/Readme.md Normal file
View File

@ -0,0 +1,41 @@
# Documentation
The current implementation is divided into 4 parts:
* Bloat : General library provider.
* IO : File I/O processing.
* Spec : Specification parsing.
* Refactor : Entrypoint, argument parsing, and refactoring process.
The files are setup to compile as one unit. As such the source files for Bloat, IO, and Spec are located within `refactor.cpp`.
Bloat contains some aliasing of some C++ keywords and does not use the standard library. Instead a library called ZPL is used (Single header replacement).
The program has pretty much no optimizations made to it, its just regular loops with no threading.
Just tried to keep the memory at a reasonable size for what it does.
The program execution is pretty much outlined quite clearly in `int main()`.
1. Setup initial reserve of global memory in an arena.
2. Parse the arguments provided.
3. Prepare IO's memory for retreviing content.
4. Reserve memory for the refactor buffer.
5. Parse the specification file
6. Iterate through all provided files to refactor and write the refactored content to the specificed destintation files.
7. Cleanup all reserves of memory`*`
`*` This technically can be skipped on windows, may be worth doing to reduce latency of process shutdown.
There are constraints for specific variables;
* `Path_Size_Largest` : Longest path size is set to 1 KB of characters.
* `Token_Max_Length` : Set to 128 KB.
* `Array_Reserve_Num` : Is set to 4 KB.
* Initial Global arena size : Set to 2 megabytes.
The `Path_Size_Largest` and `Token_Max_Length` are compile-time constraints that the runtime will not have a fallback for, if current size is not enough it will need to be changed for your use case.
`Array_Reserve_Num` is used to dictate the assumed amount of tokens will be held in total for any of spec's arrays holding ignores and refactor entries. If any of the array's exceed 4 KB they will grow triggering a resize which will bog down the speed of the refactor. Adjust if you think you can increase or lower for use case.
Initial Global arena size is a finicy thing, its most likely going to be custom allocator at one point so that it can handle growing properly, right now its just grows if the amount of memory file paths will need for sources is greater than 1 MB.

328
project/Spec.cpp Normal file
View File

@ -0,0 +1,328 @@
#include "Spec.hpp"
#include "IO.hpp"
namespace Spec
{
ct uw Array_Reserve_Num = zpl_kilobytes(4);
ct uw Token_Max_Length = 128;
namespace StaticData
{
// Custom comment signatures not supported yet (only C/C++ comments for now)
bool Ignore_Comments = false;
Array_Entry Ignore_Includes;
Array_Entry Ignore_Words;
Array_Entry Ignore_Regexes;
Array_Entry Ignore_Namespaces;
Array_Entry Includes;
Array_Entry Words;
Array_Entry Regexes;
Array_Entry Namespaces;
u32 Sig_Smallest = Token_Max_Length;
}
using namespace StaticData;
void cleanup()
{
zpl_array_free( Ignore_Includes );
zpl_array_free( Ignore_Words );
zpl_array_free( Ignore_Namespaces );
zpl_array_free( Includes );
zpl_array_free( Words );
zpl_array_free( Namespaces );
}
// Helper function for process().
forceinline
void find_next_token( Tok& type, zpl_string& token, char*& line, u32& length )
{
zpl_string_clear( token );
length = 0;
#define current line[length]
if (type == Tok::Include)
{
// Allows for '.'
while ( zpl_char_is_alphanumeric( current )
|| current == '_'
|| current == '.'
|| current == '/'
|| current == '\\' )
{
length++;
}
}
else
{
while ( zpl_char_is_alphanumeric( current ) || current == '_' )
{
length++;
}
}
#undef current
if ( length == 0 )
{
fatal("Failed to find valid initial token");
}
token = zpl_string_append_length( token, line, length );
line += length;
}
void parse()
{
static zpl_string token = zpl_string_make_reserve( g_allocator, zpl_kilobytes(1));
static bool Done = false;
if (Done)
{
zpl_array_clear( Ignore_Includes );
zpl_array_clear( Ignore_Words );
zpl_array_clear( Ignore_Namespaces );
zpl_array_clear( Includes );
zpl_array_clear( Words );
zpl_array_clear( Namespaces );
}
else
{
Done = true;
zpl_array_init_reserve( Ignore_Includes, zpl_heap(), Array_Reserve_Num );
zpl_array_init_reserve( Ignore_Words, zpl_heap(), Array_Reserve_Num );
zpl_array_init_reserve( Ignore_Namespaces, zpl_heap(), Array_Reserve_Num );
zpl_array_init_reserve( Includes, zpl_heap(), Array_Reserve_Num );
zpl_array_init_reserve( Words, zpl_heap(), Array_Reserve_Num );
zpl_array_init_reserve( Namespaces, zpl_heap(), Array_Reserve_Num );
}
Array_Line lines = IO::get_specification();
sw left = zpl_array_count( lines );
if ( left == 0 )
{
fatal("Spec::parse: lines array imporoperly setup");
}
// Skip the first line as its the version number and we only support __VERSION 1.
left--;
lines++;
do
{
char* line = * lines;
// Ignore line if its a comment
if ( line[0] == '/' && line[1] == '/')
{
continue;
}
// Remove indent
{
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
continue;
}
}
u32 length = 0;
Tok type = Tok::Num_Tok;
bool ignore = false;
Entry entry {};
// Find a valid token
find_next_token( type, token, line, length );
// Will be reguarded as an ignore.
if ( is_tok( Tok::Not, token, length ))
{
ignore = true;
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
continue;
}
// Find the category token
find_next_token( type, token, line, length );
}
if ( is_tok( Tok::Comment, token, length ) )
{
// Custom comment signatures not supported yet (only C/C++ comments for now)
Ignore_Comments = true;
continue;
}
else if ( is_tok( Tok::Word, token, length ) )
{
type = Tok::Word;
}
else if ( is_tok( Tok::Namespace, token, length ) )
{
type = Tok::Namespace;
}
else if ( is_tok( Tok::Include, token, length ))
{
type = Tok::Include;
}
else
{
log_fmt( "Sec::Parse - Unsupported keyword: %s on line: %d", token, zpl_array_count(lines) - left );
continue;
}
// Find the first argument
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
continue;
}
find_next_token( type, token, line, length );
// First argument is signature.
entry.Sig = zpl_string_make_length( g_allocator, token, length );
if ( length < StaticData::Sig_Smallest )
StaticData::Sig_Smallest = length;
if ( line[0] == '\0' || ignore )
{
switch ( type )
{
case Tok::Word:
if ( ignore)
zpl_array_append( Ignore_Words, entry );
else
zpl_array_append( Words, entry );
break;
case Tok::Namespace:
if ( ignore)
zpl_array_append( Ignore_Namespaces, entry );
else
zpl_array_append( Namespaces, entry );
break;
case Tok::Include:
if ( ignore)
zpl_array_append( Ignore_Includes, entry );
else
zpl_array_append( Includes, entry );
break;
}
continue;
}
// Look for second argument indicator
{
bool bSkip = false;
while ( line[0] != ',' )
{
if ( line[0] == '\0' )
{
switch ( type )
{
case Tok::Word:
zpl_array_append( Words, entry );
break;
case Tok::Namespace:
zpl_array_append( Namespaces, entry );
break;
case Tok::Include:
zpl_array_append( Includes, entry );
break;
}
bSkip = true;
break;
}
line++;
}
if ( bSkip )
{
continue;
}
}
// Eat the argument delimiter.
line++;
// Remove spacing
{
bool bSkip = true;
while ( zpl_char_is_space( line[0] ) )
line++;
if ( line[0] == '\0' )
{
switch ( type )
{
case Tok::Word:
zpl_array_append( Words, entry );
break;
case Tok::Namespace:
zpl_array_append( Namespaces, entry );
break;
case Tok::Include:
zpl_array_append( Includes, entry );
break;
}
continue;
}
}
find_next_token( type, token, line, length );
// Second argument is substitute.
entry.Sub = zpl_string_make_length( g_allocator, token, length );
switch ( type )
{
case Tok::Word:
zpl_array_append( Words, entry );
continue;
case Tok::Namespace:
zpl_array_append( Namespaces, entry );
continue;
case Tok::Include:
zpl_array_append( Includes, entry );
continue;
}
}
while ( lines++, left--, left > 0 );
}
}

76
project/Spec.hpp Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include "Bloat.hpp"
namespace Spec
{
enum Tok
{
Not,
Comment,
Include,
Namespace,
Word,
Num_Tok
};
forceinline
char const* str_tok( Tok tok )
{
static
char const* tok_to_str[ Tok::Num_Tok ] =
{
"not",
"comments",
"include",
"namespace",
"word",
};
return tok_to_str[ tok ];
}
forceinline
char strlen_tok( Tok tok )
{
static
const u8 tok_to_len[ Tok::Num_Tok ] =
{
3,
8,
7,
9,
4,
};
return tok_to_len[ tok ];
}
forceinline
bool is_tok( Tok tok, zpl_string str, u32 length )
{
char const* tok_str = str_tok(tok);
const u8 tok_len = strlen_tok(tok);
if ( tok_len != length)
return false;
s32 result = zpl_strncmp( tok_str, str, tok_len );
return result == 0;
}
struct Entry
{
zpl_string Sig = nullptr; // Signature
zpl_string Sub = nullptr; // Substitute
};
using Array_Entry = zpl_array( Entry );
void cleanup();
// Extract the specificication from the provided file.
void parse();
}

687
project/refactor.cpp Normal file
View File

@ -0,0 +1,687 @@
#include "Bloat.cpp"
#include "IO.cpp"
#include "Spec.cpp"
void parse_options( int num, char** arguments )
{
zpl_opts opts;
zpl_opts_init( & opts, zpl_heap(), "refactor");
zpl_opts_add( & opts, "num", "num" , "Number of files to refactor" , ZPL_OPTS_INT );
zpl_opts_add( & opts, "src" , "src" , "File/s to refactor" , ZPL_OPTS_STRING);
zpl_opts_add( & opts, "dst" , "dst" , "File/s post refactor" , ZPL_OPTS_STRING);
zpl_opts_add( & opts, "spec", "spec", "Specification for refactoring", ZPL_OPTS_STRING);
zpl_opts_add( & opts, "debug", "debug", "Allows for wait to attach", ZPL_OPTS_FLAG);
if (opts_custom_compile( & opts, num, arguments))
{
sw num = 0;
if ( zpl_opts_has_arg( & opts, "debug" ) )
{
#if Build_Debug
zpl_printf("Will wait (pause available for attachment)");
char pause = getchar();
#endif
Global::ShouldShowDebug = true;
}
if ( zpl_opts_has_arg( & opts, "num" ) )
{
num = zpl_opts_integer( & opts, "num", -1 );
uw global_reserve = num * sizeof(zpl_string) * IO::Path_Size_Largest * 2 + 8;
if ( global_reserve > zpl_megabytes(1) )
{
Memory::resize( global_reserve + zpl_megabytes(2) );
}
zpl_array_init_reserve( IO::Sources, g_allocator, num );
zpl_array_init_reserve( IO::Destinations, g_allocator, num );
}
else
{
num = 1;
zpl_array_init_reserve( IO::Sources, g_allocator, 1 );
zpl_array_init_reserve( IO::Destinations, g_allocator, 1 );
}
if ( zpl_opts_has_arg( & opts, "src" ) )
{
zpl_string opt = zpl_opts_string( & opts, "src", "INVALID SRC ARGUMENT" );
if ( num == 1 )
{
zpl_string path = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt ));
zpl_array_append( IO::Sources, path );
}
else
{
char buffer[ IO::Path_Size_Largest ];
uw left = num;
do
{
char* path = buffer;
sw length = 0;
do
{
path[length] = *opt;
}
while ( length++, opt++, *opt != ' ' && *opt != '\0' );
zpl_string path_string = zpl_string_make_length( g_allocator, path, length );
zpl_array_append( IO::Sources, path_string );
opt++;
}
while ( --left );
}
}
else
{
fatal( "-src not provided\n" );
}
if ( zpl_opts_has_arg( & opts, "dst" ) )
{
zpl_string opt = zpl_opts_string( & opts, "dst", "INVALID DST ARGUMENT" );
if ( num == 1 )
{
zpl_string path = zpl_string_make_length( g_allocator, opt, zpl_string_length( opt) );
zpl_array_append( IO::Destinations, path );
}
else
{
char buffer[ IO::Path_Size_Largest ];
uw left = num;
do
{
char* path = buffer;
sw length = 0;
do
{
path[length] = *opt;
}
while ( length++, opt++, *opt != ' ' && *opt != '\0' );
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" ) )
{
zpl_string opt = zpl_opts_string( & opts, "spec", "INVALID PATH" );
IO::Specification = zpl_string_make( g_allocator, "" );
IO::Specification = zpl_string_append( IO::Specification, opt );
}
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" );
}
zpl_opts_free( & opts);
}
/*
Refactor will problably have the execution and arg parsing (main and opts)
moved to a separate file.
*/
zpl_arena Refactor_Buffer;
void refactor()
{
ct static char const* include_sig = "include";
struct Token
{
u32 Start;
u32 End;
zpl_string Sig;
zpl_string Sub;
};
static zpl_array(Token) tokens = nullptr;
static zpl_string current = zpl_string_make( g_allocator, "");
#if Build_Debug
static zpl_string preview = zpl_string_make( g_allocator, "");
#endif
static bool Done = false;
if (! Done)
{
zpl_array_init( tokens, g_allocator );
Done = true;
}
else
{
zpl_array_clear( tokens );
}
// Prepare data and trackers.
char const* src = IO::get_next_source();
if ( src == nullptr )
return;
log_fmt("\n\nRefactoring: %s", IO::Sources[IO::Current]);
sw buffer_size = IO::Current_Size;
sw left = buffer_size;
uw col = 0;
uw line = 0;
#define pos (IO::Current_Size - left)
struct Snapshot
{
char const* Src;
sw Left;
uw Col;
uw Line;
};
#define move_forward( Amount_ ) \
do { \
if ( left - Amount_ <= 0 ) \
goto End_Search; \
\
const sw end = Amount_ - 1; \
\
line += src[end] == '\n'; \
left -= Amount_; \
col = (col + Amount_) * src[end] != '\n'; \
src += Amount_; \
} \
while (0) \
#define restore( Snapshot_ ) \
src = Snapshot_.Src; \
left = Snapshot_.Left; \
col = Snapshot_.Col; \
line = Snapshot_.Line \
do
{
// Check for comments if ignoring.
if ( Spec::Ignore_Comments && src[0] == '/' && left - 2 > 0 )
{
if ( src[1] == '/' )
{
move_forward( 2 );
// Force end of line.
while ( src[0] != '\n' )
{
move_forward( 1 );
}
goto Skip;
}
else if ( src[1] == '*' )
{
do
{
move_forward( 1 );
}
while ( (left - 2) > 0 && !( src[0] == '*' && src[1] == '/' ) );
move_forward( 1 );
goto Skip;
}
}
// Includes to ignore
do
{
Spec::Entry* ignore = Spec::Ignore_Includes;
sw ignores_left = zpl_array_count( Spec::Ignore_Includes);
Snapshot backup = { src, left, col, line };
if ( '#' != src[0] )
break;
move_forward( 1 );
// Ignore whitespace
while ( zpl_char_is_space( src[0] ) )
{
move_forward( 1 );
}
if ( zpl_strncmp( include_sig, src, sizeof(include_sig) - 1 ) != 0 )
{
restore( backup );
break;
}
const u32 sig_size = sizeof(include_sig) - 1;
move_forward( sig_size );
// Ignore whitespace
while ( zpl_char_is_space( src[0] ) || src[0] == '\"' || src[0] == '<' )
{
move_forward(1);
}
for ( ; ignores_left; ignores_left--, ignore++ )
{
zpl_string_clear( current );
u32 sig_length = zpl_string_length( ignore->Sig );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
log_fmt("\nIgnored %-81s line %d, col %d", current, line, col );
const sw length = zpl_string_length( current );
// The + 1 is for the closing " or > of the include
move_forward( length + 1 );
// Force end of line.
while ( src[0] != '\n' )
{
move_forward( 1 );
}
goto Skip;
}
}
restore( backup );
}
while (false);
// Word Ignores
{
Spec::Entry* ignore = Spec::Ignore_Words;
sw ignores_left = zpl_array_count( Spec::Ignore_Words);
for ( ; ignores_left; ignores_left--, ignore++ )
{
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, src, sig_length );
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
char before = src[-1];
char after = src[sig_length];
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|| zpl_char_is_alphanumeric( after ) || after == '_' )
{
continue;
}
log_fmt("\nIgnored %-81s line %d, col %d", current, line, col );
move_forward( sig_length );
goto Skip;
}
}
}
// Namespace Ignores
{
Spec::Entry* ignore = Spec::Ignore_Namespaces;
sw ignores_left = zpl_array_count( Spec::Ignore_Namespaces);
for ( ; ignores_left; ignores_left--, ignore++ )
{
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, src, sig_length );
if ( zpl_string_are_equal( ignore->Sig, current ) )
{
u32 length = sig_length;
char const* ns_content = src + sig_length;
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
length++;
ns_content++;
}
#if Build_Debug
zpl_string_clear( preview );
preview = zpl_string_append_length( preview, src, length );
log_fmt("\nIgnored %-40s %-40s line %d, column %d", preview, ignore->Sig, line, col );
#endif
move_forward( length );
goto Skip;
}
}
}
// Includes to match
do
{
Spec::Entry* include = Spec::Includes;
sw includes_left = zpl_array_count ( Spec::Includes);
Snapshot backup = { src, left, col, line };
if ( '#' != src[0] )
break;
move_forward( 1 );
// Ignore whitespace
while ( zpl_char_is_space( src[0] ) )
{
move_forward( 1 );
}
if ( zpl_strncmp( include_sig, src, sizeof(include_sig) - 1 ) != 0 )
{
restore( backup );
break;
}
const u32 sig_size = sizeof(include_sig) - 1;
move_forward( sig_size );
// Ignore whitespace
while ( zpl_char_is_space( src[0] ) || src[0] == '\"' || src[0] == '<' )
{
move_forward( 1 );
}
for ( ; includes_left; includes_left--, include++ )
{
zpl_string_clear( current );
u32 sig_length = zpl_string_length( include->Sig );
current = zpl_string_append_length( current, src, sig_length );
if ( zpl_string_are_equal( include->Sig, current ) )
{
Token entry {};
entry.Start = pos;
entry.End = pos + sig_length;
entry.Sig = include->Sig;
if ( include->Sub != nullptr )
{
entry.Sub = include->Sub;
buffer_size += zpl_string_length( entry.Sub) - sig_length;
}
zpl_array_append( tokens, entry );
log_fmt("\nFound %-81s line %d, column %d", current, line, col );
// The + 1 is for the closing " or > of the include
move_forward( sig_length + 1 );
// Force end of line.
while ( src[0] != '\n' )
{
move_forward( 1 );
}
goto Skip;
}
}
restore( backup );
}
while (false);
// Words to match
{
Spec::Entry* word = Spec::Words;
sw words_left = zpl_array_count ( Spec::Words);
for ( ; words_left; words_left--, word++ )
{
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, src, sig_length );
if ( zpl_string_are_equal( word->Sig, current ) )
{
char before = src[-1];
char after = src[sig_length];
if ( zpl_char_is_alphanumeric( before ) || before == '_'
|| zpl_char_is_alphanumeric( after ) || after == '_' )
{
continue;
}
Token entry {};
entry.Start = pos;
entry.End = pos + 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 );
log_fmt("\nFound %-81s line %d, column %d", current, line, col );
move_forward( sig_length );
goto Skip;
}
}
}
// Namespaces to match
{
Spec::Entry* nspace = Spec::Namespaces;
sw nspaces_left = zpl_array_count( Spec::Namespaces);
for ( ; nspaces_left; nspaces_left--, nspace++ )
{
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, src, sig_length );
if ( zpl_string_are_equal( nspace->Sig, current ) )
{
u32 length = sig_length;
char const* ns_content = src + sig_length;
while ( zpl_char_is_alphanumeric( ns_content[0] ) || ns_content[0] == '_' )
{
length++;
ns_content++;
}
Token entry {};
entry.Start = pos;
entry.End = pos + 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 );
#if Build_Debug
zpl_string_clear( preview );
preview = zpl_string_append_length( preview, src, length);
log_fmt("\nFound %-40s %-40s line %d, column %d", preview, nspace->Sig, line, col );
#endif
move_forward( length );
goto Skip;
}
}
}
Skip:
move_forward( 1 );
}
while ( left );
End_Search:
if (zpl_array_count( tokens ) == 0)
{
return;
}
// Prep data for building the content
left = zpl_array_count( tokens);
char* content = IO::Current_Content;
zpl_string refactored = zpl_string_make_reserve( zpl_arena_allocator( & Refactor_Buffer ), buffer_size );
// Generate the refactored file content.
{
Token* entry = tokens;
sw previous_end = 0;
do
{
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++;
}
while ( --left > 0 );
entry--;
if ( entry->End < IO::Current_Size )
{
refactored = zpl_string_append_length( refactored, content, IO::Current_Size - 1 - entry->End );
}
}
IO::write( refactored );
zpl_free_all( zpl_arena_allocator( & Refactor_Buffer ));
#undef pos
#undef move_forward
}
int main( int num, char** arguments )
{
Memory::setup();
parse_options( num, arguments);
IO::prepare();
// Just reserving more than we'll ever problably need.
zpl_arena_init_from_allocator( & Refactor_Buffer, zpl_heap(), IO::Largest_Src_Size * 4 + 8);
Spec::parse();
sw left = zpl_array_count( IO::Sources );
do
{
refactor();
zpl_printf("\nRefactored: %s", IO::Sources[IO::Current]);
}
while ( --left );
zpl_arena_free( & Refactor_Buffer );
Spec:: cleanup();
IO:: cleanup();
Memory::cleanup();
}

63
refactor.10x Normal file
View File

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

View File

@ -1,779 +0,0 @@
#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();
}

92
scripts/build.ci.ps1 Normal file
View File

@ -0,0 +1,92 @@
[string] $type = $null
[string] $test = $false
foreach ( $arg in $args )
{
if ( $arg -eq "test" )
{
$test = $true
}
else
{
$type = $arg
}
}
#region Regular Build
write-host "Building project`n"
$path_root = git rev-parse --show-toplevel
$path_build = Join-Path $path_root build
$path_scripts = Join-Path $path_root scripts
if ( -not( Test-Path $path_build ) )
{
$args_meson = @()
$args_meson += "setup"
$args_meson += $path_build
# Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_scripts
Push-Location $path_scripts
Invoke-Expression "& meson $args_meson"
Pop-Location
}
if ( $type )
{
$args_meson = @()
$args_meson += "configure"
$args_meson += $path_build
$args_meson += "--buildtype $($type)"
# Start-Process meson $args_meson -NoNewWindow -Wait -WorkingDirectory $path_scripts
Push-Location $path_scripts
Invoke-Expression "& meson $args_meson"
Pop-Location
}
$args_ninja = @()
$args_ninja += "-C"
$args_ninja += $path_build
Push-Location $path_root
ninja $args_ninja
Pop-Location
#endregion Regular Build
if ( $test -eq $true )
{
#region Test Build
write-host "`n`nBuilding Test`n"
# Refactor thirdparty libraries
Invoke-Expression "& $(Join-Path $PSScriptRoot 'refactor_and_format.ps1') $args"
$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
Push-Location $path_test
& meson $args_meson
Pop-Location
}
$args_ninja = @()
$args_ninja += "-C"
$args_ninja += $path_test_build
Push-Location $path_root
ninja $args_ninja
Pop-Location
#endregion Test Build
}

2
scripts/build.ps1 Normal file
View File

@ -0,0 +1,2 @@
cls
Invoke-Expression "& $(Join-Path $PSScriptRoot 'build.ci.ps1') $args"

24
scripts/clean.ps1 Normal file
View File

@ -0,0 +1,24 @@
$path_root = git rev-parse --show-toplevel
$path_build = Join-Path $path_root build
$path_test = Join-Path $path_root test
$path_test_build = Join-Path $path_test build
if ( Test-Path $path_build )
{
Remove-Item $path_build -Recurse
}
if ( Test-Path $path_test_build )
{
Remove-Item $path_test_build -Recurse
}
[string[]] $include = '*.h', '*.hpp', '*.cpp'
[string[]] $exclude =
$files = Get-ChildItem -Recurse -Path $path_test -Include $include -Exclude $exclude
if ( $files )
{
Remove-Item $files
}

12
scripts/get_sources.ps1 Normal file
View File

@ -0,0 +1,12 @@
[string[]] $include = 'refactor.cpp' #'*.c', '*.cc', '*.cpp'
# [string[]] $exclude =
$path_root = git rev-parse --show-toplevel
$path_proj = Join-Path $path_root project
$files = Get-ChildItem -Recurse -Path $path_proj -Include $include -Exclude $exclude
$sources = $files | Select-Object -ExpandProperty FullName | Resolve-Path -Relative
$sources = $sources.Replace( '\', '/' )
return $sources

19
scripts/meson.build Normal file
View File

@ -0,0 +1,19 @@
project( 'refactor', 'c', 'cpp', default_options : ['buildtype=release'] )
# add_global_arguments('-E', language : 'cpp')
includes = include_directories(
[ '../project'
, '../thirdparty'
])
get_sources = files('./get_sources.ps1')
sources = files(run_command('powershell', get_sources, check: true).stdout().strip().split('\n'))
if get_option('buildtype').startswith('debug')
add_project_arguments('-DBuild_Debug', language : ['c', 'cpp'])
endif
executable( 'refactor', sources, include_directories : includes )

View File

@ -0,0 +1,115 @@
[string[]] $include = '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp'
[string[]] $exclude = '*.g.*', '*.refactor'
$path_root = git rev-parse --show-toplevel
$path_build = Join-Path $path_root build
$path_project = Join-Path $path_root project
$path_test = Join-Path $path_root test
$path_thirdparty = Join-Path $path_root thirdparty
$refactor = Join-Path $path_build refactor.exe
# Gather the files to be formatted.
$targetFiles = @(Get-ChildItem -Recurse -Path $path_thirdparty -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
$refactoredFiles = @()
foreach ( $file in $targetFiles )
{
$destination = Join-Path $path_test (Split-Path $file -leaf)
$destination = $destination.Replace( '.h', '.refactored.h' )
$destination = $destination.Replace( '.c', '.refactored.c' )
$refactoredFiles += $destination
}
write-host "Beginning thirdpary refactor..."
$file_spec = Join-Path $path_test zpl.refactor
$refactorParams = @(
"-src=$(Join-Path $path_thirdparty "zpl.h")",
"-dst=$(Join-Path $path_test "zpl.refactored.h")",
"-spec=$($file_spec)"
)
if ( $args.Contains( "debug" ) )
{
$refactorParams += "-debug"
}
write-host "`zpl refactor: " $refactorParams
& $refactor $refactorParams
$file_spec = Join-Path $path_test "stb_image.refactor"
$refactorParams = @(
"-src=$(Join-Path $path_thirdparty "stb_image.h")",
"-dst=$(Join-Path $path_test "stb_image.refactored.h")",
"-spec=$($file_spec)"
)
if ( $args.Contains( "debug" ) )
{
$refactorParams += "-debug"
}
write-host "`n`nstb_image refactor: " $refactorParams
& $refactor $refactorParams
Write-Host "`nRefactoring complete`n"
write-host "Beginning project refactor..."
# Gather the files to be formatted.
$targetFiles = @(Get-ChildItem -Recurse -Path $path_project -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
$refactoredFiles = @()
$file_spec = Join-Path $path_test project.refactor
foreach ( $file in $targetFiles )
{
$destination = Join-Path $path_test (Split-Path $file -leaf)
$destination = $destination.Replace( '.hpp', '.refactored.hpp' )
$destination = $destination.Replace( '.cpp', '.refactored.cpp' )
$refactoredFiles += $destination
}
$refactorParams = @(
"-num=$($targetFiles.Count)"
"-src=$($targetFiles)",
"-dst=$($refactoredFiles)",
"-spec=$($file_spec)"
)
if ( $args.Contains( "debug" ) )
{
$refactorParams += "-debug"
}
& $refactor $refactorParams
write-host "`nRefactoring complete`n"
# Can't format zpl library... (It hangs clang format)
if ( $false ) {
Write-Host "Beginning format...`n"
# Format the files.
$formatParams = @(
'-i' # In-place
'-style=file' # Search for a .clang-format file in the parent directory of the source file.
'-verbose'
)
$targetFiles = @(Get-ChildItem -Recurse -Path $path_test -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
clang-format $formatParams $targetFiles
Write-Host "`nFormatting complete"
}

View File

@ -0,0 +1,38 @@
[string[]] $include = '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp'
[string[]] $exclude = '*.g.*', '*.refactor'
# Change this to your root directory if needed.
$path_root = $PSScriptRoot
# Change this to your desired destination
$path_dest = $path_root
# Gather the files to be formatted.
$targetFiles = @(Get-ChildItem -Recurse -Path $path_root -Include $include -Exclude $exclude | Select-Object -ExpandProperty FullName)
$refactoredFiles = @()
foreach ( $file in $targetFiles )
{
$destination = Join-Path $path_dest (Split-Path $file -leaf)
$destination = $destination.Replace( '.h', '.refactored.h' )
$destination = $destination.Replace( '.c', '.refactored.c' )
$refactoredFiles += $destination
}
write-host "Beginning refactor...`n"
$refactors = @(@())
$refactorParams = @(
# "-debug",
"-num=$($targetFiles.Count)"
"-src=$($targetFiles)",
"-dst=$($refactoredFiles)",
"-spec=$($file_spec)"
)
& $refactor $refactorParams
Write-Host "`nRefactoring complete`n`n"

7987
thirdparty/stb_image.h vendored Normal file

File diff suppressed because it is too large Load Diff

500
thirdparty/zpl.h vendored

File diff suppressed because it is too large Load Diff