-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 \
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
--- /dev/null
+add hello.c
--- /dev/null
+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
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
* ------------------------------------------------------------------------------------------------------------------ */
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
{
{
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 );
* ------------------------------------------------------------------------------------------------------------------ */
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
{
{
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 );
/* 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 );
#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__ }
#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();
};
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 );
--- /dev/null
+name program
+append foundation.kv
+add source/tools/metacompiler.c
stack->offset ++;
void *block = stack->data + stack->offset;
stack->offset += size;
+ stack->check_pointer = block;
return block;
}
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;
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<length; i ++ )
- ((u8 *)buffer_dest)[i] = ((u8 *)buffer_src)[ i ];
+ ASSERT_CRITICAL( dest_length );
+
+ for( u32 i=0; i<dest_length; i ++ )
+ {
+ u8 v = ((u8 *)buffer_src)[ i ];
+ ((u8 *)buffer_dest)[i] = v;
+
+ if( (src_length == 0) && (v == 0) )
+ return;
+ }
+
+ if( src_length == 0 )
+ {
+ $log( $warning, {"Buffer copy (null terminated), was truncated"} );
+ ((u8 *)buffer_dest)[ dest_length -1 ] = 0;
+ }
}
-#define _DEFAULT_SOURCE
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
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 );
}
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 );
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; i<len; i ++ )
{
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; i<len; i ++ )
{
}
#define KV_APPEND_TEMPLATE( FUNCTION, ... ) \
- c8 formatted[ 1024 ]; \
+ u32 temp_frame = _start_temporary_frame(); \
struct stream value_str; \
- string_init( &value_str, formatted, sizeof(formatted) ); \
+ stream_open_stack( &value_str, _temporary_stack_allocator(), k_stream_null_terminate ); \
for( u32 i=0; i<len; i++ ) \
{ \
FUNCTION ( &value_str, values[i], __VA_ARGS__ ); \
if( i+1!=len ) \
string_append_c8( &value_str, ' ' ); \
} \
- if( stream_error( &value_str ) ) \
- return 0; \
- return keyvalues_append_string( kvs, parent_offset, key, formatted );
+ u32 r = keyvalues_append_string( kvs, parent_offset, key, string_get(&value_str) ); \
+ _end_temporary_frame( temp_frame ); \
+ return r;
u32 keyvalues_append_vu32( struct keyvalues *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len )
{
zero_buffer( parser, sizeof(struct keyvalue_parser) );
parser->kvs = 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 )
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 )
{
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;
}
}
+
+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; i<depth; i ++ )
+ $v_string( out_stream, {" "} );
+ $v_string( out_stream, {keyvalues_key( kvs, kv, NULL )}, {" "}, {keyvalues_value( kvs, kv, NULL )}, {"\n"} );
+ }
+ else
+ keyvalues_write_stream( kvs, out_stream, kv, depth+1 );
+ kv = keyvalues_get_next( kvs, kv );
+ }
+}
+
#if 0
void vg_kv_write_init( vg_kv_write *w, vg_stream *stream )
{
return &_stdout_stream;
}
+#define KNRM "\x1B[0m"
+#define KBLK "\x1B[30m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KYEL "\x1B[33m"
+#define KBLU "\x1B[34m"
+#define KMAG "\x1B[35m"
+#define KCYN "\x1B[36m"
+#define KWHT "\x1B[37m"
+
struct stream *_log_event( u32 type, const c8 *code_location )
{
struct stream *output = _get_console_stream();
+ string_append( output, KBLK );
string_append( output, code_location );
- while( output->offset < 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;
}
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;
}
}
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;
#include <errno.h>
#include <string.h>
+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 )
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;
}
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 )
{
}
}
else
+ {
for( u32 i=0; i<write_length; i ++ )
((u8 *)stream->buffer)[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;
#include <errno.h>
#include <string.h>
-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 )
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 )
string_append( string, ")>" );
}
}
- string_append_c8( string, '\n' );
}
-
-#include "common_api.h"
+#include <stdlib.h>
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();
const c8 *list_file = NULL;
+ u64 processors = 4;
+
const c8 *arg;
if( _option_long( "tsan", "Build using thread sanitizer" ) )
_metacompiler.thread_sanitizer = 1;
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; i<stretchy_count( &_source_list ); i ++ )
+
+ u32 temp_frame = _start_temporary_frame();
{
- struct source_file *source = stretchy_get( &_source_list, i );
- struct stream *log = _log( k_log_info, source->path );
- 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; i<stretchy_count( &_source_list ); i ++ )
+ {
+ struct source_file *source = stretchy_get( &_source_list, i );
+ if( source->type == k_source_include_path )
+ $v_string( &command_string, {" -I"}, $string(&source->path), {" \\\n"} );
+ }
+
+ for( u32 i=0; i<stretchy_count( &_source_list ); i ++ )
+ {
+ struct source_file *source = stretchy_get( &_source_list, i );
+ if( source->type == 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 );
}
--- /dev/null
+name program
+append foundation.kv
+append build/test.kv