initial commit
This commit is contained in:
commit
673eb4d056
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
.vscode
|
142
build.ps1
Normal file
142
build.ps1
Normal file
@ -0,0 +1,142 @@
|
||||
$devshell = join-path $PSScriptRoot 'devshell.ps1'
|
||||
|
||||
if ($IsWindows) {
|
||||
& $devshell -arch amd64
|
||||
}
|
||||
|
||||
# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170
|
||||
$flag_all_c = '/TC'
|
||||
$flag_c11 = '/std:c11'
|
||||
$flag_all_cpp = '/TP'
|
||||
$flag_compile = '/c'
|
||||
$flag_debug = '/Zi'
|
||||
$flag_define = '/D'
|
||||
$flag_exceptions_disabled = '/EHsc-'
|
||||
$flag_RTTI_disabled = '/GR-'
|
||||
$flag_include = '/I'
|
||||
$flag_full_src_path = '/FC'
|
||||
$flag_nologo = '/nologo'
|
||||
$flag_dll = '/LD'
|
||||
$flag_dll_debug = '/LDd'
|
||||
$flag_linker = '/link'
|
||||
# $flag_link_lib = '/lib'
|
||||
$flag_link_dll = '/DLL'
|
||||
$flag_link_no_incremental = '/INCREMENTAL:NO'
|
||||
$flag_link_mapfile = '/MAP:'
|
||||
$flag_link_optimize_references = '/OPT:REF'
|
||||
$flag_link_win_debug = '/DEBUG'
|
||||
$flag_link_win_pdb = '/PDB:'
|
||||
$flag_link_win_machine_32 = '/MACHINE:X86'
|
||||
$flag_link_win_machine_64 = '/MACHINE:X64'
|
||||
$flag_link_win_path_output = '/OUT:'
|
||||
$flag_link_win_rt_dll = '/MD'
|
||||
$flag_link_win_rt_dll_debug = '/MDd'
|
||||
$flag_link_win_rt_static = '/MT'
|
||||
$flag_link_win_rt_static_debug = '/MTd'
|
||||
$flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
|
||||
$flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
|
||||
$flag_no_optimization = '/Od'
|
||||
$flag_optimize_fast = '/O2'
|
||||
$flag_optimize_size = '/O1'
|
||||
$flag_optimize_intrinsics = '/Oi'
|
||||
$flag_optimized_debug_forceinline = '/d2Obforceinline'
|
||||
$flag_optimized_debug = '/Zo'
|
||||
$flag_preprocess_to_file = '/P'
|
||||
$flag_preprocess_preserve_comments = '/C'
|
||||
# $flag_out_name = '/OUT:'
|
||||
$flag_path_interm = '/Fo'
|
||||
$flag_path_debug = '/Fd'
|
||||
$flag_path_output = '/Fe'
|
||||
$flag_preprocess_conform = '/Zc:preprocessor'
|
||||
$flag_updated_cpp_macro = "/Zc:__cplusplus"
|
||||
$flag_set_stack_size = '/F'
|
||||
$flag_syntax_only = '/Zs'
|
||||
$flag_wall = '/Wall'
|
||||
$flag_warnings_as_errors = '/WX'
|
||||
$flag_lib_list = '/LIST'
|
||||
|
||||
$archiver = 'lib'
|
||||
$compiler = 'cl'
|
||||
$linker = 'link'
|
||||
|
||||
$path_build = join-path $PSScriptRoot 'build'
|
||||
if ( -not(test-path -Path $path_build) ) {
|
||||
new-item -ItemType Directory -Path $path_build
|
||||
}
|
||||
|
||||
push-location $path_build
|
||||
|
||||
$compiler_args = @()
|
||||
$compiler_args += $flag_nologo
|
||||
|
||||
# Constraints on interpeting all files as C code
|
||||
$compiler_args += $flag_all_c
|
||||
# Constraints on C program code-gen
|
||||
$compiler_args += $flag_exceptions_disabled
|
||||
$compiler_args += $flag_RTTI_disabled
|
||||
$compiler_args += $flag_preprocess_conform
|
||||
|
||||
# Dump preprocess file
|
||||
if ($false) {
|
||||
$compiler_args += $flag_preprocess_to_file
|
||||
$compiler_args += $flag_preprocess_preserve_comments
|
||||
}
|
||||
|
||||
# Diagnostic loggign
|
||||
$compiler_args += $flag_full_src_path
|
||||
|
||||
# Specifing output pathing
|
||||
$compiler_args += ( $flag_path_interm + $path_build + '\' )
|
||||
$compiler_args += ( $flag_path_output + $path_build + '\' )
|
||||
|
||||
$compiler_args += $flag_no_optimization
|
||||
|
||||
# Debug setup
|
||||
$compiler_args += $flag_debug
|
||||
$compiler_args += ( $flag_path_debug + $path_build + '\' )
|
||||
$compiler_args += $flag_link_win_rt_static_debug
|
||||
|
||||
# Include setup
|
||||
$compiler_args += ($flag_include + $PSScriptRoot)
|
||||
|
||||
# Specify unit to compile
|
||||
$unit = join-path $PSScriptRoot 'demo.str_cache.c'
|
||||
$compiler_args += $flag_compile, $unit
|
||||
|
||||
# Diagnoistc print for the args
|
||||
$compiler_args | ForEach-Object { Write-Host $_ }
|
||||
write-host
|
||||
|
||||
# $compiler_args += ( $flag_define + "DEMO_STR_SLICE" )
|
||||
# $compiler_args += ( $flag_define + "DEMO_STR_SLICE" )
|
||||
|
||||
# Compile the unit
|
||||
& $compiler $compiler_args
|
||||
|
||||
$binary = join-path $path_build 'demo.str_cache.exe'
|
||||
$object = join-path $path_build 'demo.str_cache.obj'
|
||||
|
||||
$pdb = join-path $path_build 'demo.str_cache.pdb'
|
||||
$map = join-path $path_build 'demo.str_cache.map'
|
||||
|
||||
if ($true) {
|
||||
$linker_args = @()
|
||||
$linker_args += $flag_nologo
|
||||
$linker_args += $flag_link_win_machine_64
|
||||
$linker_args += $flag_link_no_incremental
|
||||
$linker_args += ($flag_link_win_path_output + $binary)
|
||||
|
||||
$linker_args += $flag_link_win_debug
|
||||
$linker_args += $flag_link_win_pdb + $pdb
|
||||
$linker_args += $flag_link_mapfile + $map
|
||||
|
||||
$linker_args += $object
|
||||
|
||||
# Diagnoistc print for the args
|
||||
$linker_args | ForEach-Object { Write-Host $_ }
|
||||
write-host
|
||||
|
||||
& $linker $linker_args
|
||||
}
|
||||
|
||||
Pop-Location
|
193
demo.str_cache.c
Normal file
193
demo.str_cache.c
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
A introduction to C11 with a str cache demo.
|
||||
Attempting to showcase better conventions and constructs in C; Discovered to me as of 2025 from scouring the internet.
|
||||
*/
|
||||
|
||||
/*
|
||||
The below will be implemented within this single file.
|
||||
Because of this, definitions will be kept on a need-to-have basis to target only one vendor target and toolchain.
|
||||
We will not use nearly any libraries and will be targeting only Windows 11 x64 using MSVC.
|
||||
Even so the constructs defined and their dependencies can be properly abstracted into a ergonomic library for multiple targets with enough time and pain.
|
||||
|
||||
AI prompting will be used as a search engine I'll be provding the prompts used to gather specific vendor API information thats not-memorized.
|
||||
If the prompt fails it will be noted and I'll fallback to traditional search engines to derive a reference to a specific vendor API document.
|
||||
*/
|
||||
#if 0
|
||||
int main()
|
||||
{
|
||||
VArena cache_arena; varena_init(cache_arena);
|
||||
StrCache cache = strcache_init(varena_ainfo(cache));
|
||||
|
||||
VArena file_arena; varena_init(file_arena);
|
||||
Str path_text = lit("../demo.strcache.c");
|
||||
FileContent text_file = file_read_contents(varena_ainfo(file_arena), path_text);
|
||||
|
||||
Arena ast_arena; arena_init(ast_arena);
|
||||
|
||||
WATL_ParseOps ops = { .str_cache = &cache, .node_backing = arena_ainfo(ast_arena) }
|
||||
WATL_ParsedInfo parsed = watl_parse(text_file.content, ops);
|
||||
|
||||
watl_dbg_dump(parsed.root);
|
||||
strcache_dbg_listing(cache);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
The above makes use of the following core concepts to achieve its net result:
|
||||
* Slices
|
||||
* Arenas
|
||||
* Generic Runtime Allocator Interface
|
||||
* Hashing
|
||||
|
||||
Secondarily for the purposes of using the above sufficiently the following are also utilized:
|
||||
* Virtual Address Space
|
||||
* Read/Write Files
|
||||
* Lexing & Parsing
|
||||
* Debug printing
|
||||
|
||||
TODO(Ed): Do we introduce gencpp in this?
|
||||
*/
|
||||
|
||||
/*
|
||||
First thing we'll problably want is a way to deal with text effectively.
|
||||
So we'll setup the the minimum for that when dealing with immutable constructs.
|
||||
*/
|
||||
|
||||
// We'll need some minimum set of dependencies to adequately define the constructs.
|
||||
// ASSUMING MODERN MSVC TOOLCHAIN.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <intrin.h>
|
||||
#include <tmmintrin.h>
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef unsigned __int8 U8;
|
||||
typedef signed __int8 S8;
|
||||
typedef unsigned __int16 U16;
|
||||
typedef signed __int16 S16;
|
||||
typedef unsigned __int32 U32;
|
||||
typedef signed __int32 S32;
|
||||
typedef unsigned __int64 U64;
|
||||
typedef signed __int64 S64;
|
||||
|
||||
typedef size_t USIZE;
|
||||
typedef ptrdiff_t SSIZE;
|
||||
|
||||
// Functional style cast
|
||||
#define cast(type, data) ((type)(data))
|
||||
|
||||
// Enforces size querying uses SSIZE type.
|
||||
#define size_of(data) cast(SSIZE, data)
|
||||
|
||||
/*
|
||||
The first construct we'll utilize is a String Slice.
|
||||
In modern programming with the memory sizes utilized, it is more ergonomic to track the length of strings with their pointer.
|
||||
Most strings are not stored in some immutable table tracked statically, performance loss in doing so is negligble on modern hardware constraints.
|
||||
*/
|
||||
|
||||
typedef struct Str8 Str8;
|
||||
struct Str8 {
|
||||
char const* ptr;
|
||||
SSIZE len;
|
||||
};
|
||||
|
||||
// String iterals in C include null-terminators, we aren't interested in preserving that.
|
||||
#define lit(string_literal) (Str8){ string_literal, size_of(string_literal) - 1 };
|
||||
|
||||
// For now this string can visualized using a debugger.
|
||||
// #define DEMO__STR_SLICE
|
||||
#ifdef DEMO__STR_SLICE
|
||||
int main()
|
||||
{
|
||||
Str8 first = lit("Our first string as a slice");
|
||||
return 0;
|
||||
}
|
||||
#endif DEMO__STR_SLICE
|
||||
|
||||
/*
|
||||
We now want to be able to read a file. This will be a heavy rabbit-hole as we'll need to setup a basic file interface
|
||||
and related definitions for handling the memory.
|
||||
|
||||
For the purposes of the initial definition we'll introduced fixed-sized memory handling statically allocated onto the stack.
|
||||
*/
|
||||
|
||||
/*
|
||||
First off we need to find out how to aquire the contents of a file on Windows.
|
||||
|
||||
We'll be wrapping the operation in a procedure called file_read_contents. We'll have it take a path and optional arguments (Opts__read_file_contents).
|
||||
It will return a result in a composite struct: FileOpResult; which may be expanded as needed in the future.
|
||||
*/
|
||||
|
||||
typedef struct FileOpResult FileOpResult;
|
||||
typedef struct Opts__read_file_contents Opts__read_file_contents;
|
||||
void file__read_contents(FileOpResult* result, Str8 path, Opts__read_file_contents* opts);
|
||||
FileOpResult file_read_contents ( Str8 path, Opts__read_file_contents* opts);
|
||||
|
||||
/*
|
||||
The above is a pattern that can be provided so that whether or not the result is formatted and provided to the user via the stack is entirely optional.
|
||||
*/
|
||||
|
||||
// Now for our "Version 1"
|
||||
|
||||
#define DEMO__FILE_READ_CONTENTS_V1
|
||||
#ifdef DEMO__FILE_READ_CONTENTS_V1
|
||||
|
||||
/*
|
||||
The file contents will be returned in bytes.
|
||||
To view or manage any slice of bytes we'll be utilizing a byte slice.
|
||||
*/
|
||||
typedef struct SliceByte SliceByte;
|
||||
struct SliceByte {
|
||||
U8* ptr;
|
||||
SSIZE len;
|
||||
};
|
||||
|
||||
/*
|
||||
To address memory we'll use a memory slice.
|
||||
*/
|
||||
typedef struct SliceMem SliceMem;
|
||||
struct SliceMem {
|
||||
void* ptr;
|
||||
SSIZE len;
|
||||
};
|
||||
|
||||
struct FileOpResult
|
||||
{
|
||||
// For now we'll just have the content
|
||||
SliceByte content;
|
||||
};
|
||||
|
||||
struct Opts__read_file_contents
|
||||
{
|
||||
// For now we'll just have the backing memory provided as a slice.
|
||||
SliceMem backing;
|
||||
};
|
||||
|
||||
// We'll utilize the ReadFile procedure within the WinAPI: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
|
||||
#include "fileapi.h"
|
||||
|
||||
|
||||
#endif DEMO__FILE_READ_CONTENTS_V1
|
||||
|
||||
|
||||
|
||||
#define KILOBTYES(n) (cast(SSIZE, n) << 10)
|
||||
#define MEGABYTES(n) (cast(SSIZE, n) << 20)
|
||||
#define GIGABYTES(n) (cast(SSIZE, n) << 30)
|
||||
#define TERABYTES(n) (cast(SSIZE, n) << 40)
|
||||
|
||||
/*
|
||||
We'll be defining here Fixed-sized memory blocks using typedefs on-demand
|
||||
|
||||
They will having the following format:
|
||||
typedef U8 FMem_<size>KB [ <U8 amount> ];
|
||||
*/
|
||||
|
||||
typedef U8 FMem_1KB [ KILOBTYES(1) ];
|
||||
|
28
devshell.ps1
Normal file
28
devshell.ps1
Normal file
@ -0,0 +1,28 @@
|
||||
if ($env:VCINSTALLDIR) {
|
||||
return
|
||||
}
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Use vswhere to find the latest Visual Studio installation
|
||||
$vswhere_out = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
|
||||
if ($null -eq $vswhere_out) {
|
||||
Write-Host "ERROR: Visual Studio installation not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Find Launch-VsDevShell.ps1 in the Visual Studio installation
|
||||
$vs_path = $vswhere_out
|
||||
$vs_devshell = Join-Path $vs_path "\Common7\Tools\Launch-VsDevShell.ps1"
|
||||
|
||||
if ( -not (Test-Path $vs_devshell) ) {
|
||||
Write-Host "ERROR: Launch-VsDevShell.ps1 not found in Visual Studio installation"
|
||||
Write-Host Tested path: $vs_devshell
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Launch the Visual Studio Developer Shell
|
||||
Push-Location
|
||||
write-host @args
|
||||
& $vs_devshell @args
|
||||
Pop-Location
|
Loading…
x
Reference in New Issue
Block a user