From b8712258356ac43f6ea51bfffe02554c844598ee Mon Sep 17 00:00:00 2001 From: zelaven Date: Sun, 2 Feb 2020 11:33:45 +0100 Subject: [PATCH] Metaprogramming should work now --- acs_interface/ZMEMORY.acs | 31 +++---- acs_interface/ZMEMORY_g.acs | 16 ++++ acs_interface/ZMEMORY_w.acs | 16 ++++ build2.sh | 21 +++++ meta_src/scanner.l | 2 +- meta_src/test.acs | 2 + src/acs_source/ZMEMORY.acs | 165 +++++++++++++++++++++--------------- src/acs_source/compile.sh | 4 - 8 files changed, 169 insertions(+), 88 deletions(-) create mode 100644 acs_interface/ZMEMORY_g.acs create mode 100644 acs_interface/ZMEMORY_w.acs create mode 100755 build2.sh create mode 100644 meta_src/test.acs delete mode 100644 src/acs_source/compile.sh diff --git a/acs_interface/ZMEMORY.acs b/acs_interface/ZMEMORY.acs index 4a1c6d4..99630f8 100644 --- a/acs_interface/ZMEMORY.acs +++ b/acs_interface/ZMEMORY.acs @@ -1,18 +1,15 @@ #library "ZMEMORY" -#include "zcommon.acs" - -//Simple linked list implementation of malloc - -//Memory space -global int 63:memory[]; - -//NULL "pointer" -#libdefine nullptr 0 - -//Allocated size bytes in the memory space -function int malloc (int size) {return 0;} - -//Frees an allocated block in the memory space. -//There are no safeguards in this function to guess whether or not the free is -// valid, so be careful. -function int free (int p_ptr) {return 0;} +#include "zcommon.acs" +#include "ZMEMORY_g.acs" +#include "ZMEMORY_w.acs" +global int 63:gmemory[]; +world int 255:wmemory[]; +#libdefine nullptr 0 +//#define nullptr 0 +#define malloc_allocated 0 +#define malloc_size 1 +#define malloc_next_header 2 +#define malloc_prev_header 3 +#define malloc_num_header_properties 4 +#define p_malloc_init_flag_location 0 +#define p_malloc_first_header_location 1 diff --git a/acs_interface/ZMEMORY_g.acs b/acs_interface/ZMEMORY_g.acs new file mode 100644 index 0000000..6786802 --- /dev/null +++ b/acs_interface/ZMEMORY_g.acs @@ -0,0 +1,16 @@ + +global int 63:gmemory[]; + +//[Z] The reason I do it like this is because whoever made the acc is insane. +#define gnullptr 0 + +#define gmalloc_allocated 0 +#define gmalloc_size 1 +#define gmalloc_next_header 2 +#define gmalloc_prev_header 3 +#define gmalloc_num_header_properties 4 + +#define gp_malloc_init_flag_location 0 +#define gp_malloc_first_header_location 1 +function int gmalloc (int size) {return 0;} +function int gfree (int p_ptr) {return 0;} diff --git a/acs_interface/ZMEMORY_w.acs b/acs_interface/ZMEMORY_w.acs new file mode 100644 index 0000000..85bc8fe --- /dev/null +++ b/acs_interface/ZMEMORY_w.acs @@ -0,0 +1,16 @@ + +world int 255:wmemory[]; + +//[Z] The reason I do it like this is because whoever made the acc is insane. +#define wnullptr 0 + +#define wmalloc_allocated 0 +#define wmalloc_size 1 +#define wmalloc_next_header 2 +#define wmalloc_prev_header 3 +#define wmalloc_num_header_properties 4 + +#define wp_malloc_init_flag_location 0 +#define wp_malloc_first_header_location 1 +function int wmalloc (int size) {return 0;} +function int wfree (int p_ptr) {return 0;} diff --git a/build2.sh b/build2.sh new file mode 100755 index 0000000..7261ef4 --- /dev/null +++ b/build2.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Construct the ACS source from the original file. +cd build_files +cat ../src/acs_source/ZMEMORY.acs | ../meta_src/metatool.out ZMEMORY.acs ZMEMORY_g.acs ZMEMORY_w.acs ../acs_interface/ZMEMORY.acs ../acs_interface/ZMEMORY_g.acs ../acs_interface/ZMEMORY_w.acs + +# compile the ACS source +acc -i $ACC_ZCOMMON_PATH ZMEMORY.acs ../src/acs/ZMEMORY.o + +cd ../src +# Bundle everything that isn't: +# .sh : a shell script. +thin_arg=$1 +version=$(cat ../version.txt) +if [[ $thin_arg == "thin" ]]; then + 7za a -tzip ../ZMemory_v$version\_thin.pk3 -r -x\!*.sh -x\!acs/.gitignore -xr\!acs_source +else + 7za a -tzip ../ZMemory_v$version.pk3 -r -x\!*.sh -x\!acs/.gitignore +fi + + diff --git a/meta_src/scanner.l b/meta_src/scanner.l index 4706891..8224228 100644 --- a/meta_src/scanner.l +++ b/meta_src/scanner.l @@ -41,7 +41,7 @@ FILE* interface_g = NULL; "$$" BEGIN(INITIAL); (.|\n) p(code_g); p(code_w); p(interface_g); p(interface_w); -"{" p(code_g); p(code_w); ps(interface_g, "{return 0;}"); ps(interface_w, "{return 0;}"); BEGIN(LEX_STATE_EXPORT_SPLIT_FUNCTION_BODY); +"{" p(code_g); p(code_w); ps(interface_g, "{return 0;}\n"); ps(interface_w, "{return 0;}\n"); BEGIN(LEX_STATE_EXPORT_SPLIT_FUNCTION_BODY); "@" ps(code_g,"g"); ps(code_w,"w"); ps(interface_g,"g"); ps(interface_w,"w"); (.|\n) p(code_g); p(code_w); p(interface_g); p(interface_w); "@" ps(code_g,"g"); ps(code_w,"w"); diff --git a/meta_src/test.acs b/meta_src/test.acs new file mode 100644 index 0000000..33acfa3 --- /dev/null +++ b/meta_src/test.acs @@ -0,0 +1,2 @@ +$$export_split +cookies $$ diff --git a/src/acs_source/ZMEMORY.acs b/src/acs_source/ZMEMORY.acs index fbc69a5..d3907bd 100644 --- a/src/acs_source/ZMEMORY.acs +++ b/src/acs_source/ZMEMORY.acs @@ -1,136 +1,167 @@ -#library "ZMEMORY" -#include "zcommon.acs" +$export_common #library "ZMEMORY" +$export_common #include "zcommon.acs" + +#define muffins 42 + +$export_common #include "ZMEMORY_g.acs" +$export_common #include "ZMEMORY_w.acs" //Simple linked list implementation of malloc -global int 63:memory[]; +//$export_common global int 63:gmemory[]; +//$export_common world int 255:wmemory[]; + +$export_option +global int 63:gmemory[]; +$ +world int 255:wmemory[]; +$ + +$export_common #libdefine nullptr 0 + +$export_common //#define nullptr 0 -#libdefine nullptr 0 +$export_common #define malloc_allocated 0 +$export_common #define malloc_size 1 +$export_common #define malloc_next_header 2 +$export_common #define malloc_prev_header 3 +$export_common #define malloc_num_header_properties 4 -#define malloc_allocated 0 -#define malloc_size 1 -#define malloc_next_header 2 -#define malloc_prev_header 3 -#define malloc_num_header_properties 4 +$export_common #define p_malloc_init_flag_location 0 +$export_common #define p_malloc_first_header_location 1 -#define p_malloc_init_flag_location 0 -#define p_malloc_first_header_location 1 +$$export_split +//[Z] The reason I do it like this is because whoever made the acc is insane. +#define @nullptr 0 -function int malloc (int size) { - log(s:"Invoked malloc"); +#define @malloc_allocated 0 +#define @malloc_size 1 +#define @malloc_next_header 2 +#define @malloc_prev_header 3 +#define @malloc_num_header_properties 4 + +#define @p_malloc_init_flag_location 0 +#define @p_malloc_first_header_location 1 +$$ + +$$export_split function int @malloc (int size) { //Do the setup on the first run of this function. - if(memory[p_malloc_init_flag_location] == FALSE) { //Default values for global values is 0, so this is true. - memory[p_malloc_init_flag_location] = TRUE; - memory[p_malloc_first_header_location+malloc_allocated] = FALSE; - memory[p_malloc_first_header_location+malloc_size] = -1; //"infinite" - memory[p_malloc_first_header_location+malloc_next_header] = nullptr; //nullptr - memory[p_malloc_first_header_location+malloc_prev_header] = nullptr; //nullptr + if(@memory[@p_malloc_init_flag_location] == FALSE) { //Default values for global values is 0, so this is true. + @memory[@p_malloc_init_flag_location] = TRUE; + @memory[@p_malloc_first_header_location+@malloc_allocated] = FALSE; + @memory[@p_malloc_first_header_location+@malloc_size] = -1; //"infinite" + @memory[@p_malloc_first_header_location+@malloc_next_header] = @nullptr; //nullptr + @memory[@p_malloc_first_header_location+@malloc_prev_header] = @nullptr; //nullptr } - int p_previous_header = nullptr; - int p_current_header = p_malloc_first_header_location; - int p_retval = nullptr; + int p_previous_header = @nullptr; + int p_current_header = @p_malloc_first_header_location; + int p_retval = @nullptr; - while(p_retval == nullptr) { - int memalloced = memory[p_current_header+malloc_allocated]; - int memsize = memory[p_current_header+malloc_size]; + while(p_retval == @nullptr) { + int memalloced = @memory[p_current_header+@malloc_allocated]; + int memsize = @memory[p_current_header+@malloc_size]; if(memsize == -1) { //The end of the list. - memory[p_current_header+malloc_allocated] = TRUE; - memory[p_current_header+malloc_size] = size; - memory[p_current_header+malloc_next_header] = p_current_header+malloc_num_header_properties+size; //New EOL - memory[p_current_header+malloc_prev_header] = p_previous_header; + @memory[p_current_header+@malloc_allocated] = TRUE; + @memory[p_current_header+@malloc_size] = size; + @memory[p_current_header+@malloc_next_header] = p_current_header+@malloc_num_header_properties+size; //New EOL + @memory[p_current_header+@malloc_prev_header] = p_previous_header; //Retrieve the return value while we are at the allocated space. - p_retval = p_current_header+malloc_num_header_properties; + p_retval = p_current_header+@malloc_num_header_properties; //Remember to initialize the new end list node. p_previous_header = p_current_header; //This is the header previous to the EOL. - p_current_header = memory[p_current_header+malloc_next_header]; + p_current_header = @memory[p_current_header+@malloc_next_header]; //Set the tail node constants. - memory[p_current_header+malloc_allocated] = FALSE; - memory[p_current_header+malloc_size] = -1; - memory[p_current_header+malloc_next_header] = nullptr; - memory[p_current_header+malloc_prev_header] = p_previous_header; + @memory[p_current_header+@malloc_allocated] = FALSE; + @memory[p_current_header+@malloc_size] = -1; + @memory[p_current_header+@malloc_next_header] = @nullptr; + @memory[p_current_header+@malloc_prev_header] = p_previous_header; } else if(memsize >= size && memalloced == FALSE) { //There is room here AND it isn't in use, - memory[p_current_header+malloc_allocated] = TRUE; + @memory[p_current_header+@malloc_allocated] = TRUE; //The size isn't modified because we are re-using an existing space. // It would be a good idea to check just how large this space is and act accordingly rather // than using a 500 indexes large space for a 4 indexes large object. // Objects allocated in a doom mod probably won't be outside the 1-16 indexes range so it // should still be fine for most applications. //The next header isn't changed either for the same reason. - if(memsize >= (size+malloc_num_header_properties+5)) { //Assume that 5 is the smallest useful allocation size. - int p_split_newheader = p_current_header+malloc_num_header_properties+size; //Just to the end of the allocation. - memory[p_split_newheader+malloc_allocated] = FALSE; - memory[p_split_newheader+malloc_size] = memory[p_current_header+malloc_size]-malloc_num_header_properties-size; - memory[p_split_newheader+malloc_next_header] = memory[p_current_header+malloc_next_header]; - memory[p_split_newheader+malloc_prev_header] = p_current_header; - memory[p_current_header+malloc_next_header] = p_split_newheader; //The header whose block was split should have its next pointer set to its other half. - memory[p_current_header+malloc_size] = size; //Set the size of the allocation to reflect the split. + if(memsize >= (size+@malloc_num_header_properties+5)) { //Assume that 5 is the smallest useful allocation size. + int p_split_newheader = p_current_header+@malloc_num_header_properties+size; //Just to the end of the allocation. + @memory[p_split_newheader+@malloc_allocated] = FALSE; + @memory[p_split_newheader+@malloc_size] = @memory[p_current_header+@malloc_size]-@malloc_num_header_properties-size; + @memory[p_split_newheader+@malloc_next_header] = @memory[p_current_header+@malloc_next_header]; + @memory[p_split_newheader+@malloc_prev_header] = p_current_header; + @memory[p_current_header+@malloc_next_header] = p_split_newheader; //The header whose block was split should have its next pointer set to its other half. + @memory[p_current_header+@malloc_size] = size; //Set the size of the allocation to reflect the split. } //Retrieve the return value while we are at the allocated space. - p_retval = p_current_header+malloc_num_header_properties; + p_retval = p_current_header+@malloc_num_header_properties; } else { //The observed node isn't useful for allocating the request. Go to the next node. p_previous_header = p_current_header; - p_current_header = memory[p_current_header+malloc_next_header]; + p_current_header = @memory[p_current_header+@malloc_next_header]; } } - log(s:"Malloc allocated ", d:size, s:" indexes at location ", d:p_retval, s:" with header location ", d:p_current_header); + //log(s:"Malloc allocated ", d:size, s:" indexes at location ", d:p_retval, s:" with header location ", d:p_current_header); return p_retval; } +$$ -function int free (int p_ptr) { +$$export_split function int @free (int p_ptr) { log(s:"Invoked free"); - int p_header = p_ptr - malloc_num_header_properties; + int p_header = p_ptr - @malloc_num_header_properties; - memory[p_header+malloc_allocated] = FALSE; + @memory[p_header+@malloc_allocated] = FALSE; - int p_next = memory[p_header+malloc_next_header]; - int p_prev = memory[p_header+malloc_prev_header]; + int p_next = @memory[p_header+@malloc_next_header]; + int p_prev = @memory[p_header+@malloc_prev_header]; //Below is the merging of free blocks. //It merges to the left (lower indexes) first becaue the right (larger // indexes) has a special case. (the end of the list) //the previous block is unused. Merge. - if(p_prev != nullptr //This doesn't make sense if the previous block doesn't exist. - && memory[p_prev+malloc_allocated] == FALSE) { + if(p_prev != @nullptr //This doesn't make sense if the previous block doesn't exist. + && @memory[p_prev+@malloc_allocated] == FALSE) { log(s:"Free attempting merge of header ", d:p_header, s: " to the left with header ", d:p_prev); - memory[p_prev+malloc_size] += memory[p_header+malloc_size] + malloc_num_header_properties; - memory[p_prev+malloc_next_header] = p_next; //The prev header needs to know the new next. - memory[p_next+malloc_prev_header] = p_prev; //The next header needs to know the new prev. + @memory[p_prev+@malloc_size] += @memory[p_header+@malloc_size] + @malloc_num_header_properties; + @memory[p_prev+@malloc_next_header] = p_next; //The prev header needs to know the new next. + @memory[p_next+@malloc_prev_header] = p_prev; //The next header needs to know the new prev. //Now the two blocks are the same block. requires new initializations of the // variables for the other check to function correctly. //The header is the result of the merge, and the prev is the one before it. p_header = p_prev; - p_prev = memory[p_header+malloc_prev_header]; + p_prev = @memory[p_header+@malloc_prev_header]; } //The next block is unused. Merge. //Note that p_next will never be a nullptr with correct usage. - if(memory[p_next+malloc_allocated] == FALSE) { - if(memory[p_next+malloc_size] == -1) { //EOL - memory[p_header+malloc_size] = -1; - memory[p_header+malloc_next_header] = nullptr; + if(@memory[p_next+@malloc_allocated] == FALSE) { + if(@memory[p_next+@malloc_size] == -1) { //EOL + @memory[p_header+@malloc_size] = -1; + @memory[p_header+@malloc_next_header] = @nullptr; } else { - int p_next_next = memory[p_next+malloc_next_header]; - memory[p_header+malloc_size] += memory[p_next+malloc_size] + malloc_num_header_properties; - memory[p_header+malloc_next_header] = p_next_next; //The header on the other side of the next header needs to know its new prev. - memory[p_next_next+malloc_prev_header] = p_header; //This header needs to know its new next. + int p_next_next = @memory[p_next+@malloc_next_header]; + @memory[p_header+@malloc_size] += @memory[p_next+@malloc_size] + @malloc_num_header_properties; + @memory[p_header+@malloc_next_header] = p_next_next; //The header on the other side of the next header needs to know its new prev. + @memory[p_next_next+@malloc_prev_header] = p_header; //This header needs to know its new next. } } return -1; } +$$ + //These are for debugging +/* script "memory_write" (int index, int value) { memory[index] = value; } @@ -154,3 +185,5 @@ script "memory_print_allocation_list" (void) { p_current_header = memory[p_current_header+malloc_next_header]; } } +*/ + diff --git a/src/acs_source/compile.sh b/src/acs_source/compile.sh deleted file mode 100644 index 6e0182c..0000000 --- a/src/acs_source/compile.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -acc -i $ACC_ZCOMMON_PATH ZMEMORY.acs ../acs/ZMEMORY.o - -