initial commit
This commit is contained in:
		
							
								
								
									
										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 | ||||
		Reference in New Issue
	
	Block a user