diff --git a/src/b.rs b/src/b.rs index 746b8796..0193e3da 100644 --- a/src/b.rs +++ b/src/b.rs @@ -1190,13 +1190,13 @@ pub unsafe fn get_garbage_base(path: *const c_char, target: Target) -> Option<*m write_entire_file(gitignore_path, c!("*") as *const c_void, 1)?; } - Some(temp_sprintf(c!("%s/%s.%s"), garbage_dir, filename, target.api.name)) + Some(temp_sprintf(c!("%s/%s.%s"), garbage_dir, filename, target.api.name())) } pub unsafe fn print_available_targets(targets: *const [Target]) { fprintf(stderr(), c!("Compilation targets:\n")); for i in 0..targets.len() { - fprintf(stderr(), c!(" %s\n"), (*targets)[i].api.name); + fprintf(stderr(), c!(" %s\n"), (*targets)[i].api.name()); } } @@ -1218,7 +1218,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> { } let default_target_name = if let Some(default_target) = default_target { - default_target.api.name + default_target.api.name() } else { ptr::null() }; @@ -1302,7 +1302,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> { log(Log_Level::WARNING, c!("Flag -%s is DEPRECATED! Interpreting it as `-%s %s` instead."), flag_name(linker), PARAM_FLAG_NAME, codegen_arg); } - let gen = (target.api.new)(&mut c.arena, da_slice(*codegen_args))?; + let gen = target.new(&mut c.arena, da_slice(*codegen_args))?; if input_paths.count == 0 { usage(); @@ -1379,12 +1379,12 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> { } let program_path = if (*output_path).is_null() { - temp_sprintf(c!("%s%s"), temp_strip_file_ext(*input_paths.items), target.api.file_ext) + temp_sprintf(c!("%s%s"), temp_strip_file_ext(*input_paths.items), target.file_ext()) } else { if get_file_ext(*output_path).is_some() { *output_path } else { - temp_sprintf(c!("%s%s"), *output_path, target.api.file_ext) + temp_sprintf(c!("%s%s"), *output_path, target.file_ext()) } }; @@ -1403,11 +1403,11 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> { let garbage_base = get_garbage_base(program_path, target)?; if !*nobuild { - (target.api.build)(gen, &c.program, program_path, garbage_base, *nostdlib, *debug)?; + target.build(gen, &c.program, program_path, garbage_base, *nostdlib, *debug)?; } if *run { - (target.api.run)(gen, program_path, da_slice(run_args))? + target.run(gen, program_path, da_slice(run_args))? } Some(()) diff --git a/src/btest.rs b/src/btest.rs index c2d28357..e05b5c0b 100644 --- a/src/btest.rs +++ b/src/btest.rs @@ -134,8 +134,8 @@ pub unsafe fn execute_test( ) -> Option { // TODO: add timeouts for running and building in case they go into infinite loop or something let input_path = temp_sprintf(c!("%s/%s.b"), test_folder, name); - let program_path = temp_sprintf(c!("%s/%s.%s%s"), GARBAGE_FOLDER, name, target.api.name, target.api.file_ext); - let stdout_path = temp_sprintf(c!("%s/%s.%s.stdout.txt"), GARBAGE_FOLDER, name, target.api.name); + let program_path = temp_sprintf(c!("%s/%s.%s%s"), GARBAGE_FOLDER, name, target.api.name(), target.file_ext()); + let stdout_path = temp_sprintf(c!("%s/%s.%s.stdout.txt"), GARBAGE_FOLDER, name, target.api.name()); cmd_append! { cmd, if cfg!(target_os = "windows") { @@ -144,7 +144,7 @@ pub unsafe fn execute_test( c!("./build/b") }, input_path, - c!("-t"), target.api.name, + c!("-t"), target.api.name(), c!("-o"), program_path, } if quiet { @@ -162,14 +162,14 @@ pub unsafe fn execute_test( c!("./build/b") }, input_path, - c!("-t"), target.api.name, + c!("-t"), target.api.name(), c!("-o"), program_path, c!("-q"), c!("-nobuild"), c!("-run"), } // Hack for Uxn - if strcmp(target.api.name, c!("uxn")) == 0 { + if strcmp(target.api.name(), c!("uxn")) == 0 { cmd_append!(cmd, c!("-C"), c!("runner=uxncli")); } let mut fdout = fd_open_for_write(stdout_path); @@ -235,7 +235,7 @@ pub unsafe fn print_top_labels(targets: *const [Target], stats_by_target: *const printf(c!("│ ")); } // TODO: these fancy unicode characters don't work well on mingw32 build via wine - printf(c!("┌─%-*s"), col_width - 2*j, target.api.name); + printf(c!("┌─%-*s"), col_width - 2*j, target.api.name()); print_report_stats(stats) } } @@ -249,7 +249,7 @@ pub unsafe fn print_bottom_labels(targets: *const [Target], stats_by_target: *co for _ in 0..j { printf(c!("│ ")); } - printf(c!("└─%-*s"), col_width - 2*j, target.api.name); + printf(c!("└─%-*s"), col_width - 2*j, target.api.name()); print_report_stats(stats) } } @@ -383,7 +383,7 @@ pub unsafe fn generate_report(reports: *const [Report], stats_by_target: *const let mut col_width = 0; for j in 0..targets.len() { let target = (*targets)[j]; - let width = 2*(j + 1) + strlen(target.api.name); + let width = 2*(j + 1) + strlen(target.api.name()); col_width = cmp::max(col_width, width); } @@ -423,7 +423,7 @@ type TestTable = Array; pub unsafe fn test_table_find_row(tt: *mut TestTable, case_name: *const c_char, target: Target) -> Option<*mut TestRow> { for i in 0..(*tt).count { let row = (*tt).items.add(i); - if strcmp((*row).target.api.name, target.api.name) == 0 && strcmp((*row).case_name, case_name) == 0 { + if strcmp((*row).target.api.name(), target.api.name()) == 0 && strcmp((*row).case_name, case_name) == 0 { return Some(row) } } @@ -516,7 +516,7 @@ pub unsafe fn load_tt_from_json_file_if_exists( // TODO: report the location of existing_row here as a NOTE // This requires keeping track of location in TestRow structure. Which requires location tracking capabilities // comparable to lexer.rs but in jim/jimp. - jimp_diagf(jimp, c!("WARNING: Redefinition of the row case `%s`, target `%s`. We are using only the first definition. All the rest are gonna be prunned"), case_name, target.api.name); + jimp_diagf(jimp, c!("WARNING: Redefinition of the row case `%s`, target `%s`. We are using only the first definition. All the rest are gonna be prunned"), case_name, target.api.name()); // TODO: memory leak, we are dropping the whole row here continue 'table; } @@ -524,7 +524,7 @@ pub unsafe fn load_tt_from_json_file_if_exists( let case_path = temp_sprintf(c!("%s/%s.b"), test_folder, case_name); if !file_exists(case_path)? { (*jimp).token_start = saved_point; - jimp_diagf(jimp, c!("WARNING: %s does not exist. Ignoring case `%s`, target `%s` ...\n"), case_path, case_name, target.api.name); + jimp_diagf(jimp, c!("WARNING: %s does not exist. Ignoring case `%s`, target `%s` ...\n"), case_path, case_name, target.api.name()); // TODO: memory leak, we are dropping the whole row here continue 'table; } @@ -559,7 +559,7 @@ pub unsafe fn save_tt_to_json_file( jim_member_key(jim, c!("case")); jim_string(jim, (*row).case_name); jim_member_key(jim, c!("target")); - jim_string(jim, (*row).target.api.name); + jim_string(jim, (*row).target.api.name()); jim_member_key(jim, c!("expected_stdout")); jim_string(jim, (*row).expected_stdout); jim_member_key(jim, c!("state")); @@ -776,7 +776,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> { let pattern = *(*target_flags).items.add(j); for j in 0..all_targets.count { let target = *all_targets.items.add(j); - let name = target.api.name; + let name = target.api.name(); if matches_glob(pattern, name)? { da_append(&mut selected_targets, target); added_anything = true; @@ -794,7 +794,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> { let mut matches_any = false; 'exclude: for j in 0..(*exclude_target_flags).count { let pattern = *(*exclude_target_flags).items.add(j); - if matches_glob(pattern, target.api.name)? { + if matches_glob(pattern, target.api.name())? { matches_any = true; break 'exclude; } @@ -858,7 +858,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> { fprintf(stderr(), c!("Compilation targets:\n")); for i in 0..targets.count { let target = *targets.items.add(i); - fprintf(stderr(), c!(" %s\n"), target.api.name); + fprintf(stderr(), c!(" %s\n"), target.api.name()); } return Some(()); } @@ -913,7 +913,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> { let mut target_width = 0; for j in 0..targets.count { let target = *targets.items.add(j); - target_width = cmp::max(target_width, strlen(target.api.name)); + target_width = cmp::max(target_width, strlen(target.api.name())); } let mut tt = load_tt_from_json_file_if_exists(da_slice(all_targets), json_path, *test_folder, &mut sb, &mut jimp)?; @@ -921,7 +921,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> { let case_name = *cases.items.add(i); for j in 0..targets.count { let target = *targets.items.add(j); - log(Log_Level::INFO, c!("disabling %-*s for %-*s"), case_width, case_name, target_width, target.api.name); + log(Log_Level::INFO, c!("disabling %-*s for %-*s"), case_width, case_name, target_width, target.api.name()); if let Some(row) = test_table_find_row(&mut tt, case_name, target) { (*row).state = TestState::Disabled; if !(*comment).is_null() { diff --git a/src/codegen/gas_aarch64/mod.rs b/src/codegen/gas_aarch64/mod.rs index 33bf3769..99b8020b 100644 --- a/src/codegen/gas_aarch64/mod.rs +++ b/src/codegen/gas_aarch64/mod.rs @@ -505,7 +505,7 @@ struct Gas_AArch64 { } pub unsafe fn get_apis(targets: *mut Array) { - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("gas-aarch64-linux"), file_ext: c!(""), new, @@ -517,7 +517,7 @@ pub unsafe fn get_apis(targets: *mut Array) { }, }); - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("gas-aarch64-darwin"), file_ext: c!(""), new, diff --git a/src/codegen/gas_x86_64/mod.rs b/src/codegen/gas_x86_64/mod.rs index 30617fbe..4d918594 100644 --- a/src/codegen/gas_x86_64/mod.rs +++ b/src/codegen/gas_x86_64/mod.rs @@ -637,7 +637,7 @@ struct Gas_x86_64 { } pub unsafe fn get_apis(targets: *mut Array) { - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("gas-x86_64-linux"), file_ext: c!(""), new, @@ -649,7 +649,7 @@ pub unsafe fn get_apis(targets: *mut Array) { }, }); - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("gas-x86_64-windows"), file_ext: c!(".exe"), new, @@ -661,7 +661,7 @@ pub unsafe fn get_apis(targets: *mut Array) { }, }); - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("gas-x86_64-darwin"), file_ext: c!(""), new, diff --git a/src/codegen/mos6502.rs b/src/codegen/mos6502.rs index 7f0a09d4..859350cd 100644 --- a/src/codegen/mos6502.rs +++ b/src/codegen/mos6502.rs @@ -1557,7 +1557,7 @@ struct Mos6502 { } pub unsafe fn get_apis(targets: *mut Array) { - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("6502-posix"), file_ext: c!(".6502"), new, diff --git a/src/codegen/uxn/mod.rs b/src/codegen/uxn/mod.rs index 82b1f1c9..48995ad9 100644 --- a/src/codegen/uxn/mod.rs +++ b/src/codegen/uxn/mod.rs @@ -165,7 +165,7 @@ struct Uxn { } pub unsafe fn get_apis(targets: *mut Array) { - da_append(targets, TargetAPI { + da_append(targets, TargetAPI::V1 { name: c!("uxn"), file_ext: c!(".rom"), new, diff --git a/src/targets.rs b/src/targets.rs index 2f81445f..e6baa1bd 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -17,12 +17,48 @@ impl Target { pub unsafe fn by_name(targets: *const [Target], name: *const c_char) -> Option { for i in 0..targets.len() { let target = (*targets)[i]; - if strcmp(target.api.name, name) == 0 { + if strcmp(target.name(), name) == 0 { return Some(target); } } None } + pub unsafe fn name(self) -> *const c_char { + self.api.name() + } + pub unsafe fn new(self, a: *mut arena::Arena, args: *const [*const c_char]) -> Option<*mut c_void> { + match self.api { + TargetAPI::V1 { new, .. } => new(a, args) + } + } + pub unsafe fn build ( + self, + gen: *mut c_void, + program: *const Program, + program_path: *const c_char, + garbage_base: *const c_char, + nostdlib: bool, + debug: bool, + ) -> Option<()> { + match self.api { + TargetAPI::V1 { build, .. } => build(gen, program, program_path, garbage_base, nostdlib, debug), + } + } + pub unsafe fn run ( + self, + gen: *mut c_void, + program_path: *const c_char, + run_args: *const [*const c_char], + ) -> Option<()> { + match self.api { + TargetAPI::V1 { run, .. } => run(gen, program_path, run_args), + } + } + pub unsafe fn file_ext(self) -> *const c_char { + match self.api { + TargetAPI::V1 { file_ext, .. } => file_ext, + } + } } pub unsafe fn register_apis(targets: *mut Array, apis: *const [TargetAPI], codegen_name: *const c_char) -> Option<()> { @@ -30,11 +66,11 @@ pub unsafe fn register_apis(targets: *mut Array, apis: *const [TargetAPI let api = (*apis)[i]; for j in 0..(*targets).count { let target = *(*targets).items.add(j); - if strcmp(target.api.name, api.name) == 0 { + if strcmp(target.name(), api.name()) == 0 { if strcmp(target.codegen_name, codegen_name) == 0 { - log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegen %s defines target %s more than once"), codegen_name, api.name); + log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegen %s defines target %s more than once"), codegen_name, api.name()); } else { - log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegens %s and %s define the same target %s"), codegen_name, target.codegen_name, api.name); + log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegens %s and %s define the same target %s"), codegen_name, target.codegen_name, api.name()); } return None; } @@ -45,26 +81,36 @@ pub unsafe fn register_apis(targets: *mut Array, apis: *const [TargetAPI } #[derive(Clone, Copy)] -pub struct TargetAPI { - pub name: *const c_char, - pub file_ext: *const c_char, - pub new: unsafe fn( - a: *mut arena::Arena, - args: *const [*const c_char] - ) -> Option<*mut c_void>, - pub build: unsafe fn( - gen: *mut c_void, - program: *const Program, - program_path: *const c_char, - garbage_base: *const c_char, - nostdlib: bool, - debug: bool, - ) -> Option<()>, - pub run: unsafe fn( - gen: *mut c_void, - program_path: *const c_char, - run_args: *const [*const c_char], - ) -> Option<()>, +pub enum TargetAPI { + V1 { + name: *const c_char, + file_ext: *const c_char, + new: unsafe fn( + a: *mut arena::Arena, + args: *const [*const c_char] + ) -> Option<*mut c_void>, + build: unsafe fn( + gen: *mut c_void, + program: *const Program, + program_path: *const c_char, + garbage_base: *const c_char, + nostdlib: bool, + debug: bool, + ) -> Option<()>, + run: unsafe fn( + gen: *mut c_void, + program_path: *const c_char, + run_args: *const [*const c_char], + ) -> Option<()>, + } +} + +impl TargetAPI { + pub unsafe fn name(self) -> *const c_char { + match self { + TargetAPI::V1 { name, .. } => name, + } + } } #[derive(Clone, Copy, PartialEq, Eq)]