/* * Mr. 4th Dimention - Allen Webster * * 16.03.2018 * * Converter for *.4is -> *.4id * */ // TOP #include "4ed_defines.h" #include "4coder_lib/4coder_string.h" #include "4coder_lib/4coder_mem.h" #include "4coder_file.h" #include //////////////////////////////// global char hot_directory_space[4096]; global String hot_directory = {hot_directory_space, 0, sizeof(hot_directory_space)}; internal void init_hot_directory(char *dir){ copy(&hot_directory, dir); replace_char(&hot_directory, '\\', '/'); if (hot_directory.str[hot_directory.size - 1] != '/'){ append(&hot_directory, "/"); } } internal void set_hot_directory(String str){ copy(&hot_directory, str); } internal void set_hot_directory(char *str){ copy(&hot_directory, str); } internal void push_folder_hot_directory(String str){ append(&hot_directory, str); append(&hot_directory, "/"); } internal void push_folder_hot_directory(char *str){ append(&hot_directory, str); append(&hot_directory, "/"); } internal void pop_folder_hot_directory(void){ remove_last_folder(&hot_directory); } internal String get_hot_directory(Partition *part){ String hot; hot.str = push_array(part, char, hot_directory.size); hot.size = hot_directory.size; hot.memory_size = hot_directory.size; memcpy(hot.str, hot_directory.str, hot_directory.size); return(hot); } internal FILE* fopen_hot_directory(Partition *scratch, char *file_name, char *flags){ Temp_Memory temp = begin_temp_memory(scratch); char *full_name = push_array(scratch, char, hot_directory.size); memcpy(full_name, hot_directory.str, hot_directory.size); i32 file_name_length = str_size(file_name); char *full_name_file_portion = push_array(scratch, char, file_name_length); memcpy(full_name_file_portion, file_name, file_name_length); char *terminator = push_array(scratch, char, 1); *terminator = 0; FILE *result = fopen(full_name, flags); end_temp_memory(temp); return(result); } //////////////////////////////// struct Test_Node{ Test_Node *next; String name; }; struct Test_List{ Partition *part; Test_Node *first; Test_Node *last; i32 count; }; #define zdll_push(f,l,cptr,n) (((f) == 0)?((f) = (l) = (n)):((l)->next = (n), (l) = (n))), (*(cptr)) += 1 internal void push_test(Test_List *list, String name){ Test_Node *node = push_array(list->part, Test_Node, 1); node->name = make_string_cap(push_array(list->part, char, name.size), 0, name.size); push_align(list->part, 8); copy(&node->name, name); zdll_push(list->first, list->last, &list->count, node); } internal void push_test(Test_List *list, char *name){ push_test(list, make_string_slowly(name)); } //////////////////////////////// global String code_root; global String script_root; global String sample_root; typedef u32 Generate_Flag; enum{ GenFlag_RebuildSamples = 1, GenFlag_RebuildScripts = 2, GenFlag_OutputTestNames = 4, }; enum{ GenFlag_DoAll = GenFlag_RebuildSamples|GenFlag_RebuildScripts|GenFlag_OutputTestNames, }; #define DoSamples(f) (((f) & GenFlag_RebuildSamples) != 0) #define DoScripts(f) (((f) & GenFlag_RebuildScripts) != 0) #define DoTestNames(f) (((f) & GenFlag_OutputTestNames) != 0) internal void print_usage(char *name){ fprintf(stdout, "usage: %s code-root-directory\n", name); } internal FILE* try_open_output(Partition *scratch, char *name){ FILE *out = fopen_hot_directory(scratch, name, "wb"); if (out == 0){ fprintf(stdout, "Could not open output file %s\n", name); } return(out); } internal void generate_run_script(Partition *scratch, Test_List list){ Temp_Memory temp = begin_temp_memory(scratch); set_hot_directory(code_root); FILE *out = try_open_output(scratch, "run_regression_tests.bat"); if (out != 0){ fprintf(out, "@echo off\n" "pushd ..\\4coder-non-source\\test_data\n" "set run_path=%%cd%%\\sample_files\n" "set data_path=%%cd%%\\input_data\n" "popd\n" "pushd ..\\build\n" "set build=%%cd%%\n" "popd\n" "pushd %%run_path%%\n"); for (Test_Node *node = list.first; node != 0; node = node->next){ fprintf(out, "%%build%%\\4ed -T %%data_path%%\\%.*s\n", node->name.size, node->name.str); } fprintf(out, "popd\n"); fclose(out); } end_temp_memory(temp); } internal void write_open_test_file_default_bindings(FILE *out, char *src_name, char *dst_name){ fprintf(out, "key o MDFR_CTRL\n" "type 1 %s\n" "key key_newline MDFR_NONE\n" "key o MDFR_CTRL\n" "key key_back MDFR_NONE\n" "type 1 output/\n" "key key_esc MDFR_NONE\n" "key s MDFR_ALT\n" "type 1 %s\n" "key key_newline MDFR_NONE\n", src_name, dst_name); } internal String generate_token_test_sample_file(Partition *part, i32 index, i32 token_target, Generate_Flag flags){ i32 name_cap = 512; String sample_name = make_string_cap(push_array(part, char, name_cap), 0, name_cap); append(&sample_name, "gentokentest"); append_int_to_str(&sample_name, index + 1); append(&sample_name, ".cpp"); bool32 string_build_success = terminate_with_null(&sample_name); Assert(string_build_success); set_hot_directory(sample_root); if (DoSamples(flags)){ FILE *out = try_open_output(part, sample_name.str); if (out != 0){ fprintf(out, "int foo(){\n" "\n"); i32 token_count = 6; Assert(token_count < token_target); for (;token_count + 10 < token_target;){ fprintf(out, "int x = 0;\n"); token_count += 5; } Assert(token_count < token_target); fprintf(out, "}\n"); fclose(out); } else{ sample_name.str = 0; sample_name.size = 0; sample_name.memory_size = 0; } } return(sample_name); } internal void generate_token_tests(Partition *scratch, Test_List *test_list, Generate_Flag flags){ Temp_Memory temp = begin_temp_memory(scratch); for (i32 size = 1024, i = 0; i < 5; size <<= 1, ++i){ char test_name_space[512]; String test_name = make_fixed_width_string(test_name_space); append(&test_name, "gentest_capstress"); append_int_to_str(&test_name, i + 1); append(&test_name, ".4is"); bool32 string_build_success = terminate_with_null(&test_name); Assert(string_build_success); String sample_name = generate_token_test_sample_file(scratch, i, size, flags); if (sample_name.str != 0){ set_hot_directory(script_root); if (DoScripts(flags)){ FILE *out = try_open_output(scratch, test_name.str); if (out != 0){ fprintf(out, "mouse_xy 20 20\n" "key P MDFR_CTRL\n" "basewait 1\n"); write_open_test_file_default_bindings(out, sample_name.str, sample_name.str); fprintf(out, "key key_down MDFR_CTRL\n"); for (i32 i = 0; i < 5; ++i){ fprintf(out, "type 1 int x = 0;\n" "key key_newline MDFR_NONE\n"); } fprintf(out, "key s MDFR_CTRL\n" "exit\n" "key Y MDFR_NONE"); fclose(out); } } if (DoTestNames(flags)){ remove_extension(&test_name); append(&test_name, "4id"); bool32 string_build_success = terminate_with_null(&test_name); Assert(string_build_success); push_test(test_list, test_name); } } } end_temp_memory(temp); } internal String generate_dupline_test_sample_file(Partition *part, i32 line_count, bool32 always_newline, Generate_Flag flags){ i32 name_cap = 512; String sample_name = make_string_cap(push_array(part, char, name_cap), 0, name_cap); append(&sample_name, "genduplinetest"); append_int_to_str(&sample_name, line_count); append(&sample_name, "_"); append_int_to_str(&sample_name, always_newline); append(&sample_name, ".cpp"); bool32 string_build_success = terminate_with_null(&sample_name); Assert(string_build_success); if (DoSamples(flags)){ set_hot_directory(sample_root); FILE *out = try_open_output(part, sample_name.str); if (out != 0){ for (i32 i = 0; i < line_count; ++i){ fprintf(out, "abcd"); if (i + 1 < line_count || always_newline){ fprintf(out, "\n"); } } fclose(out); } } return(sample_name); } internal void generate_dupline_specific_test(Partition *scratch, Test_List *test_list, Generate_Flag flags, i32 line_count, bool32 always_newline, bool32 read_only){ char test_name_space[512]; String test_name = make_fixed_width_string(test_name_space); if (read_only){ append(&test_name, "gentest_dupline_readonly.4is"); } else{ append(&test_name, "gentest_dupline"); append_int_to_str(&test_name, line_count); append(&test_name, "_"); append_int_to_str(&test_name, always_newline); append(&test_name, ".4is"); } bool32 string_build_success = terminate_with_null(&test_name); Assert(string_build_success); String sample_name; if (read_only){ sample_name = make_lit_string("*messages*"); } else{ sample_name = generate_dupline_test_sample_file(scratch, line_count, always_newline, flags); } if (sample_name.str != 0){ set_hot_directory(script_root); if (DoScripts(flags)){ FILE *out = try_open_output(scratch, test_name.str); if (out != 0){ fprintf(out, "mouse_xy 20 20\n" "key P MDFR_CTRL\n" "basewait 1\n"); if (read_only){ fprintf(out, "key i MDFR_CTRL\n" "type 1 *messages*\n" "key key_newline MDFR_NONE\n" "key L MDFR_CTRL\n" "key s MDFR_CTRL\n" "exit\n"); } else{ write_open_test_file_default_bindings(out, sample_name.str, sample_name.str); fprintf(out, "key L MDFR_CTRL\n" "key s MDFR_CTRL\n" "exit\n"); } fclose(out); } } if (DoTestNames(flags)){ remove_extension(&test_name); append(&test_name, "4id"); bool32 string_build_success = terminate_with_null(&test_name); Assert(string_build_success); push_test(test_list, test_name); } } } internal void generate_dupline_tests(Partition *scratch, Test_List *test_list, Generate_Flag flags){ Temp_Memory temp = begin_temp_memory(scratch); for (i32 line_count = 0; line_count < 2; ++line_count){ for (bool32 always_newline = 0; always_newline <= 1; ++always_newline){ generate_dupline_specific_test(scratch, test_list, flags, line_count, always_newline, false); } } generate_dupline_specific_test(scratch, test_list, flags, 0, false, true); end_temp_memory(temp); } int main(int argc, char **argv){ if (argc != 2){ print_usage(argv[0]); exit(1); } // NOTE(allen): Init the hot directory init_hot_directory(argv[1]); // NOTE(allen): Init the partition i32 memory_size = MB(8); Partition part_ = make_part(malloc(memory_size), memory_size); Partition *part = &part_; // NOTE(allen): Get various root paths code_root = get_hot_directory(part); push_folder_hot_directory("test_input_scripts/generated"); script_root = get_hot_directory(part); set_hot_directory(code_root); pop_folder_hot_directory(); push_folder_hot_directory("4coder-non-source/test_data/sample_files"); sample_root = get_hot_directory(part); // NOTE(allen): Setup the test list i32 test_list_size = MB(8); Partition test_list_part = make_part(malloc(test_list_size), test_list_size); Test_List test_list = {0}; test_list.part = &test_list_part; // NOTE(allen): Tests //push_test(&test_list, "test_load_FONT_COURIER_NEW_28_c.4id"); push_test(&test_list, "test_load_rome_txt.4id"); //generate_token_tests(part, &test_list, GenFlag_DoAll); //generate_token_tests(part, &test_list, GenFlag_OutputTestNames); //generate_dupline_tests(part, &test_list, GenFlag_DoAll); //generate_dupline_tests(part, &test_list, GenFlag_OutputTestNames); // NOTE(allen): Generate the run test script generate_run_script(part, test_list); return(0); } // BOTTOM