More dependency movement from zpl, incremental design improvements.

Made token_fmt more ergonomic, going to have to use a similar behavior with the upfront body constructors.
This commit is contained in:
2023-07-12 01:33:11 -04:00
parent 20d307759b
commit 7828e6d2ea
26 changed files with 2009 additions and 739 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
# define ZPL_IMPLEMENTATION
#endif
// TODO: This will be removed when making the library have zero dependencies.
// TODO : This will be removed when making the library have zero dependencies.
#pragma region ZPL INCLUDE
#if __clang__
# pragma clang diagnostic push
@ -27,10 +27,16 @@
# define ZPL_MODULE_HASHING
#include "zpl.h"
#undef Array
#undef heap
#undef alloc_item
#undef alloc_array
#undef Array
#undef heap
#undef malloc
#undef mfree
#undef ZPL_ASSERT_MSG
#undef ZPL_ASSERT_NOT_NULL
#undef ZPL_DEBUG_TRAP
#undef ZPL_PANIC
using zpl::b32;
using zpl::s8;
@ -38,12 +44,15 @@ using zpl::s16;
using zpl::s32;
using zpl::s64;
using zpl::u8;
using zpl::u16;
using zpl::u32;
using zpl::u64;
using zpl::uw;
using zpl::sw;
using zpl::sptr;
using zpl::uptr;
using zpl::f32;
using zpl::f64;
// using zpl::AllocType;
// using zpl::Arena;
@ -63,39 +72,40 @@ using zpl::uptr;
// using zpl::ZPL_ALLOCATOR_FLAG_CLEAR_TO_ZERO;
using zpl::align_forward;
using zpl::align_forward_i64;
// using zpl::align_forward;
// using zpl::align_forward_i64;
// using zpl::alloc;
// using zpl::alloc_align;
// using zpl::arena_allocator;
// using zpl::arena_init_from_memory;
// using zpl::arena_init_from_allocator;
// using zpl::arena_free;
using zpl::assert_crash;
using zpl::char_first_occurence;
using zpl::char_is_alpha;
using zpl::char_is_alphanumeric;
using zpl::char_is_digit;
using zpl::char_is_hex_digit;
using zpl::char_is_space;
using zpl::crc32;
// using zpl::assert_crash;
// using zpl::char_first_occurence;
// using zpl::char_is_alpha;
// using zpl::char_is_alphanumeric;
// using zpl::char_is_digit;
// using zpl::char_is_hex_digit;
// using zpl::char_is_space;
// using zpl::crc32;
// using zpl::free_all;
using zpl::is_power_of_two;
using zpl::mem_copy;
using zpl::mem_move;
using zpl::mem_set;
using zpl::pointer_add;
// using zpl::is_power_of_two;
// using zpl::mem_copy;
// using zpl::mem_move;
// using zpl::mem_set;
// using zpl::pointer_add;
// using zpl::pool_allocator;
// using zpl::pool_init;
// using zpl::pool_free;
using zpl::process_exit;
using zpl::str_compare;
using zpl::str_copy;
using zpl::str_fmt_buf;
using zpl::str_fmt_va;
using zpl::str_fmt_out_va;
// using zpl::process_exit;
// using zpl::str_compare;
// using zpl::str_copy;
// using zpl::str_fmt_buf;
// using zpl::str_fmt_va;
// using zpl::str_fmt_out_va;
using zpl::str_fmt_out_err;
using zpl::str_fmt_out_err_va;
using zpl::str_len;
// using zpl::str_len;
using zpl::zero_size;
#if __clang__
@ -114,6 +124,27 @@ using zpl::zero_size;
#endif
/* Platform compiler */
#if defined( _MSC_VER )
# define ZPL_COMPILER_MSVC 1
#elif defined( __GNUC__ )
# define ZPL_COMPILER_GCC 1
#elif defined( __clang__ )
# define ZPL_COMPILER_CLANG 1
#elif defined( __MINGW32__ )
# define ZPL_COMPILER_MINGW 1
#elif defined( __TINYC__ )
# define ZPL_COMPILER_TINYC 1
#else
# error Unknown compiler
#endif
#ifndef zpl_cast
# define zpl_cast( Type ) ( Type )
#endif
#include "Banned.define.hpp"
@ -163,8 +194,7 @@ using zpl::zero_size;
#define rcast( Type_, Value_ ) reinterpret_cast< Type_ >( Value_ )
#define pcast( Type_, Value_ ) ( * (Type_*)( & (Value_) ) )
#define GEN_STRINGIZE_VA( ... ) #__VA_ARGS__
#define txt( ... ) GEN_STRINGIZE_VA( __VA_ARGS__ )
#define txt_to_StrC( ... ) sizeof( GEN_STRINGIZE_VA( __VA_ARGS__ ) ), GEN_STRINGIZE_VA( __VA_ARGS__ )
#define stringize( ... ) GEN_STRINGIZE_VA( __VA_ARGS__ )
#define do_once() \
do \
{ \
@ -194,7 +224,73 @@ namespace gen
constexpr
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
#pragma region Debug
#ifndef ZPL_DEBUG_TRAP
# if defined( _MSC_VER )
# if _MSC_VER < 1300
# define ZPL_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */
# else
# define ZPL_DEBUG_TRAP() __debugbreak()
# endif
# elif defined( ZPL_COMPILER_TINYC )
# define ZPL_DEBUG_TRAP() process_exit( 1 )
# else
# define ZPL_DEBUG_TRAP() __builtin_trap()
# endif
#endif
#ifndef ZPL_ASSERT_MSG
# define ZPL_ASSERT_MSG( cond, msg, ... ) \
do \
{ \
if ( ! ( cond ) ) \
{ \
assert_handler( #cond, __FILE__, zpl_cast( s64 ) __LINE__, msg, ##__VA_ARGS__ ); \
ZPL_DEBUG_TRAP(); \
} \
} while ( 0 )
#endif
#ifndef ZPL_ASSERT_NOT_NULL
# define ZPL_ASSERT_NOT_NULL( ptr ) ZPL_ASSERT_MSG( ( ptr ) != NULL, #ptr " must not be NULL" )
#endif
// NOTE: Things that shouldn't happen with a message!
#ifndef ZPL_PANIC
# define ZPL_PANIC( msg, ... ) ZPL_ASSERT_MSG( 0, msg, ##__VA_ARGS__ )
#endif
void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... );
s32 assert_crash( char const* condition );
void process_exit( u32 code );
#pragma endregion Debug
#pragma region Memory
//! Checks if value is power of 2.
ZPL_DEF_INLINE b32 is_power_of_two( sw x );
//! Aligns address to specified alignment.
ZPL_DEF_INLINE void* align_forward( void* ptr, sw alignment );
//! Aligns value to a specified alignment.
ZPL_DEF_INLINE s64 align_forward_i64( s64 value, sw alignment );
//! Moves pointer forward by bytes.
ZPL_DEF_INLINE void* pointer_add( void* ptr, sw bytes );
//! Copy non-overlapping memory from source to destination.
void* mem_copy( void* dest, void const* source, sw size );
//! Search for a constant value within the size limit at memory location.
ZPL_DEF void const* mem_find( void const* data, u8 byte_value, sw size );
//! Copy memory from source to destination.
ZPL_DEF_INLINE void* mem_move( void* dest, void const* source, sw size );
//! Set constant value at memory location with specified size.
ZPL_DEF_INLINE void* mem_set( void* data, u8 byte_value, sw size );
enum AllocType : u8
{
@ -246,7 +342,6 @@ namespace gen
# define alloc_array( allocator_, Type, count ) ( Type* )alloc( allocator_, size_of( Type ) * ( count ) )
#endif
/* heap memory analysis tools */
/* define ZPL_HEAP_ANALYSIS to enable this feature */
/* call zpl_heap_stats_init at the beginning of the entry point */
@ -266,17 +361,168 @@ namespace gen
//! The heap allocator backed by operating system's memory manager.
constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; }
// #ifndef malloc
#ifndef malloc
//! Helper to allocate memory using heap allocator.
# define malloc( sz ) alloc( heap(), sz )
// //! Helper to allocate memory using heap allocator.
// # define malloc( sz ) ZPL_NS( alloc )( ZPL_NS( heap_allocator )(), sz )
//! Helper to free memory allocated by heap allocator.
# define mfree( ptr ) free( heap(), ptr )
#endif
// //! Helper to free memory allocated by heap allocator.
// # define mfree( ptr ) ZPL_NS( free )( ZPL_NS( heap_allocator )(), ptr )
ZPL_IMPL_INLINE b32 is_power_of_two( sw x )
{
if ( x <= 0 )
return false;
return ! ( x & ( x - 1 ) );
}
// //! Alias to heap allocator.
// # define heap ZPL_NS( heap_allocator )
// #endif
ZPL_IMPL_INLINE void* align_forward( void* ptr, sw alignment )
{
uptr p;
ZPL_ASSERT( is_power_of_two( alignment ) );
p = zpl_cast( uptr ) ptr;
return zpl_cast( void* )( ( p + ( alignment - 1 ) ) & ~( alignment - 1 ) );
}
ZPL_IMPL_INLINE s64 align_forward_i64( s64 value, sw alignment )
{
return value + ( alignment - value % alignment ) % alignment;
}
ZPL_IMPL_INLINE void* pointer_add( void* ptr, sw bytes )
{
return zpl_cast( void* )( zpl_cast( u8* ) ptr + bytes );
}
ZPL_IMPL_INLINE void* mem_move( void* dest, void const* source, sw n )
{
if ( dest == NULL )
{
return NULL;
}
u8* d = zpl_cast( u8* ) dest;
u8 const* s = zpl_cast( u8 const* ) source;
if ( d == s )
return d;
if ( s + n <= d || d + n <= s ) // NOTE: Non-overlapping
return mem_copy( d, s, n );
if ( d < s )
{
if ( zpl_cast( uptr ) s % size_of( sw ) == zpl_cast( uptr ) d % size_of( sw ) )
{
while ( zpl_cast( uptr ) d % size_of( sw ) )
{
if ( ! n-- )
return dest;
*d++ = *s++;
}
while ( n >= size_of( sw ) )
{
*zpl_cast( sw* ) d = *zpl_cast( sw* ) s;
n -= size_of( sw );
d += size_of( sw );
s += size_of( sw );
}
}
for ( ; n; n-- )
*d++ = *s++;
}
else
{
if ( ( zpl_cast( uptr ) s % size_of( sw ) ) == ( zpl_cast( uptr ) d % size_of( sw ) ) )
{
while ( zpl_cast( uptr )( d + n ) % size_of( sw ) )
{
if ( ! n-- )
return dest;
d[ n ] = s[ n ];
}
while ( n >= size_of( sw ) )
{
n -= size_of( sw );
*zpl_cast( sw* )( d + n ) = *zpl_cast( sw* )( s + n );
}
}
while ( n )
n--, d[ n ] = s[ n ];
}
return dest;
}
ZPL_IMPL_INLINE void* mem_set( void* dest, u8 c, sw n )
{
if ( dest == NULL )
{
return NULL;
}
u8* s = zpl_cast( u8* ) dest;
sw k;
u32 c32 = ( ( u32 )-1 ) / 255 * c;
if ( n == 0 )
return dest;
s[ 0 ] = s[ n - 1 ] = c;
if ( n < 3 )
return dest;
s[ 1 ] = s[ n - 2 ] = c;
s[ 2 ] = s[ n - 3 ] = c;
if ( n < 7 )
return dest;
s[ 3 ] = s[ n - 4 ] = c;
if ( n < 9 )
return dest;
k = -zpl_cast( sptr ) s & 3;
s += k;
n -= k;
n &= -4;
*zpl_cast( u32* )( s + 0 ) = c32;
*zpl_cast( u32* )( s + n - 4 ) = c32;
if ( n < 9 )
return dest;
*zpl_cast( u32* )( s + 4 ) = c32;
*zpl_cast( u32* )( s + 8 ) = c32;
*zpl_cast( u32* )( s + n - 12 ) = c32;
*zpl_cast( u32* )( s + n - 8 ) = c32;
if ( n < 25 )
return dest;
*zpl_cast( u32* )( s + 12 ) = c32;
*zpl_cast( u32* )( s + 16 ) = c32;
*zpl_cast( u32* )( s + 20 ) = c32;
*zpl_cast( u32* )( s + 24 ) = c32;
*zpl_cast( u32* )( s + n - 28 ) = c32;
*zpl_cast( u32* )( s + n - 24 ) = c32;
*zpl_cast( u32* )( s + n - 20 ) = c32;
*zpl_cast( u32* )( s + n - 16 ) = c32;
k = 24 + ( zpl_cast( uptr ) s & 4 );
s += k;
n -= k;
{
u64 c64 = ( zpl_cast( u64 ) c32 << 32 ) | c32;
while ( n > 31 )
{
*zpl_cast( u64* )( s + 0 ) = c64;
*zpl_cast( u64* )( s + 8 ) = c64;
*zpl_cast( u64* )( s + 16 ) = c64;
*zpl_cast( u64* )( s + 24 ) = c64;
n -= 32;
s += 32;
}
}
return dest;
}
ZPL_IMPL_INLINE void* alloc_align( AllocatorInfo a, sw size, sw alignment )
{
@ -338,14 +584,6 @@ namespace gen
}
}
// ZPL_IMPL_INLINE AllocatorInfo heap( void )
// {
// AllocatorInfo a;
// a.Proc = heap_allocator_proc;
// a.Data = nullptr;
// return a;
// }
struct Arena
{
static
@ -466,9 +704,234 @@ namespace gen
return { allocator_proc, this };
}
};
#pragma endregion Memory
#pragma region String Ops
ZPL_DEF_INLINE const char* char_first_occurence( const char* str, char c );
ZPL_DEF_INLINE b32 char_is_alpha( char c );
ZPL_DEF_INLINE b32 char_is_alphanumeric( char c );
ZPL_DEF_INLINE b32 char_is_digit( char c );
ZPL_DEF_INLINE b32 char_is_hex_digit( char c );
ZPL_DEF_INLINE b32 char_is_space( char c );
ZPL_DEF_INLINE char char_to_lower( char c );
ZPL_DEF_INLINE char char_to_upper( char c );
ZPL_DEF_INLINE s32 digit_to_int( char c );
ZPL_DEF_INLINE s32 hex_digit_to_int( char c );
ZPL_DEF_INLINE s32 str_compare( const char* s1, const char* s2 );
ZPL_DEF_INLINE s32 str_compare( const char* s1, const char* s2, sw len );
ZPL_DEF_INLINE char* str_copy( char* dest, const char* source, sw len );
ZPL_DEF_INLINE sw str_copy_nulpad( char* dest, const char* source, sw len );
ZPL_DEF_INLINE sw str_len( const char* str );
ZPL_DEF_INLINE sw str_len( const char* str, sw max_len );
ZPL_DEF_INLINE char* str_reverse( char* str ); // NOTE: ASCII only
// NOTE: ASCII only
ZPL_DEF_INLINE void str_to_lower( char* str );
ZPL_DEF_INLINE void str_to_upper( char* str );
s64 str_to_i64( const char* str, char** end_ptr, s32 base ); // TODO : Support more than just decimal and hexadecimal
void i64_to_str( s64 value, char* string, s32 base );
void u64_to_str( u64 value, char* string, s32 base );
ZPL_IMPL_INLINE const char* char_first_occurence( const char* s, char c )
{
char ch = c;
for ( ; *s != ch; s++ )
{
if ( *s == '\0' )
return NULL;
}
return s;
}
ZPL_IMPL_INLINE b32 char_is_alpha( char c )
{
if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) )
return true;
return false;
}
ZPL_IMPL_INLINE b32 char_is_alphanumeric( char c )
{
return char_is_alpha( c ) || char_is_digit( c );
}
ZPL_IMPL_INLINE b32 char_is_digit( char c )
{
if ( c >= '0' && c <= '9' )
return true;
return false;
}
ZPL_IMPL_INLINE b32 char_is_hex_digit( char c )
{
if ( char_is_digit( c ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) )
return true;
return false;
}
ZPL_IMPL_INLINE b32 char_is_space( char c )
{
if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' )
return true;
return false;
}
ZPL_IMPL_INLINE char char_to_lower( char c )
{
if ( c >= 'A' && c <= 'Z' )
return 'a' + ( c - 'A' );
return c;
}
ZPL_IMPL_INLINE char char_to_upper( char c )
{
if ( c >= 'a' && c <= 'z' )
return 'A' + ( c - 'a' );
return c;
}
ZPL_IMPL_INLINE s32 digit_to_int( char c )
{
return char_is_digit( c ) ? c - '0' : c - 'W';
}
ZPL_IMPL_INLINE s32 hex_digit_to_int( char c )
{
if ( char_is_digit( c ) )
return digit_to_int( c );
else if ( is_between( c, 'a', 'f' ) )
return c - 'a' + 10;
else if ( is_between( c, 'A', 'F' ) )
return c - 'A' + 10;
return -1;
}
ZPL_IMPL_INLINE s32 str_compare( const char* s1, const char* s2 )
{
while ( *s1 && ( *s1 == *s2 ) )
{
s1++, s2++;
}
return *( u8* )s1 - *( u8* )s2;
}
ZPL_IMPL_INLINE s32 str_compare( const char* s1, const char* s2, sw len )
{
for ( ; len > 0; s1++, s2++, len-- )
{
if ( *s1 != *s2 )
return ( ( s1 < s2 ) ? -1 : +1 );
else if ( *s1 == '\0' )
return 0;
}
return 0;
}
ZPL_IMPL_INLINE char* str_copy( char* dest, const char* source, sw len )
{
ZPL_ASSERT_NOT_NULL( dest );
if ( source )
{
char* str = dest;
while ( len > 0 && *source )
{
*str++ = *source++;
len--;
}
while ( len > 0 )
{
*str++ = '\0';
len--;
}
}
return dest;
}
ZPL_IMPL_INLINE sw str_copy_nulpad( char* dest, const char* source, sw len )
{
sw result = 0;
ZPL_ASSERT_NOT_NULL( dest );
if ( source )
{
const char* source_start = source;
char* str = dest;
while ( len > 0 && *source )
{
*str++ = *source++;
len--;
}
while ( len > 0 )
{
*str++ = '\0';
len--;
}
result = source - source_start;
}
return result;
}
ZPL_IMPL_INLINE sw str_len( const char* str )
{
if ( str == NULL )
{
return 0;
}
const char* p = str;
while ( *str )
str++;
return str - p;
}
ZPL_IMPL_INLINE sw str_len( const char* str, sw max_len )
{
const char* end = zpl_cast( const char* ) mem_find( str, 0, max_len );
if ( end )
return end - str;
return max_len;
}
ZPL_IMPL_INLINE char* str_reverse( char* str )
{
sw len = str_len( str );
char* a = str + 0;
char* b = str + len - 1;
len /= 2;
while ( len-- )
{
swap( char, *a, *b );
a++, b--;
}
return str;
}
ZPL_IMPL_INLINE void str_to_lower( char* str )
{
if ( ! str )
return;
while ( *str )
{
*str = char_to_lower( *str );
str++;
}
}
ZPL_IMPL_INLINE void str_to_upper( char* str )
{
if ( ! str )
return;
while ( *str )
{
*str = char_to_upper( *str );
str++;
}
}
#pragma endregion String Ops
#pragma region Containers
#pragma push_macro("template")
#undef template
@ -551,7 +1014,6 @@ namespace gen
{
Data[ idx ] = value;
}
// mem_set( Data + begin, value, end - begin)
return true;
}
@ -618,6 +1080,8 @@ namespace gen
{
if ( ! grow( num ) )
return false;
header = get_header();
}
header->Num = num;
@ -635,7 +1099,7 @@ namespace gen
header.Num = new_capacity;
sw size = sizeof( Header ) + sizeof( Type ) * new_capacity;
Header* new_header = reinterpret_cast< Header* >( alloc( header.Allocator, size ) );
Header* new_header = rcast( Header*, alloc( header.Allocator, size ) );
if ( new_header == nullptr )
return false;
@ -703,6 +1167,19 @@ namespace gen
return result;
}
static
HashTable init_reserve( AllocatorInfo allocator, sw num )
{
HashTable<Type> result = { { nullptr }, { nullptr } };
result.Hashes = Array<sw>::init_reserve( allocator, num );
result.Hashes.get_header()->Num = num;
result.Entries = Array<Entry>::init_reserve( allocator, num );
return result;
}
void clear( void )
{
for ( sw idx = 0; idx < Hashes.num(); idx++ )
@ -764,10 +1241,7 @@ namespace gen
sw idx;
sw last_added_index;
HashTable<Type> new_ht = init( Hashes.get_header()->Allocator );
new_ht.Hashes.resize( new_num );
new_ht.Entries.reserve( new_ht.Hashes.num() );
HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num );
Array<sw>::Header* hash_header = new_ht.Hashes.get_header();
@ -798,8 +1272,6 @@ namespace gen
}
destroy();
// Hashes = new_ht.Hashes;
// Entries = new_ht.Entries;
*this = new_ht;
}
@ -926,6 +1398,12 @@ namespace gen
#pragma pop_macro("template")
#pragma endregion Containers
#pragma region Hashing
u32 crc32( void const* data, sw len );
#pragma endregion Hashing
#pragma region String
// Constant string with length.
struct StrC
@ -933,18 +1411,20 @@ namespace gen
sw Len;
char const* Ptr;
static constexpr
StrC from( char const* str )
{
return { str_len( str ), str };
}
operator char const* () const
{
return Ptr;
}
};
#define txt_StrC( text ) \
(StrC){ sizeof( text ) - 1, text }
StrC to_StrC( char const* str )
{
return { str_len( str ), str };
}
// Dynamic String
// This is directly based off the ZPL string api.
// They used a header pattern
@ -1023,29 +1503,10 @@ namespace gen
}
static
String fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... )
{
va_list va;
va_start( va, fmt );
str_fmt_va( buf, buf_size, fmt, va );
va_end( va );
return make( allocator, buf );
}
String fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... );
static
String fmt_buf( AllocatorInfo allocator, char const* fmt, ... )
{
local_persist thread_local
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
str_fmt_va( buf, ZPL_PRINTF_MAXLEN, fmt, va );
va_end( va );
return make( allocator, buf );
}
String fmt_buf( AllocatorInfo allocator, char const* fmt, ... );
static
String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue )
@ -1151,18 +1612,7 @@ namespace gen
return append( other.Data, other.length() );
}
bool append_fmt( char const* fmt, ... )
{
sw res;
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1;
va_end( va );
return append( buf, res );
}
bool append_fmt( char const* fmt, ... );
sw avail_space() const
{
@ -1424,6 +1874,22 @@ namespace gen
DirEntry* Dir;
};
enum FileStandardType
{
EFileStandard_INPUT,
EFileStandard_OUTPUT,
EFileStandard_ERROR,
EFileStandard_COUNT,
};
/**
* Get standard file I/O.
* @param std Check zpl_file_standard_type
* @return File handle to standard I/O
*/
FileInfo* file_get_standard( FileStandardType std );
/**
* Closes the file
* @param file
@ -1533,6 +1999,7 @@ namespace gen
{
if ( ! f->Ops.read_at )
f->Ops = default_file_operations;
return f->Ops.write_at( f->FD, buffer, size, offset, bytes_written );
}
@ -1540,6 +2007,17 @@ namespace gen
#pragma endregion File Handling
#pragma region Printing
// NOTE: A locally persisting buffer is used internally
char* str_fmt_buf( char const* fmt, ... );
char* str_fmt_buf_va( char const* fmt, va_list va );
sw str_fmt_va( char* str, sw n, char const* fmt, va_list va );
sw str_fmt_out_va( char const* fmt, va_list va );
sw str_fmt_file_va( FileInfo* f, char const* fmt, va_list va );
#pragma endregion Printing
namespace Memory
{
// NOTE: This limits the size of the string that can be read from a file or generated to 10 megs.
@ -1556,7 +2034,6 @@ namespace gen
void cleanup();
}
inline
sw log_fmt(char const* fmt, ...)
{

View File

@ -1097,7 +1097,7 @@ namespace gen
}
Code::Global = make_code();
Code::Global->Name = get_cached_string( name("Global Code") );
Code::Global->Name = get_cached_string( txt_StrC("Global Code") );
Code::Global->Content = Code::Global->Name;
Code::Invalid = make_code();
@ -1139,34 +1139,34 @@ namespace gen
access_private = make_code();
access_private->Type = ECode::Access_Private;
access_private->Name = get_cached_string( StrC::from("private:") );
access_private->Name = get_cached_string( txt_StrC("private:") );
access_private.set_global();
access_protected = make_code();
access_protected->Type = ECode::Access_Protected;
access_protected->Name = get_cached_string( StrC::from("protected:") );
access_protected->Name = get_cached_string( txt_StrC("protected:") );
access_protected.set_global();
access_public = make_code();
access_public->Type = ECode::Access_Public;
access_public->Name = get_cached_string( StrC::from("public:") );
access_public->Name = get_cached_string( txt_StrC("public:") );
access_public.set_global();
module_global_fragment = make_code();
module_global_fragment->Type = ECode::Untyped;
module_global_fragment->Name = get_cached_string( StrC::from("module;") );
module_global_fragment->Name = get_cached_string( txt_StrC("module;") );
module_global_fragment->Content = module_global_fragment->Name;
module_global_fragment.set_global();
module_private_fragment = make_code();
module_private_fragment->Type = ECode::Untyped;
module_private_fragment->Name = get_cached_string( StrC::from("module : private;") );
module_private_fragment->Name = get_cached_string( txt_StrC("module : private;") );
module_private_fragment->Content = module_private_fragment->Name;
module_private_fragment.set_global();
pragma_once = make_code();
pragma_once->Type = ECode::Untyped;
pragma_once->Name = get_cached_string( StrC::from("#pragma once") );
pragma_once->Name = get_cached_string( txt_StrC("#pragma once") );
pragma_once->Content = pragma_once->Name;
pragma_once.set_global();
@ -1733,13 +1733,13 @@ namespace gen
{ \
if ( Name_.Len <= 0 ) \
{ \
log_failure( "gen::" txt(Context_) ": Invalid name length provided - %d", Name_.Len ); \
log_failure( "gen::" stringize(Context_) ": Invalid name length provided - %d", Name_.Len ); \
return Code::Invalid; \
} \
\
if ( Name_.Ptr == nullptr ) \
{ \
log_failure( "gen::" txt(Context_) ": name is null" ); \
log_failure( "gen::" stringize(Context_) ": name is null" ); \
return Code::Invalid; \
} \
}
@ -1747,7 +1747,7 @@ namespace gen
# define null_check( Context_, Code_ ) \
if ( ! Code_ ) \
{ \
log_failure( "gen::" txt(Context_) ": " txt(Code_) " provided is null" ); \
log_failure( "gen::" stringize(Context_) ": " stringize(Code_) " provided is null" ); \
return Code::Invalid; \
}
@ -1755,13 +1755,13 @@ namespace gen
{ \
if ( ! Code_ ) \
{ \
log_failure( "gen::" txt(Context_) ": " txt(Code_) " provided is null" ); \
log_failure( "gen::" stringize(Context_) ": " stringize(Code_) " provided is null" ); \
return Code::Invalid; \
} \
\
if ( Code_->is_invalid() ) \
{ \
log_failure("gen::" txt(Context_) ": " txt(Code_) " provided is invalid" ); \
log_failure("gen::" stringize(Context_) ": " stringize(Code_) " provided is invalid" ); \
return Code::Invalid; \
} \
}
@ -2633,7 +2633,7 @@ namespace gen
\
if ( num <= 0 ) \
{ \
log_failure("gen::" txt(Name_) ": num cannot be zero or negative"); \
log_failure("gen::" stringize(Name_) ": num cannot be zero or negative"); \
return Code::Invalid; \
}
@ -2642,7 +2642,7 @@ namespace gen
\
if ( num <= 0 ) \
{ \
log_failure("gen::" txt(Name_) ": num cannot be zero or negative"); \
log_failure("gen::" stringize(Name_) ": num cannot be zero or negative"); \
return Code::Invalid; \
} \
\
@ -2660,7 +2660,7 @@ namespace gen
\
if ( ! entry ) \
{ \
log_failure("gen::" txt(Name_) ": Provided an null entry"); \
log_failure("gen::" stringize(Name_) ": Provided an null entry"); \
return Code::Invalid; \
} \
\
@ -2674,7 +2674,7 @@ namespace gen
\
if ( ! entry ) \
{ \
log_failure("gen::" txt(Name_) ": Provided an null entry"); \
log_failure("gen::" stringize(Name_) ": Provided an null entry"); \
return Code::Invalid; \
} \
\
@ -2682,7 +2682,7 @@ namespace gen
{
# define def_body_code_validation_end( Name_ ) \
log_failure("gen::" txt(Name_) ": Entry type is not allowed: %s", entry->debug_str() ); \
log_failure("gen::" stringize(Name_) ": Entry type is not allowed: %s", entry->debug_str() ); \
return Code::Invalid; \
\
default: \
@ -3451,7 +3451,7 @@ namespace gen
local_persist thread_local
Array<Token> Tokens = { nullptr };
s32 left = content.Len -1;
s32 left = content.Len;
char const* scanner = content.Ptr;
char const* word = scanner;
@ -3898,16 +3898,16 @@ namespace gen
}
#pragma region Helper Macros
# define check_parse_args( func, def ) \
if ( def.Len <= 0 ) \
{ \
log_failure( "gen::" txt(func) ": length must greater than 0" ); \
return Code::Invalid; \
} \
if ( def.Ptr == nullptr ) \
{ \
log_failure( "gen::" txt(func) ": def was null" ); \
return Code::Invalid; \
# define check_parse_args( func, def ) \
if ( def.Len <= 0 ) \
{ \
log_failure( "gen::" stringize(func) ": length must greater than 0" ); \
return Code::Invalid; \
} \
if ( def.Ptr == nullptr ) \
{ \
log_failure( "gen::" stringize(func) ": def was null" ); \
return Code::Invalid; \
}
# define nexttok toks.next()
@ -3950,13 +3950,13 @@ namespace gen
if ( left == 0 )
{
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) );
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", stringize(parse_typedef) );
return Code::Invalid;
}
if ( currtok.Type == TokType::BraceSquare_Close )
{
log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) );
log_failure( "%s: Error, empty array expression in typedef definition", stringize(parse_typedef) );
return Code::Invalid;
}
@ -3973,13 +3973,13 @@ namespace gen
if ( left == 0 )
{
log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) );
log_failure( "%s: Error, unexpected end of type definition, expected ]", stringize(parse_typedef) );
return Code::Invalid;
}
if ( currtok.Type != TokType::BraceSquare_Close )
{
log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) );
log_failure( "%s: Error, expected ] in type definition, not %s", stringize(parse_typedef), str_tok_type( currtok.Type ) );
return Code::Invalid;
}
@ -4179,12 +4179,12 @@ namespace gen
{
using namespace Parser;
Code params = parse_params( toks, txt(parse_function) );
Code params = parse_params( toks, stringize(parse_function) );
Code body = { nullptr };
if ( check( TokType::BraceCurly_Open ) )
{
body = parse_function_body( toks, txt(parse_function) );
body = parse_function_body( toks, stringize(parse_function) );
if ( body == Code::Invalid )
return Code::Invalid;
}
@ -4438,13 +4438,13 @@ namespace gen
eat( TokType::Operator );
// Parse Params
Code params = parse_params( toks, txt(parse_operator) );
Code params = parse_params( toks, stringize(parse_operator) );
// Parse Body
Code body = { nullptr };
if ( check( TokType::BraceCurly_Open ) )
{
body = parse_function_body( toks, txt(parse_function) );
body = parse_function_body( toks, stringize(parse_function) );
if ( body == Code::Invalid )
return Code::Invalid;
}
@ -4471,7 +4471,7 @@ namespace gen
{
using namespace Parser;
Code array_expr = parse_array_decl( toks, txt(parse_variable) );
Code array_expr = parse_array_decl( toks, stringize(parse_variable) );
Code expr = Code::Invalid;
@ -4561,7 +4561,7 @@ namespace gen
Code result = Code::Invalid;
Code type = parse_type( toks, txt(parse_variable) );
Code type = parse_type( toks, stringize(parse_variable) );
if ( type == Code::Invalid )
return Code::Invalid;
@ -4569,7 +4569,7 @@ namespace gen
if ( check( TokType::Operator) )
{
// Dealing with an operator overload
result = parse_operator_after_ret_type( ModuleFlag::None, attributes, specifiers, type, toks, txt(parse_template) );
result = parse_operator_after_ret_type( ModuleFlag::None, attributes, specifiers, type, toks, stringize(parse_template) );
}
else
{
@ -4580,7 +4580,7 @@ namespace gen
{
// Dealing with a function
result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, txt(parse_template) );
result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, stringize(parse_template) );
}
else
{
@ -4591,7 +4591,7 @@ namespace gen
}
// Dealing with a variable
result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, txt(parse_template) );
result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, stringize(parse_template) );
}
}
@ -4746,7 +4746,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_class_struct_body: invalid specifier " txt(spec) " for variable" );
log_failure( "gen::parse_class_struct_body: invalid specifier " "%s" " for variable", ESpecifier::to_str(spec) );
return Code::Invalid;
}
@ -4948,7 +4948,7 @@ namespace gen
case TokType::Decl_Extern_Linkage:
if ( which == Extern_Linkage_Body )
log_failure( "gen::parse_extern_link_body: nested extern linkage" );
log_failure( "gen::parse_global_nspace: nested extern linkage" );
member = parse_extern_link_body( toks, context );
break;
@ -4979,7 +4979,7 @@ namespace gen
case TokType::Module_Export:
if ( which == Export_Body )
log_failure( "gen::parse_extern_link_body: nested export declaration" );
log_failure( "gen::parse_global_nspace: nested export declaration" );
member = parse_export_body( toks, context );
break;
@ -5054,7 +5054,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_class_struct_body: invalid specifier " txt(spec) " for variable" );
log_failure( "gen::parse_global_nspace: invalid specifier " "%s" " for variable", ESpecifier::to_str(spec) );
return Code::Invalid;
}
@ -5110,7 +5110,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_class_struct( TokType::Decl_Class, toks, txt(parse_class) );
return parse_class_struct( TokType::Decl_Class, toks, stringize(parse_class) );
}
internal
@ -5155,7 +5155,7 @@ namespace gen
{
eat( TokType::Assign_Classifer );
type = parse_type( toks, txt(parse_enum) );
type = parse_type( toks, stringize(parse_enum) );
if ( type == Code::Invalid )
return Code::Invalid;
}
@ -5229,7 +5229,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_enum( toks, txt(parse_enum) );
return parse_enum( toks, stringize(parse_enum) );
}
internal inline
@ -5247,7 +5247,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_export_body( toks, txt(parse_export_body) );
return parse_export_body( toks, stringize(parse_export_body) );
}
internal inline
@ -5295,7 +5295,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_extern_link( toks, txt(parse_extern_link) );
return parse_extern_link( toks, stringize(parse_extern_link) );
}
internal
@ -5309,7 +5309,7 @@ namespace gen
Code function = { nullptr };
// Type declaration or return type
Code type = parse_type( toks, txt(parse_friend) );
Code type = parse_type( toks, stringize(parse_friend) );
if ( type == Code::Invalid )
return Code::Invalid;
@ -5317,10 +5317,10 @@ namespace gen
if ( currtok.Type == TokType::Identifier )
{
// Name
Token name = parse_identifier( toks, txt(parse_friend) );
Token name = parse_identifier( toks, stringize(parse_friend) );
// Parameter list
Code params = parse_params( toks, txt(parse_friend) );
Code params = parse_params( toks, stringize(parse_friend) );
function = make_code();
function->Type = Function_Fwd;
@ -5355,7 +5355,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_friend( toks, txt(parse_friend) );
return parse_friend( toks, stringize(parse_friend) );
}
internal
@ -5388,7 +5388,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_variable: invalid specifier " txt(spec) " for variable" );
log_failure( "gen::parse_functon: invalid specifier " "%s" " for functon", ESpecifier::to_str(spec) );
return Code::Invalid;
}
@ -5402,11 +5402,11 @@ namespace gen
specifiers = def_specifiers( num_specifiers, specs_found );
}
Code ret_type = parse_type( toks, txt(parse_function) );
Code ret_type = parse_type( toks, stringize(parse_function) );
if ( ret_type == Code::Invalid )
return Code::Invalid;
Token name = parse_identifier( toks, txt(parse_function) );
Token name = parse_identifier( toks, stringize(parse_function) );
if ( ! name )
return Code::Invalid;
@ -5425,7 +5425,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_functon( toks, txt(parse_function) );
return parse_functon( toks, stringize(parse_function) );
}
Code parse_global_body( StrC def )
@ -5437,7 +5437,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_global_nspace( ECode::Global_Body, toks, txt(parse_global_body) );
return parse_global_nspace( ECode::Global_Body, toks, stringize(parse_global_body) );
}
internal
@ -5446,9 +5446,9 @@ namespace gen
using namespace Parser;
eat( TokType::Decl_Namespace );
Token name = parse_identifier( toks, txt(parse_namespace) );
Token name = parse_identifier( toks, stringize(parse_namespace) );
Code body = parse_global_nspace( ECode::Namespace_Body, toks, txt(parse_namespace) );
Code body = parse_global_nspace( ECode::Namespace_Body, toks, stringize(parse_namespace) );
if ( body == Code::Invalid )
return Code::Invalid;
@ -5471,7 +5471,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_namespace( toks, txt(parse_namespace) );
return parse_namespace( toks, stringize(parse_namespace) );
}
internal
@ -5500,7 +5500,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_variable: invalid specifier " txt(spec) " for variable" );
log_failure( "gen::parse_operator: invalid specifier " "%s" " for operator", ESpecifier::to_str(spec) );
return Code::Invalid;
}
@ -5515,7 +5515,7 @@ namespace gen
}
// Parse Return Type
Code ret_type = parse_type( toks, txt(parse_operator) );
Code ret_type = parse_type( toks, stringize(parse_operator) );
Code result = parse_operator_after_ret_type( ModuleFlag::None, attributes, specifiers, ret_type, toks, context );
return result;
@ -5530,7 +5530,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_operator( toks, txt(parse_operator) );
return parse_operator( toks, stringize(parse_operator) );
}
Code parse_operator_cast( Parser::TokArray& toks, char const* context )
@ -5539,7 +5539,7 @@ namespace gen
eat( TokType::Decl_Operator );
Code type = parse_type( toks, txt(parse_operator_cast) );
Code type = parse_type( toks, stringize(parse_operator_cast) );
eat( TokType::Capture_Start );
eat( TokType::Capture_End );
@ -5597,13 +5597,13 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_operator_cast( toks, txt(parse_operator_cast) );
return parse_operator_cast( toks, stringize(parse_operator_cast) );
}
internal inline
Code parse_struct( Parser::TokArray& toks, char const* context )
{
return parse_class_struct( Parser::TokType::Decl_Struct, toks, txt(parse_struct) );
return parse_class_struct( Parser::TokType::Decl_Struct, toks, stringize(parse_struct) );
}
Code parse_struct( StrC def )
@ -5615,7 +5615,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_class_struct( TokType::Decl_Struct, toks, txt(parse_struct) );
return parse_class_struct( TokType::Decl_Struct, toks, stringize(parse_struct) );
}
internal
@ -5629,7 +5629,7 @@ namespace gen
eat( TokType::Decl_Template );
Code params = parse_params( toks, txt(parse_template), UseTemplateCapture );
Code params = parse_params( toks, stringize(parse_template), UseTemplateCapture );
if ( params == Code::Invalid )
return Code::Invalid;
@ -5639,19 +5639,19 @@ namespace gen
{
if ( check( TokType::Decl_Class ) )
{
definition = parse_class( toks, txt(parse_template) );
definition = parse_class( toks, stringize(parse_template) );
break;
}
if ( check( TokType::Decl_Struct ) )
{
definition = parse_enum( toks, txt(parse_template) );
definition = parse_enum( toks, stringize(parse_template) );
break;
}
if ( check( TokType::Decl_Using ))
{
definition = parse_using( toks, txt(parse_template) );
definition = parse_using( toks, stringize(parse_template) );
break;
}
@ -5693,7 +5693,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_template: invalid specifier " txt(spec) " for variable or function" );
log_failure( "gen::parse_template: invalid specifier %s for variable or function", ESpecifier::to_str( spec ) );
return Code::Invalid;
}
@ -5711,7 +5711,7 @@ namespace gen
specifiers = def_specifiers( num_specifiers, specs_found );
}
definition = parse_operator_function_or_variable( expects_function, attributes, specifiers, toks, txt(parse_template) );
definition = parse_operator_function_or_variable( expects_function, attributes, specifiers, toks, stringize(parse_template) );
break;
}
@ -5734,7 +5734,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_template( toks, txt(parse_template) );
return parse_template( toks, stringize(parse_template) );
}
internal
@ -5915,7 +5915,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
Code result = parse_type( toks, txt(parse_type) );
Code result = parse_type( toks, stringize(parse_type) );
return result;
}
@ -5931,7 +5931,7 @@ namespace gen
eat( TokType::Decl_Typedef );
type = parse_type( toks, txt(parse_typedef) );
type = parse_type( toks, stringize(parse_typedef) );
if ( ! check( TokType::Identifier ) )
{
@ -5942,7 +5942,7 @@ namespace gen
name = currtok;
eat( TokType::Identifier );
array_expr = parse_array_decl( toks, txt(parse_typedef) );
array_expr = parse_array_decl( toks, stringize(parse_typedef) );
eat( TokType::Statement_End );
@ -5970,7 +5970,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_typedef( toks, txt(parse_typedef) );
return parse_typedef( toks, stringize(parse_typedef) );
}
internal
@ -6002,7 +6002,7 @@ namespace gen
while ( ! check( TokType::BraceCurly_Close ) )
{
Code entry = parse_variable( toks, txt(parse_union) );
Code entry = parse_variable( toks, stringize(parse_union) );
if ( entry )
body->add_entry( entry );
@ -6036,7 +6036,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_union( toks, txt(parse_union) );
return parse_union( toks, stringize(parse_union) );
}
internal
@ -6072,10 +6072,10 @@ namespace gen
eat( TokType::Operator );
type = parse_type( toks, txt(parse_typedef) );
type = parse_type( toks, stringize(parse_typedef) );
}
array_expr = parse_array_decl( toks, txt(parse_typedef) );
array_expr = parse_array_decl( toks, stringize(parse_typedef) );
eat( TokType::Statement_End );
@ -6104,7 +6104,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_using( toks, txt(parse_using) );
return parse_using( toks, stringize(parse_using) );
}
internal
@ -6144,7 +6144,7 @@ namespace gen
break;
default:
log_failure( "gen::parse_variable: invalid specifier " txt(spec) " for variable" );
log_failure( "gen::parse_variable: invalid specifier %s for variable", ESpecifier::to_str( spec ) );
return Code::Invalid;
}
@ -6162,7 +6162,7 @@ namespace gen
specifiers = def_specifiers( num_specifiers, specs_found );
}
Code type = parse_type( toks, txt(parse_variable) );
Code type = parse_type( toks, stringize(parse_variable) );
if ( type == Code::Invalid )
return Code::Invalid;
@ -6170,7 +6170,7 @@ namespace gen
name = currtok;
eat( TokType::Identifier );
Code result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, txt(parse_variable) );
Code result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, stringize(parse_variable) );
return result;
}
@ -6184,7 +6184,7 @@ namespace gen
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_variable( toks, txt(parse_variable) );
return parse_variable( toks, stringize(parse_variable) );
}
// Undef helper macros
@ -6197,42 +6197,31 @@ namespace gen
#pragma endregion Parsing Constructors
#pragma region Untyped Constructors
struct TokEntry
{
char const* Str;
sw Length;
};
sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va )
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va )
{
char const* buf_begin = buf;
sw remaining = buf_size;
HashTable<TokEntry> tok_map;
HashTable<StrC> tok_map;
{
// TODO : Switch this to use an arena that makes use of the stack (cap the size of the token table to around 4096 bytes)
tok_map = HashTable<TokEntry>::init( Memory::GlobalAllocator );
tok_map = HashTable<StrC>::init( Memory::GlobalAllocator );
s32 left = num_tokens;
s32 left = num_tokens - 1;
while ( left-- )
{
char const* token = va_arg( va, char const* );
char const* value = va_arg( va, char const* );
StrC value = va_arg( va, StrC );
TokEntry entry
{
value,
str_len(value, (sw)128)
};
u32 key = crc32( token, str_len(token) );
u32 key = crc32( token, str_len(token, 32) );
tok_map.set( key, entry );
tok_map.set( key, value );
}
}
char current = *fmt;
char const* fmt = va_arg( va, char const* );
char current = *fmt;
while ( current )
{
@ -6263,12 +6252,12 @@ namespace gen
char const* token = fmt + 1;
u32 key = crc32( token, tok_len );
TokEntry* value = tok_map.get( key );
StrC* value = tok_map.get( key );
if ( value )
{
sw left = value->Length;
char const* str = value->Str;
sw left = value->Len;
char const* str = value->Ptr;
while ( left-- )
{
@ -6295,7 +6284,7 @@ namespace gen
tok_map.clear();
sw result = buf_size - remaining + 1;
sw result = buf_size - remaining;
return result;
}
@ -6330,21 +6319,21 @@ namespace gen
return result;
}
Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... )
Code untyped_token_fmt( s32 num_tokens, ... )
{
local_persist thread_local
char buf[ZPL_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
sw length = token_fmt_va(buf, ZPL_PRINTF_MAXLEN, fmt, num_tokens, va);
va_start(va, num_tokens);
sw length = token_fmt_va(buf, ZPL_PRINTF_MAXLEN, num_tokens, va);
va_end(va);
Code
result = make_code();
result->Name = get_cached_string( { str_len(fmt, MaxNameLength), fmt } );
result->Name = get_cached_string( { length, buf } );
result->Type = ECode::Untyped;
result->Content = get_cached_string( { length, buf } );
result->Content = result->Name;
return result;
}

View File

@ -97,7 +97,7 @@ namespace gen
{
static
StrC lookup[Num_Types] = {
# define Entry( Type ) { txt_to_StrC( Type ) },
# define Entry( Type ) { sizeof(stringize(Type)), stringize(Type) },
Define_Types
# undef Entry
};
@ -189,7 +189,7 @@ namespace gen
{
local_persist
char const* lookup[ Num_Ops ] = {
# define Entry( Type_, Token_ ) txt(Token_),
# define Entry( Type_, Token_ ) stringize(Token_),
Define_Operators
# undef Entry
","
@ -252,7 +252,7 @@ namespace gen
# define internal internal
# define local_persist local_persist
# define Entry( Spec_, Code_ ) { txt_to_StrC(Code_) },
# define Entry( Spec_, Code_ ) { sizeof(stringize(Code_)), stringize(Code_) },
Define_Specifiers
# undef Entry
@ -352,9 +352,9 @@ namespace gen
# define GEN_API_Import_Code __declspec(dllimport)
# define GEN_Attribute_Keyword __declspec
constexpr char const* API_Export = txt( GEN_API_Export_Code );
constexpr char const* API_Import = txt( GEN_API_Import_Code );
constexpr char const* Keyword = txt( GEN_Attribute_Keyword);
constexpr char const* API_Export = stringize( GEN_API_Export_Code );
constexpr char const* API_Import = stringize( GEN_API_Import_Code );
constexpr char const* Keyword = stringize( GEN_Attribute_Keyword);
#elif ZPL_HAS_ATTRIBUTE( visibility ) || ZPL_GCC_VERSION_CHECK( 3, 3, 0 ) || ZPL_INTEL_VERSION_CHECK( 13, 0, 0 )
# define GEN_API_Export_Code __attribute__ ((visibility ("default")))
@ -501,7 +501,7 @@ namespace gen
char const* debug_str()
{
char const* fmt = txt(
char const* fmt = stringize(
\nCode Debug:
\nType : %s
\nParent : %s
@ -773,26 +773,26 @@ namespace gen
, ModuleFlag mflags = ModuleFlag::None );
Code def_class_body ( s32 num, ... );
Code def_class_body ( s32 num, Code* codes );
Code def_enum_body ( s32 num, ... );
Code def_enum_body ( s32 num, Code* codes );
Code def_export_body ( s32 num, ... );
Code def_export_body ( s32 num, Code* codes);
Code def_extern_link_body( s32 num, ... );
Code def_extern_link_body( s32 num, Code* codes );
Code def_function_body ( s32 num, ... );
Code def_function_body ( s32 num, Code* codes );
Code def_global_body ( s32 num, ... );
Code def_global_body ( s32 num, Code* codes );
Code def_namespace_body ( s32 num, ... );
Code def_namespace_body ( s32 num, Code* codes );
Code def_params ( s32 num, ... );
Code def_params ( s32 num, Code* params );
Code def_specifiers ( s32 num , ... );
Code def_specifiers ( s32 num, SpecifierT* specs );
Code def_specifiers ( s32 num, ... );
Code def_struct_body ( s32 num, ... );
Code def_struct_body ( s32 num, Code* codes );
Code def_union_body ( s32 num, ... );
Code def_class_body ( s32 num, Code* codes );
Code def_enum_body ( s32 num, Code* codes );
Code def_export_body ( s32 num, Code* codes);
Code def_extern_link_body( s32 num, Code* codes );
Code def_function_body ( s32 num, Code* codes );
Code def_global_body ( s32 num, Code* codes );
Code def_namespace_body ( s32 num, Code* codes );
Code def_params ( s32 num, Code* params );
Code def_specifiers ( s32 num, SpecifierT* specs );
Code def_struct_body ( s32 num, Code* codes );
Code def_union_body ( s32 num, Code* codes );
# pragma endregion Upfront
@ -819,18 +819,20 @@ namespace gen
# pragma endregion Parsing
# pragma region Untyped text
sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va );
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
//! Do not use directly. Use the token_fmt macro instead.
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
inline
StrC token_fmt( char const* fmt, sw num_tokens, ... )
StrC _token_fmt( sw num, ... )
{
local_persist thread_local
char buf[ZPL_PRINTF_MAXLEN] = { 0 };
mem_set( buf, 0, ZPL_PRINTF_MAXLEN );
va_list va;
va_start(va, fmt);
sw result = token_fmt_va(buf, ZPL_PRINTF_MAXLEN, fmt, num_tokens, va);
va_start(va, num );
sw result = token_fmt_va(buf, ZPL_PRINTF_MAXLEN, num, va);
va_end(va);
return { result, buf };
@ -969,10 +971,15 @@ namespace gen
// Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL.
# define name( Id_ ) { txt_to_StrC( Id_ ) }
# define name( Id_ ) { sizeof(stringize( Id_ )) - 1, stringize(Id_) }
// Same as name just used to indicate intention of literal for code instead of names.
# define code( ... ) { txt_to_StrC( __VA_ARGS__ ) }
# define code( ... ) { sizeof(stringize(__VA_ARGS__)) - 1, stringize( __VA_ARGS__ ) }
# define args( ... ) macro_num_args( __VA_ARGS__ ), __VA_ARGS__
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
# define token_fmt( ... ) _token_fmt( (macro_num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
#pragma endregion Macros
#pragma region Constants