From 6012208c61e616a5d31d285ba8873f55b987bf70 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 25 May 2022 21:56:39 -0500 Subject: [PATCH] Bugfix: IKI variable substitution in fake doesn't always expand properly. The commit 85738c3aed3949cc3f26b33e39d28b69dcc6d571 didn't fully solve the problem. One problem is a copy & paste mistake in the declaration of fake_make_parameter_variable_option_build_s where the wrong define is used. Make sure to conditionally allocate the arguments array before operating on the "used" position. The used_content variable should not be needed because the arguments.used should be 0. After conditional allocation, ensure that the arguments.used is 0 before operation and remove the no longer needed used_content. When the reserved IKI variables that represent program parameters are used and exist in isolation for their argument, then they should expand as separate variables. Consider these four examples: print 1 parameter:"build" print 2 parameter:"build". print 3 "parameter:"build"" print 4 "parameter:"build\" between parameter:"build"" Lets say fake is called with the following "fake make -b /tmp/". The "print 1" example would have the following parameters: 1) 1 2) -b 3) /tmp/ The "print 2" example would have the following parameters: 1) 2 2) -b /tmp/. The "print 3" example would have the following parameters: 1) 3 2) -b /tmp/ The "print 4" example would have the following parameters: 1) 3 2) -b /tmp/ between -b /tmp/ The "print 1" expands into 3 parameters because the IKI variable is by itself for that given argument. The "print 2" expands into 2 parameters because the IKI variable is not by itself for the given argument (It has a period '.' at the end). The "print 3" expands into 2 parameters because it is quoted and is treated as a single argument. The "print 4" expands into 2 parameters because it is quoted and is treated as a single argument and the "between" should still be between the two substitutions. A break is added at the end of one of the loops because that part of the loop is only reached after a match. When a match is identified, the loop no longer needs further iterations. --- level_3/fake/c/private-common.c | 2 +- level_3/fake/c/private-make-operate.c | 175 ++++++++++++++++++++++------------ 2 files changed, 115 insertions(+), 62 deletions(-) diff --git a/level_3/fake/c/private-common.c b/level_3/fake/c/private-common.c index 863e7ca..6275c88 100644 --- a/level_3/fake/c/private-common.c +++ b/level_3/fake/c/private-common.c @@ -260,7 +260,7 @@ extern "C" { const f_string_static_t fake_make_parameter_variable_verbosity_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_verbosity_s, 0, FAKE_make_parameter_variable_verbosity_s_length); const f_string_static_t fake_make_parameter_variable_work_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_work_s, 0, FAKE_make_parameter_variable_work_s_length); - const f_string_static_t fake_make_parameter_variable_option_build_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_build_s, 0, FAKE_make_parameter_variable_build_s_length); + const f_string_static_t fake_make_parameter_variable_option_build_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_option_build_s, 0, FAKE_make_parameter_variable_option_build_s_length); const f_string_static_t fake_make_parameter_variable_option_color_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_option_color_s, 0, FAKE_make_parameter_variable_option_color_s_length); const f_string_static_t fake_make_parameter_variable_option_data_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_option_data_s, 0, FAKE_make_parameter_variable_option_data_s_length); const f_string_static_t fake_make_parameter_variable_option_define_s = macro_f_string_static_t_initialize(FAKE_make_parameter_variable_option_define_s, 0, FAKE_make_parameter_variable_option_define_s_length); diff --git a/level_3/fake/c/private-make-operate.c b/level_3/fake/c/private-make-operate.c index 40b0f39..2c1f624 100644 --- a/level_3/fake/c/private-make-operate.c +++ b/level_3/fake/c/private-make-operate.c @@ -182,8 +182,6 @@ extern "C" { f_array_length_t k = 0; f_array_length_t l = 0; - f_array_length_t used_content = 0; - const f_string_static_t reserved_name[] = { fake_make_parameter_variable_build_s, fake_make_parameter_variable_color_s, @@ -260,9 +258,16 @@ extern "C" { // Skip content that is unused, but quoted content, even if empty, should remain. if (content.array[i].start > content.array[i].stop) { - if (quotes.array[i]) { - ++arguments->used; + *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); + + break; + } + + arguments->array[arguments->used++].used = 0; } continue; @@ -285,8 +290,15 @@ extern "C" { data_make->buffer.string[iki_data.delimits.array[j]] = f_iki_syntax_placeholder_s.string[0]; } // for + *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); + + break; + } + if (iki_data.variable.used) { - used_content = arguments->array[arguments->used].used; // Copy everything up to the start of the first IKI variable. if (iki_data.variable.array[0].start && content.array[i].start < iki_data.variable.array[0].start) { @@ -367,104 +379,128 @@ extern "C" { unmatched = F_false; - *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); + // Unquoted IKI content that are reserved words and entirely represent a single parameter should expand into separate parameters. + if (content.array[i].start == iki_data.variable.array[0].start && content.array[i].stop == iki_data.variable.array[0].stop && !quotes.array[i]) { + *status = f_string_dynamics_increase_by(reserved_value[k]->used, arguments); - if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); - break; - } + break; + } - for (l = 0; l < reserved_value[k]->used; ++l) { + for (l = 0; l < reserved_value[k]->used; ++l) { - if (!reserved_value[k]->array[l].used) continue; + if (!reserved_value[k]->array[l].used) continue; - if (l) { - *status = f_string_dynamic_append(f_string_space_s, &arguments->array[arguments->used]); + arguments->array[arguments->used].used = 0; + + *status = f_string_dynamic_append_nulless(reserved_value[k]->array[l], &arguments->array[arguments->used]); if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } - } - *status = f_string_dynamic_append_nulless(reserved_value[k]->array[l], &arguments->array[arguments->used]); + ++arguments->used; + } // for + } + else { + *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); break; } - } // for - if (F_status_is_error(*status) || !unmatched) break; + for (l = 0; l < reserved_value[k]->used; ++l) { + + if (!reserved_value[k]->array[l].used) continue; + + if (l) { + *status = f_string_dynamic_append(f_string_space_s, &arguments->array[arguments->used]); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + + break; + } + } + + *status = f_string_dynamic_append_nulless(reserved_value[k]->array[l], &arguments->array[arguments->used]); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + + break; + } + } // for + } + + break; } // for if (F_status_is_error(*status)) break; } - if (unmatched && parameter->used) { + if (unmatched && F_status_is_error_not(*status)) { for (k = 0; k < parameter->used; ++k) { // Check against IKI variable list. - *status = fl_string_dynamic_partial_compare_dynamic(parameter->array[k].name, data_make->buffer, iki_data.content.array[j]); - - if (*status == F_equal_to) { - unmatched = F_false; - - if (parameter->array[k].value.used) { - if (quotes.array[i]) { - for (l = 0; l < parameter->array[k].value.used; ++l) { + if (fl_string_dynamic_partial_compare_dynamic(parameter->array[k].name, data_make->buffer, iki_data.content.array[j]) != F_equal_to) { + continue; + } - if (l > 0) { - *status = f_string_dynamic_append(f_string_space_s, &arguments->array[arguments->used]); + unmatched = F_false; - if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + if (parameter->array[k].value.used) { + if (quotes.array[i]) { + for (l = 0; l < parameter->array[k].value.used; ++l) { - break; - } - } - - *status = f_string_dynamic_append_nulless(parameter->array[k].value.array[l], &arguments->array[arguments->used]); + if (l > 0) { + *status = f_string_dynamic_append(f_string_space_s, &arguments->array[arguments->used]); if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); break; } - } // for - } - else { - *status = f_string_dynamics_increase_by(fake_default_allocation_small_d, arguments); + } + + *status = f_string_dynamic_append_nulless(parameter->array[k].value.array[l], &arguments->array[arguments->used]); if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } + } // for + } + else { + *status = f_string_dynamics_increase_by(fake_default_allocation_small_d, arguments); - for (l = 0; l < parameter->array[k].value.used; ++l) { + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); - *status = f_string_dynamic_append_nulless(parameter->array[k].value.array[l], &arguments->array[arguments->used]); + break; + } - if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + for (l = 0; l < parameter->array[k].value.used; ++l) { - break; - } - } // for - } - } + *status = f_string_dynamic_append_nulless(parameter->array[k].value.array[l], &arguments->array[arguments->used]); - break; - } - else if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "fl_string_dynamic_compare", F_true); + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); - break; + break; + } + } // for + } } + + break; } // for } @@ -499,9 +535,17 @@ extern "C" { } } - // Make sure to copy and content between multiple IKI variables within the same content. + // Make sure to copy content between multiple IKI variables within the same content. if (j + 1 < iki_data.variable.used) { if (iki_data.variable.array[j].stop + 1 < iki_data.variable.array[j + 1].start && iki_data.variable.array[j + 1].stop <= content.array[i].stop) { + *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); + + break; + } + range.start = iki_data.variable.array[j].stop + 1; range.stop = iki_data.variable.array[j + 1].start - 1; @@ -516,8 +560,18 @@ extern "C" { } } // for + if (F_status_is_error(*status)) break; + // Copy everything after the last IKI variable to the end of the content. if (iki_data.variable.used && content.array[i].stop > iki_data.variable.array[iki_data.variable.used - 1].stop) { + *status = f_string_dynamics_increase(fake_default_allocation_small_d, arguments); + + if (F_status_is_error(*status)) { + fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase", F_true); + + break; + } + range.start = iki_data.variable.array[iki_data.variable.used - 1].stop + 1; range.stop = content.array[i].stop; @@ -530,8 +584,7 @@ extern "C" { } } - // Unquoted empty Content after IKI variable substitution are not used as an argument. - if (used_content < arguments->array[arguments->used].used || quotes.array[i]) { + if (!(content.array[i].start == iki_data.variable.array[0].start && content.array[i].stop == iki_data.variable.array[0].stop && !quotes.array[i])) { ++arguments->used; } } -- 1.8.3.1