jjbbb
authorhgn <hgodden00@gmail.com>
Mon, 22 Sep 2025 20:24:22 +0000 (20:24 +0000)
committerhgn <hgodden00@gmail.com>
Mon, 22 Sep 2025 20:24:22 +0000 (20:24 +0000)
15 files changed:
bootstrap.sh
build/test.kv [new file with mode: 0644]
foundation.kv [new file with mode: 0644]
include/common_api.h
metacompiler.kv [new file with mode: 0644]
source/foundation/allocator_stack.c
source/foundation/buffer_operations.c
source/foundation/io.c
source/foundation/keyvalues.c
source/foundation/logging.c
source/foundation/options.c
source/foundation/stream.c
source/foundation/string.c
source/tools/metacompiler.c
test.kv [new file with mode: 0644]

index 1c166c68feaebca4ce8b538ae42edcf420a2cd06..1756bfe0af849ff4822aa681c5d931bf602e787b 100755 (executable)
@@ -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 (file)
index 0000000..7e9178a
--- /dev/null
@@ -0,0 +1 @@
+add hello.c
diff --git a/foundation.kv b/foundation.kv
new file mode 100644 (file)
index 0000000..b42dd77
--- /dev/null
@@ -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
index 5ab73c82183dc5ccec7fef48df8c9c823061c8e2..79da403fea0c82b0ee7bffdae11cf9d370e85ee9 100644 (file)
@@ -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 (file)
index 0000000..af43f0b
--- /dev/null
@@ -0,0 +1,3 @@
+name program
+append foundation.kv
+add source/tools/metacompiler.c
index fd310b05867f4a080deb774c39ec6d1c6afb0ed2..51dc42bc3a2c2df5cf312831747e528018105029 100644 (file)
@@ -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;
index b9ad005eec80ac644ad2f409ce712a9143527b18..a89ca0f44991a8ada07f2dd5235eb4c52b0c6933 100644 (file)
@@ -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<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;
+   }
 }
index 9c421d816c80e746e1c7417b40293cbe4e6bc2c1..e3fd392c3a1ce81d0bb49d15dd22550a1cb65e79 100644 (file)
@@ -1,4 +1,3 @@
-#define _DEFAULT_SOURCE
 #include <dirent.h>
 #include <stdio.h>
 #include <sys/stat.h>
index 68fc0f5db4dd4f81131ecbcf19ee9fd1c6111325..b7a70d30cd59b9d8fd3b815f5ebdcc4bfdffecdc 100644 (file)
@@ -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; i<len; i ++ )
    {
@@ -215,7 +220,7 @@ bool keyvalues_read_f32s( 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; i<len; i ++ )
    {
@@ -239,18 +244,18 @@ const c8 *keyvalues_read_string( struct keyvalues *kvs, u32 root_offset, const c
 }
 
 #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 )
 {
@@ -292,7 +297,14 @@ static void keyvalue_parser_init( struct keyvalue_parser *parser, struct keyvalu
 
    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 )
@@ -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; 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 )
 {
index e13fabc387be4a1d3fcb2dfc3d59e51e50f6a32b..9f5f778853cc04186c8b0e3ef6f0d6bde8b1c7f5 100644 (file)
@@ -16,17 +16,29 @@ struct stream *_get_console_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;
 }
index 3eca315f56bf3ec8fbb9bd561d520bef8e23660b..2d2554affcb4db5e2578527a70c035ce37fa0f5d 100644 (file)
@@ -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;
index 3c0e8ab482d51fcf58eae042e07c89971b3d04d5..aa9592fc91633d58e253f85712ed90e6975fb4c7 100644 (file)
@@ -2,12 +2,34 @@
 #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 )
@@ -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; 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;
index 9a03fbab1f50105072c05d1789bd6dd0cfe950b1..6d813572601122a54e11a3b7db3620bea0000c32 100644 (file)
@@ -1,12 +1,11 @@
 #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 )
@@ -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' );
 }
-
index 5135544756e3f187097c0dd039d155b161e816bb..b1416386687ec3a32abf8db58145feda1b9f48f8 100644 (file)
-#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();
@@ -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; 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 );
 }
diff --git a/test.kv b/test.kv
new file mode 100644 (file)
index 0000000..4b9d98f
--- /dev/null
+++ b/test.kv
@@ -0,0 +1,3 @@
+name program
+append foundation.kv
+append build/test.kv