added relative lookups on file_contents directives
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 May 2021 16:06:37 +0000 (11:06 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 May 2021 16:06:37 +0000 (11:06 -0500)
bin/onyx
include/onyxastnodes.h
include/onyxutils.h
modules/immediate_mode/immediate_renderer.onyx
modules/immediate_mode/shaders/basic_fragment.glsl [new file with mode: 0644]
modules/immediate_mode/shaders/basic_vertex.glsl [new file with mode: 0644]
modules/immediate_mode/shaders/textured_fragment.glsl [new file with mode: 0644]
src/onyx.c
src/onyxparser.c
src/onyxutils.c
src/onyxwasm.c

index 8b041462c9620aaf04f32cb4226d3c956d6ee596..b0d63f12be1bc99483631ffa016291787b97e4a8 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index bd88b7fd3d783deb7954103b50cce882ce77ff69..4db208e99032a724781f4db926a1ee8918ba0987 100644 (file)
@@ -504,7 +504,14 @@ struct AstArrayAccess   { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 ele
 struct AstFieldAccess   { AstTyped_base; AstTyped *expr; u32 offset; u32 idx; char* field; }; // If token is null, defer to field
 struct AstSizeOf        { AstTyped_base; AstType *so_ast_type; Type *so_type; u64 size; };
 struct AstAlignOf       { AstTyped_base; AstType *ao_ast_type; Type *ao_type; u64 alignment; };
-struct AstFileContents  { AstTyped_base; OnyxToken *filename; u32 addr, size; };
+struct AstFileContents  {
+    AstTyped_base;
+
+    OnyxToken *filename_token;
+    char *filename; // The parsed file name, with '\' sequences removed and resolved to a particular file if possible.
+
+    u32 addr, size;
+};
 struct AstUnaryFieldAccess {
     AstTyped_base;
 
index d1369e8630be6be148f830d4e0e42e218ec6c5d0..b9c9b21944ed3282b1687a9f2374a63f73c44404 100644 (file)
@@ -30,3 +30,9 @@ u32 char_to_base16_value(char x);
 
 // Returns the length after processing the string.
 i32 string_process_escape_seqs(char* dest, char* src, i32 len);
+
+// NOTE: This should not be called until immediately before using the return value.
+// This function can return a static variable which will change if this is called
+// another time.                                        -brendanfh 2020/10/09
+// :RelativeFiles This should lookup for the file relative to "relative_to"
+char* lookup_included_file(char* filename, char* relative_to, b32 add_onyx_suffix, b32 search_included_folders);
index 4fd88b2d3cb2b38033758d6d763139834af687a7..ba7d925913495d1c87e1883c0756cc95a8ee0dd4 100644 (file)
@@ -3,62 +3,6 @@ package immediate_mode
 use package core
 #private_file gl :: package gl
 
-// CLEANUP: Proper multi-line strings need to be added...
-// This is a gross abuse of the lexer.
-IMMEDIATE_VERTEX_SHADER :: "#version 300 es
-
-layout(location = 0) in vec2 a_vertex;
-layout(location = 1) in vec4 a_color;
-layout(location = 2) in vec2 a_texture;
-
-uniform mat4 u_view;
-uniform mat4 u_world;
-
-out vec4 v_color;
-out vec2 v_texture;
-
-void main() {
-    gl_Position = u_view * u_world * vec4(a_vertex, 0, 1);
-
-    v_color = a_color;
-    v_texture = a_texture;
-}
-"
-
-IMMEDIATE_FRAGMENT_SHADER :: "#version 300 es
-
-precision mediump float;
-
-uniform sampler2D u_texture;
-
-in vec4 v_color;
-in vec2 v_texture;
-
-out vec4 fragColor;
-
-void main() {
-    fragColor = v_color;
-}
-"
-
-IMMEDIATE_FRAGMENT_SHADER_TEXTURED :: "#version 300 es
-
-precision mediump float;
-
-uniform sampler2D u_texture;
-
-in vec4 v_color;
-in vec2 v_texture;
-
-out vec4 fragColor;
-
-void main() {
-    fragColor = v_color * texture(u_texture, v_texture);
-}
-"
-
-
-
 Vector2 :: struct {
     x, y: f32;
 }
@@ -103,6 +47,10 @@ Immediate_Renderer :: struct {
     }
 
     init :: (use ir: ^Immediate_Renderer, max_verticies := Default_Max_Verticies) {
+        IMMEDIATE_VERTEX_SHADER            :: #file_contents "./shaders/basic_vertex.glsl"
+        IMMEDIATE_FRAGMENT_SHADER          :: #file_contents "./shaders/basic_fragment.glsl"
+        IMMEDIATE_FRAGMENT_SHADER_TEXTURED :: #file_contents "./shaders/textured_fragment.glsl"
+
         simple_shader   = Shader.make_from_source(IMMEDIATE_VERTEX_SHADER, IMMEDIATE_FRAGMENT_SHADER);
         textured_shader = Shader.make_from_source(IMMEDIATE_VERTEX_SHADER, IMMEDIATE_FRAGMENT_SHADER_TEXTURED);
         active_shader   = ^simple_shader;
diff --git a/modules/immediate_mode/shaders/basic_fragment.glsl b/modules/immediate_mode/shaders/basic_fragment.glsl
new file mode 100644 (file)
index 0000000..f8bc23c
--- /dev/null
@@ -0,0 +1,14 @@
+#version 300 es
+
+precision mediump float;
+
+uniform sampler2D u_texture;
+
+in vec4 v_color;
+in vec2 v_texture;
+
+out vec4 fragColor;
+
+void main() {
+    fragColor = v_color;
+}
\ No newline at end of file
diff --git a/modules/immediate_mode/shaders/basic_vertex.glsl b/modules/immediate_mode/shaders/basic_vertex.glsl
new file mode 100644 (file)
index 0000000..4c6edf4
--- /dev/null
@@ -0,0 +1,18 @@
+#version 300 es
+
+layout(location = 0) in vec2 a_vertex;
+layout(location = 1) in vec4 a_color;
+layout(location = 2) in vec2 a_texture;
+
+uniform mat4 u_view;
+uniform mat4 u_world;
+
+out vec4 v_color;
+out vec2 v_texture;
+
+void main() {
+    gl_Position = u_view * u_world * vec4(a_vertex, 0, 1);
+
+    v_color = a_color;
+    v_texture = a_texture;
+}
\ No newline at end of file
diff --git a/modules/immediate_mode/shaders/textured_fragment.glsl b/modules/immediate_mode/shaders/textured_fragment.glsl
new file mode 100644 (file)
index 0000000..186e4c9
--- /dev/null
@@ -0,0 +1,14 @@
+#version 300 es
+
+precision mediump float;
+
+uniform sampler2D u_texture;
+
+in vec4 v_color;
+in vec2 v_texture;
+
+out vec4 fragColor;
+
+void main() {
+    fragColor = v_color * texture(u_texture, v_texture);
+}
\ No newline at end of file
index 01c5977cdc6d34063ea884143b3364254b5faf8c..ea6a5e58c24316b1de49bee8ec199c194320cf6c 100644 (file)
@@ -206,58 +206,6 @@ static void context_free() {
     compile_opts_free(context.options);
 }
 
-// NOTE: This should not be called until immediately before using the return value.
-// This function can return a static variable which will change if this is called
-// another time.                                        -brendanfh 2020/10/09
-// :RelativeFiles This should lookup for the file relative to "relative_to"
-static char* lookup_included_file(char* filename, char* relative_to) {
-    assert(relative_to != NULL);
-
-    static char path[256];
-    fori (i, 0, 256) path[i] = 0;
-
-    static char fn[128];
-    fori (i, 0, 128) fn[i] = 0;
-
-    if (!bh_str_ends_with(filename, ".onyx")) {
-        bh_snprintf(fn, 128, "%s.onyx", filename);
-    } else {
-        bh_snprintf(fn, 128, "%s", filename);
-    }
-
-#if defined(_BH_LINUX)
-    #define DIR_SEPARATOR '/'
-#elif defined(_BH_WINDOWS)
-    #define DIR_SEPARATOR '\\'
-#endif
-
-    fori (i, 0, 128) if (fn[i] == '/') fn[i] = DIR_SEPARATOR;
-
-    if (bh_str_starts_with(filename, "./")) {
-        if (relative_to[strlen(relative_to) - 1] != DIR_SEPARATOR)
-            bh_snprintf(path, 256, "%s%c%s", relative_to, DIR_SEPARATOR, fn);
-        else
-            bh_snprintf(path, 256, "%s%s", relative_to, fn);
-
-        if (bh_file_exists(path)) return bh_path_get_full_name(path, global_scratch_allocator);
-
-        return fn;
-    }
-
-    bh_arr_each(const char *, folder, context.options->included_folders) {
-        if ((*folder)[strlen(*folder) - 1] != DIR_SEPARATOR)
-            bh_snprintf(path, 256, "%s%c%s", *folder, DIR_SEPARATOR, fn);
-        else
-            bh_snprintf(path, 256, "%s%s", *folder, fn);
-
-        if (bh_file_exists(path)) return bh_path_get_full_name(path, global_scratch_allocator);
-    }
-
-    return fn;
-
-#undef DIR_SEPARATOR
-}
-
 static void parse_source_file(bh_file_contents* file_contents) {
     // :Remove passing the allocators as parameters
     OnyxTokenizer tokenizer = onyx_tokenizer_create(context.token_alloc, file_contents);
@@ -304,7 +252,7 @@ static void process_load_entity(Entity* ent) {
 
         char* parent_folder = bh_path_get_parent(parent_file, global_scratch_allocator);
         
-        char* filename = lookup_included_file(include->name, parent_folder);
+        char* filename = lookup_included_file(include->name, parent_folder, 1, 1);
         char* formatted_name = bh_strdup(global_heap_allocator, filename);
 
         process_source_file(formatted_name, include->token->pos);
index c24ff4e8189014d349caeee3a9fd48c61d50412c..0b7195c63590c15f9f61af7c3bb231b96ed90393 100644 (file)
@@ -483,7 +483,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             if (parse_possible_directive(parser, "file_contents")) {
                 AstFileContents* fc = make_node(AstFileContents, Ast_Kind_File_Contents);
                 fc->token = parser->prev - 1;
-                fc->filename = expect_token(parser, Token_Type_Literal_String);
+                fc->filename_token = expect_token(parser, Token_Type_Literal_String);
                 fc->type = type_make_slice(parser->allocator, &basic_types[Basic_Kind_U8]);
                 
                 ENTITY_SUBMIT(fc);
index 49a10a9f96de8bc5c279cd9e2c4a11d88326b091..64a44ff1ac02736b26ca5fd31c23708886e1d541 100644 (file)
@@ -1452,3 +1452,54 @@ i32 string_process_escape_seqs(char* dest, char* src, i32 len) {
 
     return total_len;
 }
+
+char* lookup_included_file(char* filename, char* relative_to, b32 add_onyx_suffix, b32 search_included_folders) {
+    assert(relative_to != NULL);
+
+    static char path[256];
+    fori (i, 0, 256) path[i] = 0;
+
+    static char fn[128];
+    fori (i, 0, 128) fn[i] = 0;
+
+    if (!bh_str_ends_with(filename, ".onyx") && add_onyx_suffix) {
+        bh_snprintf(fn, 128, "%s.onyx", filename);
+    } else {
+        bh_snprintf(fn, 128, "%s", filename);
+    }
+
+#if defined(_BH_LINUX)
+    #define DIR_SEPARATOR '/'
+#elif defined(_BH_WINDOWS)
+    #define DIR_SEPARATOR '\\'
+#endif
+
+    fori (i, 0, 128) if (fn[i] == '/') fn[i] = DIR_SEPARATOR;
+
+    if (bh_str_starts_with(filename, "./")) {
+        if (relative_to[strlen(relative_to) - 1] != DIR_SEPARATOR)
+            bh_snprintf(path, 256, "%s%c%s", relative_to, DIR_SEPARATOR, fn + 2);
+        else
+            bh_snprintf(path, 256, "%s%s", relative_to, fn + 2);
+
+        if (bh_file_exists(path)) return bh_path_get_full_name(path, global_scratch_allocator);
+
+        return fn;
+    }
+
+    if (search_included_folders) {
+        bh_arr_each(const char *, folder, context.options->included_folders) {
+            if ((*folder)[strlen(*folder) - 1] != DIR_SEPARATOR)
+                bh_snprintf(path, 256, "%s%c%s", *folder, DIR_SEPARATOR, fn);
+            else
+                bh_snprintf(path, 256, "%s%s", *folder, fn);
+
+            if (bh_file_exists(path)) return bh_path_get_full_name(path, global_scratch_allocator);
+        }
+    }
+
+    return fn;
+
+#undef DIR_SEPARATOR
+}
+
index 43b21cb15b21dcaa445fecadebdee8d8210420ae..851c744458be46cd18451ed370703e5883ca8973 100644 (file)
@@ -3081,26 +3081,40 @@ static void emit_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
 }
 
 static void emit_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {
-    token_toggle_end(fc->filename);
+    token_toggle_end(fc->filename_token);
 
-    if (bh_table_has(StrLitInfo, mod->loaded_file_info, fc->filename->text)) {
-        StrLitInfo info = bh_table_get(StrLitInfo, mod->loaded_file_info, fc->filename->text);
+    // INVESTIGATE: I think that filename should always be NULL when this function starts because
+    // a file contents entity is only processed once and therefore should only go through this step
+    // once. But somehow filename isn't NULL occasionally so I have to check for that...
+    //                                                                      - brendanfh  2021/05/23
+    if (fc->filename == NULL) {
+        const char* parent_file = fc->token->pos.filename;
+        if (parent_file == NULL) parent_file = ".";
+
+        char* parent_folder = bh_path_get_parent(parent_file, global_scratch_allocator);
+
+        char* temp_fn     = bh_alloc_array(global_scratch_allocator, char, fc->filename_token->length);
+        i32   temp_fn_len = string_process_escape_seqs(temp_fn, fc->filename_token->text, fc->filename_token->length);
+        char* filename    = lookup_included_file(temp_fn, parent_folder, 0, 0);
+        fc->filename      = bh_strdup(global_heap_allocator, filename);
+    }
+
+    token_toggle_end(fc->filename_token);
+
+    if (bh_table_has(StrLitInfo, mod->loaded_file_info, fc->filename)) {
+        StrLitInfo info = bh_table_get(StrLitInfo, mod->loaded_file_info, fc->filename);
         fc->addr = info.addr;
         fc->size = info.len;
-
-        token_toggle_end(fc->filename);
         return;
     }
 
     u32 offset = mod->next_datum_offset;
     bh_align(offset, 16);
 
-    if (!bh_file_exists(fc->filename->text)) {
-        onyx_report_error(fc->filename->pos,
+    if (!bh_file_exists(fc->filename)) {
+        onyx_report_error(fc->filename_token->pos,
                 "Unable to open file for reading, '%s'.",
-                fc->filename->text);
-
-        token_toggle_end(fc->filename);
+                fc->filename);
         return;
     }
 
@@ -3108,14 +3122,14 @@ static void emit_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {
     // if the filename is prefixed with a './' or '.\\' then it should be relative to the
     // file in which is was inclded. The loaded file info above should probably use the full
     // file path in order to avoid duplicates.
-    bh_file_contents contents = bh_file_read_contents(global_heap_allocator, fc->filename->text);
+    bh_file_contents contents = bh_file_read_contents(global_heap_allocator, fc->filename);
     u8* actual_data = bh_alloc(global_heap_allocator, contents.length + 1);
     u32 length = contents.length + 1;
     memcpy(actual_data, contents.data, contents.length);
     actual_data[contents.length] = 0;
     bh_file_contents_free(&contents);
 
-    bh_table_put(StrLitInfo, mod->loaded_file_info, fc->filename->text, ((StrLitInfo) {
+    bh_table_put(StrLitInfo, mod->loaded_file_info, fc->filename, ((StrLitInfo) {
         .addr = offset,
         .len  = length - 1,
     }));
@@ -3132,8 +3146,6 @@ static void emit_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {
     bh_arr_push(mod->data, datum);
 
     mod->next_datum_offset = offset + length;
-
-    token_toggle_end(fc->filename);
 }
 
 OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {