From: hgn Date: Mon, 22 Sep 2025 20:24:22 +0000 (+0000) Subject: jjbbb X-Git-Url: https://skaterift.com/git/?a=commitdiff_plain;h=20e42f2dad1c7234774fd12555afddb77490f3d1;p=vg.git jjbbb --- diff --git a/bootstrap.sh b/bootstrap.sh index 1c166c6..1756bfe 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,5 +1,7 @@ -mkdir -p bin/vg.metacompiler-linux-x86_64-zig-cc/ -zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unused-function -O0 -ggdb -std=c99 \ +mkdir -p bin/vg.metacompiler-linux-x86_64-zig-cc/ && +taskset -c 0-1 zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unused-function -O0 -ggdb \ + -std=c99 -D_DEFAULT_SOURCE \ + -include "common_api.h" \ source/foundation/options.c \ source/foundation/logging.c \ source/foundation/allocator_heap.c \ @@ -15,18 +17,6 @@ zig cc -I. -I./include/ -fsanitize=address -lasan -Wall -Wno-unused-function -O0 source/foundation/buffer_operations.c \ \ source/tools/metacompiler.c \ - -o bin/vg.metacompiler-linux-x86_64-zig-cc/vg.metacompiler - + -o bin/vg.metacompiler-linux-x86_64-zig-cc/vg.metacompiler && \ +echo I now need to install a symlink into /usr/bin. sudo please. && \ sudo ln -sf $(realpath ./bin/vg.metacompiler-linux-x86_64-zig-cc/vg.metacompiler) /usr/bin/vgc - -# Foundatin Engine -# Y source/foundation/options.c source/foundation/options.c -# Y source/foundation/logging.c source/foundation/logging__ENGINE.c -# Y source/foundation/allocator_heap.c source/foundation/allocator_heap.c -# Y source/foundation/allocator_stack.c source/foundation/allocator_stack.c -# Y source/foundation/allocator_pool.c source/foundation/allocator_pool.c -# source/foundation/allocator_queue.c source/foundation/allocator_queue.c -# Y source/foundation/stream.c source/foundation/stream.c -# Y source/foundation/string.c source/foundation/string.c -# source/foundation/keyvalues.c source/foundation/keyvalues.c -# Y source/foundation/exit.c source/foundation/exit__ENGINE.c diff --git a/build/test.kv b/build/test.kv new file mode 100644 index 0000000..7e9178a --- /dev/null +++ b/build/test.kv @@ -0,0 +1 @@ +add hello.c diff --git a/foundation.kv b/foundation.kv new file mode 100644 index 0000000..b42dd77 --- /dev/null +++ b/foundation.kv @@ -0,0 +1,14 @@ +include include/ +add source/foundation/options.c +add source/foundation/logging.c +add source/foundation/allocator_heap.c +add source/foundation/allocator_stack.c +add source/foundation/allocator_pool.c +add source/foundation/allocator_queue.c +add source/foundation/allocator_stretchy.c +add source/foundation/stream.c +add source/foundation/string.c +add source/foundation/keyvalues.c +add source/foundation/exit.c +add source/foundation/io.c +add source/foundation/buffer_operations.c diff --git a/include/common_api.h b/include/common_api.h index 5ab73c8..79da403 100644 --- a/include/common_api.h +++ b/include/common_api.h @@ -50,7 +50,7 @@ bool _option_flag( c8 c, const c8 *desc ); const c8 *_option_argument( char c, const c8 *desc ); bool _option_long( c8 *name, const c8 *desc ); const c8 *_option_long_argument( char *name, const c8 *desc ); -const c8 *_option( u32 index ); +const c8 *_option(void); /* Heap allocation * ------------------------------------------------------------------------------------------------------------------ */ @@ -65,7 +65,7 @@ u32 buffer_djb2( const void *buffer, i32 max_length ); bool compare_buffers( const void *buffer_a, i32 a_max, const void *buffer_b, i32 b_max ); i32 buffer_first_index( const void *buffer, u8 match, i32 max_length ); i32 buffer_last_index( const void *buffer, u8 match, i32 max_length ); -void buffer_copy( const void *buffer_src, void *buffer_dest, i32 length ); +void buffer_copy( const void *buffer_src, u32 src_length, void *buffer_dest, u32 dest_length ); struct stretchy_allocator { @@ -84,11 +84,13 @@ struct stack_allocator { u32 capacity, offset; /* bytes */ void *data; + + void *check_pointer; }; void stack_init( struct stack_allocator *stack, void *buffer, u32 capacity, const c8 *debug_name ); void *stack_allocate( struct stack_allocator *stack, u32 size, u32 alignment, const c8 *debug_name ); void stack_clear( struct stack_allocator *stack ); -void stack_extend_last( struct stack_allocator *stack, i32 extra_bytes ); +void stack_extend_last( struct stack_allocator *stack, void *check_pointer, i32 extra_bytes ); u32 stack_offset( struct stack_allocator *stack, void *pointer ); void *stack_pointer( struct stack_allocator *stack, u32 offset ); @@ -150,12 +152,19 @@ void queue_clear( struct queue_allocator *queue ); * ------------------------------------------------------------------------------------------------------------------ */ enum stream_flag { - k_stream_overflow_error = 0x20, - k_stream_text = 0x10, /* SEMANTIC, not logical. */ - k_stream_procedural = 0x8, - k_stream_posix = 0x4, - k_stream_write = 0x2, - k_stream_read = 0x1 + /* options */ + k_stream_overflow_error = 0x1000, + k_stream_null_terminate = 0x2000, + + /* memory type */ + k_stream_buffer = 0x10, + k_stream_procedural = 0x20, + k_stream_stack = 0x40, + k_stream_posix = 0x80, + + /* modes */ + k_stream_write = 0x1, + k_stream_read = 0x2 }; struct stream { @@ -164,16 +173,20 @@ struct stream { void *posix_stream; u8 *buffer; + u32 (*procedure)( u32 flags, u32 offset, void *buffer, u32 length ); + }; - struct - { - u32 (*procedure)( u32 flags, u32 offset, void *buffer, u32 length ); - void *procedure_userdata; - }; + union + { + struct stack_allocator *stack; + void *procedure_userdata; }; }; + +void stream_open_stack( struct stream *stream, struct stack_allocator *stack, u32 flags ); void stream_open_buffer( struct stream *stream, void *buffer, u32 buffer_length, u32 flags ); bool stream_open_file( struct stream *stream, const c8 *path, u32 flags ); + void stream_close( struct stream *stream ); u32 stream_read( struct stream *stream, void *buffer, u32 length ); u32 stream_write( struct stream *stream, const void *buffer, u32 length ); @@ -183,7 +196,8 @@ bool stream_error( struct stream *stream ); /* String (Stream subset) * ------------------------------------------------------------------------------------------------------------------ */ -void string_init( struct stream *string, c8 *buffer, u32 buffer_length ); + +const c8 *string_get( struct stream *string ); void string_clip( struct stream *string, i32 length ); void string_append( struct stream *string, const c8 *substring ); void string_append_c8( struct stream *string, c8 c ); @@ -215,6 +229,7 @@ void v_string( struct stream *string, struct v_string_arg *argument_list ); #define k_$float 4 #define k_$errno 5 +#define $string( X, ... ) { string_get( X ), __VA_ARGS__ } #define $unsigned( X, ... ) { .type=k_$unsigned, ._u64=X, __VA_ARGS__ } #define $signed( X, ... ) { .type=k_$signed, ._i64=X, __VA_ARGS__ } #define $float( X, ... ) { .type=k_$float, ._f64=X, __VA_ARGS__ } @@ -242,12 +257,13 @@ enum string_parse_result string_parse_f64( struct stream *string, f64 *value ); #define $warning 0x8 #define $error 0x10 #define $fatal 0x20 +#define $shell 0x40 /* One day we will replace this shit with a good pre-processor. */ #define $TO_STRING( S ) $TO_STRING_1( S ) #define $TO_STRING_1( S ) #S #define $line __FILE__ ":" $TO_STRING(__LINE__) -#define $log( C, ... ) $v_string( _log_event( C, $line ), __VA_ARGS__ ) +#define $log( C, ... ) $v_string( _log_event( C, $line ), __VA_ARGS__, {"\n"} ) struct stream *_log_event( u32 type, const c8 *code_location ); struct stream *_get_console_stream(); @@ -262,7 +278,7 @@ struct keyvalues }; void keyvalues_init( struct keyvalues *kvs, struct stack_allocator *stack ); void keyvalues_parse_stream( struct keyvalues *kvs, u32 root_offset, struct stream *in_stream ); -void keyvalues_write_stream( struct keyvalues *kvs, struct stream *out_stream ); +void keyvalues_write_stream( struct keyvalues *kvs, struct stream *out_stream, u32 node, u32 depth ); bool keyvalues_read_file( struct keyvalues *kvs, const char *path, struct stack_allocator *stack ); bool keyvalues_write_file( struct keyvalues *kvs, const char *path ); diff --git a/metacompiler.kv b/metacompiler.kv new file mode 100644 index 0000000..af43f0b --- /dev/null +++ b/metacompiler.kv @@ -0,0 +1,3 @@ +name program +append foundation.kv +add source/tools/metacompiler.c diff --git a/source/foundation/allocator_stack.c b/source/foundation/allocator_stack.c index fd310b0..51dc42b 100644 --- a/source/foundation/allocator_stack.c +++ b/source/foundation/allocator_stack.c @@ -26,6 +26,7 @@ void *stack_allocate( struct stack_allocator *stack, u32 size, u32 alignment, co stack->offset ++; void *block = stack->data + stack->offset; stack->offset += size; + stack->check_pointer = block; return block; } @@ -44,12 +45,13 @@ void *stack_pointer( struct stack_allocator *stack, u32 offset ) return stack->data + offset; } -void stack_extend_last( struct stack_allocator *stack, i32 extra_bytes ) +void stack_extend_last( struct stack_allocator *stack, void *check_pointer, i32 extra_bytes ) { + ASSERT_CRITICAL( check_pointer == stack->check_pointer ); stack->offset += extra_bytes; } -#define TEMP_STACK_MAX 8 +#define TEMP_STACK_MAX 64 struct stack_allocator _temp_stack; u32 _temp_offsets[ TEMP_STACK_MAX ]; u32 _temp_stack_depth = 0; diff --git a/source/foundation/buffer_operations.c b/source/foundation/buffer_operations.c index b9ad005..a89ca0f 100644 --- a/source/foundation/buffer_operations.c +++ b/source/foundation/buffer_operations.c @@ -66,8 +66,22 @@ i32 buffer_last_index( const void *buffer, u8 match, i32 max_length ) return index; } -void buffer_copy( const void *buffer_src, void *buffer_dest, i32 length ) +void buffer_copy( const void *buffer_src, u32 src_length, void *buffer_dest, u32 dest_length ) { - for( i32 i=0; i #include #include diff --git a/source/foundation/keyvalues.c b/source/foundation/keyvalues.c index 68fc0f5..b7a70d3 100644 --- a/source/foundation/keyvalues.c +++ b/source/foundation/keyvalues.c @@ -53,7 +53,7 @@ static u32 keyvalues_string_append( struct keyvalues *kvs, const c8 *string ) i32 length = buffer_first_index(string,0,0)+1; char *buf = stack_allocate( kvs->stack, length, 1, "KV string (appended)" ); - buffer_copy( string, buf, length ); + buffer_copy( string, 0, buf, length ); return stack_offset( kvs->stack, buf ); } @@ -134,12 +134,17 @@ c8 *keyvalues_value( struct keyvalues *kvs, u32 kv_offset, u32 *out_length ) u32 keyvalues_get_next( struct keyvalues *kvs, u32 kv_offset ) { + ASSERT_CRITICAL( kv_offset ); + struct keyvalue *kv = stack_pointer( kvs->stack, kv_offset ); return kv->brother_offset; } u32 keyvalues_get_child( struct keyvalues *kvs, u32 root_offset, u32 index ) { + if( root_offset == 0 ) + root_offset = kvs->root_offset; + if( keyvalues_type( kvs, root_offset ) == k_keyvalue_type_frame ) { struct keyvalue *parent = stack_pointer( kvs->stack, root_offset ); @@ -191,7 +196,7 @@ bool keyvalues_read_u32s( struct keyvalues *kvs, u32 root_offset, const c8 *key, u32 value_length; char *value = keyvalues_value( kvs, keyvalues_get( kvs, root_offset, key ), &value_length ); struct stream s; - stream_open_buffer( &s, value, value_length, k_stream_text|k_stream_read ); + stream_open_buffer( &s, value, value_length, k_stream_read ); for( u32 i=0; ikvs = out_kvs; - parser->frame_stack[0].frame_offset = root_offset; + parser->frame_stack[0].frame_offset = root_offset? root_offset: out_kvs->root_offset; + + u32 child = keyvalues_get_child( out_kvs, root_offset, 0 ); + while( child ) + { + parser->frame_stack[0].latest_child_offset = child; + child = keyvalues_get_next( out_kvs, child ); + } } static void keyvalue_parser_link( struct keyvalue_parser *parser, u32 offset, u32 depth ) @@ -340,7 +352,7 @@ void keyvalues_parse_stream( struct keyvalues *kvs, u32 root_offset, struct stre if( parser.token0_length ) { parser.token0_length --; - stack_extend_last( parser.kvs->stack, +1 ); + stack_extend_last( parser.kvs->stack, parser.token0_buffer, +1 ); parser.token0_buffer[ parser.token0_length ] = '\0'; if( parser.token1_length ) @@ -401,7 +413,7 @@ void keyvalues_parse_stream( struct keyvalues *kvs, u32 root_offset, struct stre { if( parser.token0_length ) { - stack_extend_last( parser.kvs->stack, +1 ); + stack_extend_last( parser.kvs->stack, parser.token0_buffer, +1 ); parser.token0_buffer[ parser.token0_length-1 ] = c; parser.token0_length ++; parser.token0_hash = ((parser.token0_hash << 5) + parser.token0_hash) + (u32)c; @@ -431,6 +443,24 @@ void keyvalues_parse_stream( struct keyvalues *kvs, u32 root_offset, struct stre } } + +void keyvalues_write_stream( struct keyvalues *kvs, struct stream *out_stream, u32 node, u32 depth ) +{ + u32 kv = keyvalues_get_child( kvs, node, 0 ); + while( kv ) + { + if( keyvalues_type( kvs, kv ) == k_keyvalue_type_pair ) + { + for( u32 i=0; ioffset < 20 ) string_append_c8( output, ' ' ); - - if( type == $error ) string_append( output, "ERR|" ); - else if( type == $warning ) string_append( output, "WRN|" ); - else if( type == $ok ) string_append( output, "OK |" ); - else if( type == $info ) string_append( output, "LOG|" ); - else if( type == $low ) string_append( output, "LOW|" ); - else if( type == $fatal ) string_append( output, "!!!|" ); + while( output->offset < 32 ) string_append_c8( output, ' ' ); + if( type == $error ) string_append( output, KRED "ERR|" ); + else if( type == $warning ) string_append( output, KYEL "WRN|" ); + else if( type == $ok ) string_append( output, KGRN "OK |" ); + else if( type == $info ) string_append( output, KNRM "LOG|" ); + else if( type == $low ) string_append( output, KNRM "LOW|" ); + else if( type == $fatal ) string_append( output, KRED "!!!|" ); + else if( type == $shell ) string_append( output, KBLU "SHL|" ); + string_append( output, KNRM ); return output; } diff --git a/source/foundation/options.c b/source/foundation/options.c index 3eca315..2d2554a 100644 --- a/source/foundation/options.c +++ b/source/foundation/options.c @@ -200,6 +200,8 @@ const c8 *_option_argument( c8 c, const c8 *desc ) if( arg->name[j] == c ) { arg->used |= 0x1 << j; + ASSERT_CRITICAL( _options.arguments[ i + 1 ].type == k_argument_regular ); + _options.arguments[ i + 1 ].used = 0xffffffff; return _options.arguments[ i + 1 ].value; } } @@ -246,20 +248,18 @@ const c8 *_option_long_argument( c8 *name, const c8 *desc ) return arg? arg->value: NULL; } -const c8 *_option( u32 index ) +const c8 *_option(void) { - u32 count = 0; for( u32 i=0; i<_options.argument_count; i ++ ) { struct argument *arg = &_options.arguments[ i ]; if( arg->type == k_argument_regular ) { - count ++; - if( index+1 == count ) - { - arg->used = 0xffffffff; - return arg->value; - } + if( arg->used ) + continue; + + arg->used = 0xffffffff; + return arg->value; } } return NULL; diff --git a/source/foundation/stream.c b/source/foundation/stream.c index 3c0e8ab..aa9592f 100644 --- a/source/foundation/stream.c +++ b/source/foundation/stream.c @@ -2,12 +2,34 @@ #include #include +void stream_open_stack( struct stream *stream, struct stack_allocator *stack, u32 flags ) +{ + stream->flags = flags | k_stream_stack | k_stream_write; + stream->buffer_length = 0; + stream->offset = 0; + stream->buffer = stack_allocate( stack, 0, 4, "Stream" ); + stream->stack = stack; + + if( flags & k_stream_null_terminate ) + { + stack_extend_last( stack, stream->buffer, 1 ); + ((u8 *)stream->buffer)[0] = 0; + } +} + void stream_open_buffer( struct stream *stream, void *buffer, u32 buffer_length, u32 flags ) { - stream->flags = flags; + stream->flags = flags | k_stream_buffer; stream->buffer_length = buffer_length; stream->offset = 0; stream->buffer = buffer; + + if( (flags & k_stream_null_terminate) && (flags & k_stream_write) ) + { + ASSERT_CRITICAL( buffer_length >= 2 ); + stream->buffer_length --; + ((u8 *)buffer)[0] = 0; + } } bool stream_open_file( struct stream *stream, const c8 *path, u32 flags ) @@ -42,7 +64,10 @@ void stream_close( struct stream *stream ) static u32 stream_usable_length( struct stream *stream, u32 length ) { - if( stream->buffer_length && ((stream->offset + length) > stream->buffer_length) ) + if( stream->flags & k_stream_posix ) + return length; + + if( (stream->offset + length) > stream->buffer_length ) return stream->buffer_length - stream->offset; else return length; } @@ -91,7 +116,15 @@ u32 stream_read( struct stream *stream, void *buffer, u32 length ) u32 stream_write( struct stream *stream, const void *buffer, u32 length ) { ASSERT_CRITICAL( stream->flags & k_stream_write ); + u32 write_length = stream_usable_length( stream, length ); + if( stream->flags & k_stream_stack ) + { + i32 extend = length - write_length; + stack_extend_last( stream->stack, stream->buffer, extend ); + stream->buffer_length += extend; + write_length = length; + } if( stream->flags & k_stream_posix ) { @@ -112,8 +145,14 @@ u32 stream_write( struct stream *stream, const void *buffer, u32 length ) } } else + { for( u32 i=0; ibuffer)[stream->offset + i] = ((u8 *)buffer)[i]; + + // Note to self: Yes, this is safe (theres an extra 'hidden' byte in the buffer) + if( stream->flags & k_stream_null_terminate ) + ((u8 *)stream->buffer)[stream->offset+write_length] = 0; + } stream->offset += write_length; return write_length; diff --git a/source/foundation/string.c b/source/foundation/string.c index 9a03fba..6d81357 100644 --- a/source/foundation/string.c +++ b/source/foundation/string.c @@ -1,12 +1,11 @@ #include #include -void string_init( struct stream *string, c8 *buffer, u32 buffer_length ) +const c8 *string_get( struct stream *string ) { - ASSERT_CRITICAL( buffer ); - ASSERT_CRITICAL( buffer_length >= 2 ); - buffer[ 0 ] = 0; - stream_open_buffer( string, buffer, buffer_length-1, k_stream_write|k_stream_read|k_stream_text ); + ASSERT_CRITICAL( string->flags & (k_stream_stack|k_stream_buffer) ); + ASSERT_CRITICAL( string->flags & k_stream_null_terminate ); + return (const c8 *)string->buffer; } void string_clip( struct stream *string, i32 length ) @@ -15,22 +14,17 @@ void string_clip( struct stream *string, i32 length ) ASSERT_CRITICAL( length < string->buffer_length ); ASSERT_CRITICAL( !(string->flags & k_stream_posix) ); stream_seek( string, length ); - string->buffer[ length ] = 0; + stream_write( string, NULL, 0 ); } void string_append( struct stream *string, const c8 *substring ) { - for( u32 i=0; substring[i]; i ++ ) - stream_write( string, substring+i, 1 ); - if( !(string->flags & k_stream_posix) ) - string->buffer[ stream_offset( string ) ] = 0; + stream_write( string, substring, buffer_last_index( substring, 0, 0 ) ); } void string_append_c8( struct stream *string, c8 c ) { stream_write( string, &c, 1 ); - if( !(string->flags & k_stream_posix) ) - string->buffer[ stream_offset( string ) ] = 0; } static u32 string_u64_core( c8 reverse_buffer[64], u64 value, u64 base, u32 max_characters ) @@ -285,6 +279,4 @@ void v_string( struct stream *string, struct v_string_arg *argument_list ) string_append( string, ")>" ); } } - string_append_c8( string, '\n' ); } - diff --git a/source/tools/metacompiler.c b/source/tools/metacompiler.c index 5135544..b141638 100644 --- a/source/tools/metacompiler.c +++ b/source/tools/metacompiler.c @@ -1,66 +1,115 @@ -#include "common_api.h" +#include struct { bool address_sanitizer, thread_sanitizer, no_pdb; + + c8 binary_name[ 128 ]; + + struct stack_allocator all; } static _metacompiler; struct source_file { - const c8 *path; + enum source_type + { + k_source_c, + k_source_include_path + } + type; + + struct stream path; }; struct stretchy_allocator _source_list; -void _append_kv_list( const c8 *path ) -{ - struct keyvalues list; - ASSERT_CRITICAL( keyvalues_read_file( &list, path, _temporary_stack_allocator() ) ); +void _append_kv_list( const c8 *path ); - u32 block = keyvalues_get_child( &list, 0, 0 ); - while( block ) +void _parse_kv_block( struct keyvalues *kvs, u32 block, const c8 *folder ) +{ + u32 kv = keyvalues_get_child( kvs, block, 0 ); + while( kv ) { - if( compare_buffers( keyvalues_key( &list, block, NULL ), 0, "binary", 0 ) ) + if( keyvalues_type( kvs, kv ) == k_keyvalue_type_frame ) + { + _parse_kv_block( kvs, kv, folder ); + } + else { - u32 command = keyvalues_get_child( &list, block, 0 ); - const c8 *binary_name = NULL; + if( compare_buffers( keyvalues_key( kvs, kv, NULL ), 0, "name", 0 ) ) + { + buffer_copy( keyvalues_value( kvs, kv, NULL ), 0, + _metacompiler.binary_name, sizeof(_metacompiler.binary_name ) ); + } - while( command ) + if( compare_buffers( keyvalues_key( kvs, kv, NULL ), 0, "add", 0 ) ) { - if( compare_buffers( keyvalues_key( &list, command, NULL ), 0, "name", 0 ) ) - binary_name = keyvalues_value( &list, command, NULL ); + struct source_file *source = stretchy_append( &_source_list ); + source->type = k_source_c; - if( compare_buffers( keyvalues_key( &list, command, NULL ), 0, "source", 0 ) ) - { - struct source_file *source = stretchy_append( &_source_list ); - source->path = keyvalues_value( &list, command, NULL ); - } + stream_open_stack( &source->path, &_metacompiler.all, k_stream_null_terminate ); + $v_string( &source->path, {folder}, {"/"}, {keyvalues_value( kvs, kv, NULL )} ); + } - if( compare_buffers( keyvalues_key( &list, command, NULL ), 0, "append", 0 ) ) - { - struct stream stream; - if( stream_open_file( &stream, path, k_stream_read ) ) - { - keyvalues_parse_stream( &list, block, &stream ); - stream_close( &stream ); - } - } + if( compare_buffers( keyvalues_key( kvs, kv, NULL ), 0, "include", 0 ) ) + { + struct source_file *source = stretchy_append( &_source_list ); + source->type = k_source_include_path; - command = keyvalues_get_next( &list, command ); + stream_open_stack( &source->path, &_metacompiler.all, k_stream_null_terminate ); + $v_string( &source->path, {folder}, {"/"}, {keyvalues_value( kvs, kv, NULL )} ); } - ASSERT_CRITICAL( binary_name ); - struct stream *log = _log( k_log_info, "Working on binary: " ); - string_append( log, binary_name ); - string_append( log, "\n" ); + if( compare_buffers( keyvalues_key( kvs, kv, NULL ), 0, "append", 0 ) ) + { + u32 temp_frame = _start_temporary_frame(); + { + struct stream path_string; + stream_open_stack( &path_string, _temporary_stack_allocator(), k_stream_null_terminate ); + $v_string( &path_string, {folder}, {"/"}, {keyvalues_value( kvs, kv, NULL )} ); + _append_kv_list( string_get( &path_string ) ); + } + _end_temporary_frame( temp_frame ); + } } - block = keyvalues_get_next( &list, block ); + kv = keyvalues_get_next( kvs, kv ); } } +void _append_kv_list( const c8 *path ) +{ + u32 temp_frame = _start_temporary_frame(); + + c8 *folder = realpath( path, NULL ); + if( !folder ) + { + $log( $fatal, {"'"}, {path}, {"' "}, $errno() ); + _fatal_exit(); + } + + i32 s = buffer_last_index( folder, '/', 0 ); + if( s != -1 ) + { + folder[s] = '\0'; + } + + struct keyvalues list; + ASSERT_CRITICAL( keyvalues_read_file( &list, path, _temporary_stack_allocator() ) ); + _parse_kv_block( &list, 0, folder ); + + free( folder ); + _end_temporary_frame( temp_frame ); +} + +void system_call( const c8 *call ) +{ + $log( $shell, {call} ); + ASSERT_CRITICAL( system(call) == 0 ); +} + i32 main( i32 argc, const c8 *argv[] ) { _exit_init(); @@ -68,6 +117,8 @@ i32 main( i32 argc, const c8 *argv[] ) const c8 *list_file = NULL; + u64 processors = 4; + const c8 *arg; if( _option_long( "tsan", "Build using thread sanitizer" ) ) _metacompiler.thread_sanitizer = 1; @@ -89,27 +140,78 @@ i32 main( i32 argc, const c8 *argv[] ) if( (arg = _option_long_argument( "arch", "any, i386, x86_64" )) ) { } + + if( (arg = _option_argument( 'j', "CPU count <0-8>" )) ) + { + struct stream arg_stream; + stream_open_buffer( &arg_stream, (void*)arg, buffer_last_index(arg,0,0)+1, k_stream_read ); + ASSERT_CRITICAL( string_parse_u64( &arg_stream, &processors ) == k_string_parse_ok ); + } - list_file = _option( 0 ); + list_file = _option(); //if( (arg = _option_long_argument( "platform", _options_check_end(); - ASSERT_CRITICAL( list_file ); + stack_init( &_metacompiler.all, NULL, BYTES_MB(64), "Everything" ); - stretchy_init( &_source_list, sizeof(struct source_file) ); + ASSERT_CRITICAL( list_file ); - u32 temp_frame = _start_temporary_frame(); + $log( $info, {"Building source tree"} ); + stretchy_init( &_source_list, sizeof(struct source_file) ); _append_kv_list( list_file ); - _end_temporary_frame( temp_frame ); - for( u32 i=0; ipath ); - string_append( log, "\n" ); + c8 *output_folder = realpath( list_file, NULL ); + if( !output_folder ) + { + $log( $fatal, {"'"}, {list_file}, {"' "}, $errno() ); + _fatal_exit(); + } + + i32 s = buffer_last_index( output_folder, '/', 0 ); + if( s != -1 ) + output_folder[s] = '\0'; + + struct stream folder_string; + stream_open_stack( &folder_string, _temporary_stack_allocator(), k_stream_null_terminate ); + $v_string( &folder_string, {output_folder}, {"/bin/"}, {"project"}, {"-linux-x86_64-zig-cc"} ); + + free(output_folder); + + struct stream command_string; + stream_open_stack( &command_string, _temporary_stack_allocator(), k_stream_null_terminate ); + $v_string( &command_string, {"mkdir -p "}, $string( &folder_string ) ); + system_call( string_get( &command_string ) ); + + + + stream_open_stack( &command_string, _temporary_stack_allocator(), k_stream_null_terminate ); + $v_string( &command_string, {"taskset -c 0-"}, $unsigned(processors), + {" zig cc -Wall -Wno-unused-function -std=c99 -D_DEFAULT_SOURCE \\\n"}, + {" -include \"common_api.h\" \\\n"} ); + + for( u32 i=0; itype == k_source_include_path ) + $v_string( &command_string, {" -I"}, $string(&source->path), {" \\\n"} ); + } + + for( u32 i=0; itype == k_source_c ) + $v_string( &command_string, {" "}, $string(&source->path), {" \\\n"} ); + } + + $v_string( &command_string, {"-o "}, $string( &folder_string ), {"/project"} ); + system_call( string_get( &command_string ) ); } + _end_temporary_frame( temp_frame ); stretchy_free( &_source_list ); } diff --git a/test.kv b/test.kv new file mode 100644 index 0000000..4b9d98f --- /dev/null +++ b/test.kv @@ -0,0 +1,3 @@ +name program +append foundation.kv +append build/test.kv