From f5e65bbbee191a336f387cbb7163ba249b161d53 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 15 May 2022 16:31:11 -0500 Subject: [PATCH] Feature: The iki_read program should support a more generalized substitution process called "replace". In the distant past I mixed up having only two or three substitution parameters. After getting confused, I decided to just have a 3 argument substitution. The three argument substitution only substitutes if both the variable name and the variable value match. This is great but it doesn't follow the completeness theorem. The iki_read should also handle the general case in addition to the specific case. Provide a two argument substitution called "replace" that handles the more general case. When any variable name matches the given replace parameter, then the variable value is replaced for all matching variable names regardless of the existing variable value. Fix small mistakes in the IKI specification. I needed to refer to the "variable value" with this change and "variable variable" is simply not the correct way. Use "variable names" rather than "object names" to be more consistent and clear in this regard. --- level_3/iki_read/c/common.c | 2 + level_3/iki_read/c/common.h | 12 ++++- level_3/iki_read/c/iki_read.c | 46 ++++++++++++++++++- level_3/iki_read/c/private-print.c | 38 ++++++++++++---- level_3/iki_read/c/private-print.h | 8 ++-- level_3/iki_read/c/private-read.c | 91 ++++++++++++++++++++++++++++++-------- level_3/iki_read/c/private-read.h | 30 ++++++++++++- specifications/iki.txt | 4 +- 8 files changed, 193 insertions(+), 38 deletions(-) diff --git a/level_3/iki_read/c/common.c b/level_3/iki_read/c/common.c index e2283a6..6b31f5f 100644 --- a/level_3/iki_read/c/common.c +++ b/level_3/iki_read/c/common.c @@ -20,6 +20,7 @@ extern "C" { const f_string_static_t iki_read_short_literal_s = macro_f_string_static_t_initialize(IKI_READ_short_literal_s, 0, IKI_READ_short_literal_s_length); const f_string_static_t iki_read_short_name_s = macro_f_string_static_t_initialize(IKI_READ_short_name_s, 0, IKI_READ_short_name_s_length); const f_string_static_t iki_read_short_object_s = macro_f_string_static_t_initialize(IKI_READ_short_object_s, 0, IKI_READ_short_object_s_length); + const f_string_static_t iki_read_short_replace_s = macro_f_string_static_t_initialize(IKI_READ_short_replace_s, 0, IKI_READ_short_replace_s_length); const f_string_static_t iki_read_short_substitute_s = macro_f_string_static_t_initialize(IKI_READ_short_substitute_s, 0, IKI_READ_short_substitute_s_length); const f_string_static_t iki_read_short_total_s = macro_f_string_static_t_initialize(IKI_READ_short_total_s, 0, IKI_READ_short_total_s_length); const f_string_static_t iki_read_short_whole_s = macro_f_string_static_t_initialize(IKI_READ_short_whole_s, 0, IKI_READ_short_whole_s_length); @@ -30,6 +31,7 @@ extern "C" { const f_string_static_t iki_read_long_literal_s = macro_f_string_static_t_initialize(IKI_READ_long_literal_s, 0, IKI_READ_long_literal_s_length); const f_string_static_t iki_read_long_name_s = macro_f_string_static_t_initialize(IKI_READ_long_name_s, 0, IKI_READ_long_name_s_length); const f_string_static_t iki_read_long_object_s = macro_f_string_static_t_initialize(IKI_READ_long_object_s, 0, IKI_READ_long_object_s_length); + const f_string_static_t iki_read_long_replace_s = macro_f_string_static_t_initialize(IKI_READ_long_replace_s, 0, IKI_READ_long_replace_s_length); const f_string_static_t iki_read_long_substitute_s = macro_f_string_static_t_initialize(IKI_READ_long_substitute_s, 0, IKI_READ_long_substitute_s_length); const f_string_static_t iki_read_long_total_s = macro_f_string_static_t_initialize(IKI_READ_long_total_s, 0, IKI_READ_long_total_s_length); const f_string_static_t iki_read_long_whole_s = macro_f_string_static_t_initialize(IKI_READ_long_whole_s, 0, IKI_READ_long_whole_s_length); diff --git a/level_3/iki_read/c/common.h b/level_3/iki_read/c/common.h index 4c8b240..e0d0f2f 100644 --- a/level_3/iki_read/c/common.h +++ b/level_3/iki_read/c/common.h @@ -83,6 +83,7 @@ extern "C" { #define IKI_READ_short_literal_s "L" #define IKI_READ_short_name_s "n" #define IKI_READ_short_object_s "o" + #define IKI_READ_short_replace_s "r" #define IKI_READ_short_substitute_s "s" #define IKI_READ_short_total_s "t" #define IKI_READ_short_whole_s "w" @@ -93,6 +94,7 @@ extern "C" { #define IKI_READ_long_literal_s "literal" #define IKI_READ_long_name_s "name" #define IKI_READ_long_object_s "object" + #define IKI_READ_long_replace_s "replace" #define IKI_READ_long_substitute_s "substitute" #define IKI_READ_long_total_s "total" #define IKI_READ_long_whole_s "whole" @@ -103,6 +105,7 @@ extern "C" { #define IKI_READ_short_literal_s_length 1 #define IKI_READ_short_name_s_length 1 #define IKI_READ_short_object_s_length 1 + #define IKI_READ_short_replace_s_length 1 #define IKI_READ_short_substitute_s_length 1 #define IKI_READ_short_total_s_length 1 #define IKI_READ_short_whole_s_length 1 @@ -112,7 +115,8 @@ extern "C" { #define IKI_READ_long_line_s_length 4 #define IKI_READ_long_literal_s_length 7 #define IKI_READ_long_name_s_length 4 - #define IKI_READ_long_object_s_length 7 + #define IKI_READ_long_object_s_length 6 + #define IKI_READ_long_replace_s_length 7 #define IKI_READ_long_substitute_s_length 10 #define IKI_READ_long_total_s_length 5 #define IKI_READ_long_whole_s_length 5 @@ -123,6 +127,7 @@ extern "C" { extern const f_string_static_t iki_read_short_literal_s; extern const f_string_static_t iki_read_short_name_s; extern const f_string_static_t iki_read_short_object_s; + extern const f_string_static_t iki_read_short_replace_s; extern const f_string_static_t iki_read_short_substitute_s; extern const f_string_static_t iki_read_short_total_s; extern const f_string_static_t iki_read_short_whole_s; @@ -133,6 +138,7 @@ extern "C" { extern const f_string_static_t iki_read_long_literal_s; extern const f_string_static_t iki_read_long_name_s; extern const f_string_static_t iki_read_long_object_s; + extern const f_string_static_t iki_read_long_replace_s; extern const f_string_static_t iki_read_long_substitute_s; extern const f_string_static_t iki_read_long_total_s; extern const f_string_static_t iki_read_long_whole_s; @@ -155,6 +161,7 @@ extern "C" { iki_read_parameter_name_e, iki_read_parameter_object_e, iki_read_parameter_whole_e, + iki_read_parameter_replace_e, iki_read_parameter_substitute_e, iki_read_parameter_total_e, }; @@ -177,11 +184,12 @@ extern "C" { macro_f_console_parameter_t_initialize(iki_read_short_name_s.string, iki_read_long_name_s.string, 0, 1, f_console_type_normal_e), \ macro_f_console_parameter_t_initialize(iki_read_short_object_s.string, iki_read_long_object_s.string, 0, 0, f_console_type_normal_e), \ macro_f_console_parameter_t_initialize(iki_read_short_whole_s.string, iki_read_long_whole_s.string, 0, 0, f_console_type_normal_e), \ + macro_f_console_parameter_t_initialize(iki_read_short_replace_s.string, iki_read_long_replace_s.string, 0, 2, f_console_type_normal_e), \ macro_f_console_parameter_t_initialize(iki_read_short_substitute_s.string, iki_read_long_substitute_s.string, 0, 3, f_console_type_normal_e), \ macro_f_console_parameter_t_initialize(iki_read_short_total_s.string, iki_read_long_total_s.string, 0, 0, f_console_type_normal_e), \ } - #define iki_read_total_parameters_d 18 + #define iki_read_total_parameters_d 19 #endif // _di_iki_read_parameters_ #ifndef _di_iki_read_substitution_t_ diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c index 8d5f755..5c85e3a 100644 --- a/level_3/iki_read/c/iki_read.c +++ b/level_3/iki_read/c/iki_read.c @@ -39,14 +39,24 @@ extern "C" { f_print_dynamic_raw(f_string_eol_s, file.stream); - fll_program_print_help_option(file, context, iki_read_short_substitute_s, iki_read_long_substitute_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Substitute the entire variable for the given name and content value with the given string."); + fll_program_print_help_option(file, context, iki_read_short_replace_s, iki_read_long_replace_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Simple substitution, replacing the variable for the given name with the given string."); + fll_program_print_help_option(file, context, iki_read_short_substitute_s, iki_read_long_substitute_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Substitute the variable for the given name and matching content value with the given string."); fll_program_print_help_usage(file, context, iki_read_program_name_s, fll_program_parameter_filenames_s); fl_print_format(" %[Notes:%]%r", file.stream, context.set.important, context.set.important, f_string_eol_s); fl_print_format(" This program will find and print variables, vocabularies, or content following the IKI standard, without focusing on any particular vocabulary specification.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - fl_print_format(" This %[%r%r%] option, requires 3 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); + fl_print_format(" The %[%r%r%] option requires 2 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); + fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, context.set.notable); + fl_print_format(" %[<%]%r%[>%].%r", file.stream, context.set.notable, context.set.notable, iki_read_substitution_with_s, context.set.notable, context.set.notable, f_string_eol_s); + + fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be substituted.%r", file.stream, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, f_string_eol_s); + fl_print_format(" %[%r%]: The new string to use as the substitute.%r%r", file.stream, context.set.notable, iki_read_substitution_with_s, context.set.notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The vocabulary is case-sensitive and must exactly match.%r%r", file.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] option requires 3 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, context.set.notable); fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_replace_s, context.set.notable, context.set.notable); fl_print_format(" %[<%]%r%[>%].%r", file.stream, context.set.notable, context.set.notable, iki_read_substitution_with_s, context.set.notable, context.set.notable, f_string_eol_s); @@ -57,6 +67,14 @@ extern "C" { fl_print_format(" The vocabulary and replacement are case-sensitive and must exactly match.%r%r", file.stream, f_string_eol_s, f_string_eol_s); + fl_print_format(" The difference between %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); + fl_print_format(" and %[%r%r%] is that the", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); + fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names and the", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); + fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names that must also have the given matching content.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); + fl_print_format(" option takes priority over the %[%r%r%] option when matching the same variable.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" The default behavior is to only display content portion of the IKI variable.%r%r", file.stream, f_string_eol_s, f_string_eol_s); funlockfile(file.stream); @@ -246,6 +264,30 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->parameters.array[iki_read_parameter_replace_e].result != f_console_result_none_e) { + if (main->parameters.array[iki_read_parameter_replace_e].result == f_console_result_found_e || main->parameters.array[iki_read_parameter_replace_e].values.used % 2 != 0) { + if (main->error.verbosity != f_console_verbosity_quiet_e) { + flockfile(main->error.to.stream); + + fl_print_format("%r%[%QThe parameter '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, main->error.notable); + fl_print_format("%[' requires 2 strings.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s); + + funlockfile(main->error.to.stream); + } + + status = F_status_set_error(F_parameter); + } + + if (main->parameters.array[iki_read_parameter_total_e].result == f_console_result_found_e) { + if (main->error.verbosity != f_console_verbosity_quiet_e) { + fll_program_parameter_long_print_cannot_use_with(main->error, iki_read_long_replace_s, iki_read_long_total_s); + } + + status = F_status_set_error(F_parameter); + } + } + if (main->parameters.array[iki_read_parameter_substitute_e].result != f_console_result_none_e) { if (main->parameters.array[iki_read_parameter_substitute_e].result == f_console_result_found_e || main->parameters.array[iki_read_parameter_substitute_e].values.used % 3 != 0) { if (main->error.verbosity != f_console_verbosity_quiet_e) { diff --git a/level_3/iki_read/c/private-print.c b/level_3/iki_read/c/private-print.c index 1dfafea..8c2ffeb 100644 --- a/level_3/iki_read/c/private-print.c +++ b/level_3/iki_read/c/private-print.c @@ -7,27 +7,47 @@ extern "C" { #endif #ifndef _di_iki_read_substitutions_print_ - void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { + void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { - f_status_t status = F_none; - f_array_length_t i = 0; + uint8_t matched = F_false; + f_array_length_t at = 0; - for (; i < substitutions.used; ++i) { + // Grab the last (right-most) match. + for (f_array_length_t i = 0; i < substitutions.used; ++i) { - status = fl_string_dynamic_partial_compare_string(substitutions.array[i].replace.string, data->buffer, substitutions.array[i].replace.used, iki_data.content.array[index]); - if (status == F_equal_to) break; + if (fl_string_dynamic_partial_compare_string(substitutions.array[i].replace.string, data->buffer, substitutions.array[i].replace.used, iki_data.content.array[index]) == F_equal_to) { + matched = F_true; + at = i; + } } // for - if (status == F_equal_to) { + if (matched) { + if (content_only) { + f_print_dynamic(substitutions.array[at].with, data->main->output.to.stream); + } + else { + f_string_range_t range = macro_f_string_range_t_initialize(iki_data.variable.array[index].start, iki_data.content.array[index].start - 1); + + f_print_dynamic_partial(data->buffer, range, data->main->output.to.stream); + + f_print_dynamic(substitutions.array[at].with, data->main->output.to.stream); + + range.start = iki_data.content.array[index].stop + 1; + range.stop = iki_data.variable.array[index].stop; + + f_print_dynamic_partial(data->buffer, range, data->main->output.to.stream); + } + } + else if (replacement.replace.used) { if (content_only) { - f_print_dynamic(substitutions.array[i].with, data->main->output.to.stream); + f_print_dynamic(replacement.with, data->main->output.to.stream); } else { f_string_range_t range = macro_f_string_range_t_initialize(iki_data.variable.array[index].start, iki_data.content.array[index].start - 1); f_print_dynamic_partial(data->buffer, range, data->main->output.to.stream); - f_print_dynamic(substitutions.array[i].with, data->main->output.to.stream); + f_print_dynamic(replacement.with, data->main->output.to.stream); range.start = iki_data.content.array[index].stop + 1; range.stop = iki_data.variable.array[index].stop; diff --git a/level_3/iki_read/c/private-print.h b/level_3/iki_read/c/private-print.h index 8687a22..03b0e63 100644 --- a/level_3/iki_read/c/private-print.h +++ b/level_3/iki_read/c/private-print.h @@ -13,7 +13,7 @@ extern "C" { #endif /** - * Print any applicable substition and if there is non then print the given range at the given index. + * Print any applicable substitution and if there is none then print the given range at the given index. * * @param data * The program data. @@ -21,8 +21,10 @@ extern "C" { * The IKI data. * @param ranges * The ranges containing the desired range to print as specified by index. + * @param replacement + * A simple substitution string for substitution, substituted only if there are no matches in the substitutions. * @param substitutions - * The substitions associated with the variable for the given range at the given index to use for potential printing. + * The substitutions associated with the variable for the given range at the given index to use for potential printing. * @param index * The index used to identify the desired range in variable, content, and ranges. * @param content_only @@ -30,7 +32,7 @@ extern "C" { * Set to FALSE to print the entire variable when printing substituted text. */ #ifndef _di_iki_read_substitutions_print_ - extern void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; + extern void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; #endif // _di_iki_read_substitutions_print_ #ifdef __cplusplus diff --git a/level_3/iki_read/c/private-read.c b/level_3/iki_read/c/private-read.c index 494c286..af4c035 100644 --- a/level_3/iki_read/c/private-read.c +++ b/level_3/iki_read/c/private-read.c @@ -121,11 +121,21 @@ extern "C" { const bool content_only = data->mode == iki_read_mode_content_e; + iki_read_substitution_t replacements[iki_data->variable.used]; iki_read_substitutions_t substitutionss[iki_data->variable.used]; + memset(replacements, 0, sizeof(iki_read_substitution_t) * iki_data->variable.used); memset(substitutionss, 0, sizeof(iki_read_substitutions_t) * iki_data->variable.used); if (data->mode == iki_read_mode_literal_e || data->mode == iki_read_mode_content_e) { + status = iki_read_replacements_identify(data, &iki_data->vocabulary, replacements); + + if (F_status_is_error(status)) { + fll_error_print(data->main->error, F_status_set_fine(status), "iki_read_replacements_identify", F_true); + + return status; + } + status = iki_read_substitutions_identify(data, &iki_data->vocabulary, substitutionss); if (F_status_is_error(status)) { @@ -181,8 +191,8 @@ extern "C" { if (matches++ != data->at) continue; } - if (substitutionss[j].used) { - iki_read_substitutions_print(data, *iki_data, *ranges, substitutionss[j], j, content_only); + if (replacements[j].replace.used || substitutionss[j].used) { + iki_read_substitutions_print(data, *iki_data, *ranges, replacements[j], substitutionss[j], j, content_only); } else { f_print_dynamic_partial(data->buffer, ranges->array[j], data->main->output.to.stream); @@ -209,8 +219,8 @@ extern "C" { if (data->at < ranges->used) { flockfile(data->main->output.to.stream); - if (substitutionss[data->at].used) { - iki_read_substitutions_print(data, *iki_data, *ranges, substitutionss[data->at], data->at, content_only); + if (replacements[data->at].replace.used || substitutionss[data->at].used) { + iki_read_substitutions_print(data, *iki_data, *ranges, replacements[data->at], substitutionss[data->at], data->at, content_only); } else { f_print_dynamic_partial(data->buffer, ranges->array[data->at], data->main->output.to.stream); @@ -231,8 +241,8 @@ extern "C" { for (f_array_length_t i = 0; i < ranges->used; ++i) { - if (substitutionss[i].used) { - iki_read_substitutions_print(data, *iki_data, *ranges, substitutionss[i], i, content_only); + if (replacements[i].replace.used || substitutionss[i].used) { + iki_read_substitutions_print(data, *iki_data, *ranges, replacements[i], substitutionss[i], i, content_only); } else { f_print_dynamic_partial(data->buffer, ranges->array[i], data->main->output.to.stream); @@ -288,11 +298,21 @@ extern "C" { const bool content_only = data->mode == iki_read_mode_content_e; + iki_read_substitution_t replacements[iki_data->variable.used]; iki_read_substitutions_t substitutionss[iki_data->variable.used]; + memset(replacements, 0, sizeof(iki_read_substitution_t) * iki_data->variable.used); memset(substitutionss, 0, sizeof(iki_read_substitutions_t) * iki_data->variable.used); if (data->mode == iki_read_mode_literal_e || data->mode == iki_read_mode_content_e) { + status = iki_read_replacements_identify(data, &iki_data->vocabulary, replacements); + + if (F_status_is_error(status)) { + fll_error_print(data->main->error, F_status_set_fine(status), "iki_read_replacements_identify", F_true); + + return status; + } + status = iki_read_substitutions_identify(data, &iki_data->vocabulary, substitutionss); if (F_status_is_error(status)) { @@ -403,16 +423,16 @@ extern "C" { } // for if (name_missed) { - if (substitutionss[j].used) { - iki_read_substitutions_print(data, *iki_data, iki_data->variable, substitutionss[j], j, F_false); + if (replacements[j].replace.used || substitutionss[j].used) { + iki_read_substitutions_print(data, *iki_data, iki_data->variable, replacements[j], substitutionss[j], j, F_false); } else { f_print_dynamic_partial(data->buffer, iki_data->variable.array[j], data->main->output.to.stream); } } else { - if (substitutionss[j].used) { - iki_read_substitutions_print(data, *iki_data, *ranges, substitutionss[j], j, content_only); + if (replacements[j].replace.used || substitutionss[j].used) { + iki_read_substitutions_print(data, *iki_data, *ranges, replacements[j], substitutionss[j], j, content_only); } else { f_print_dynamic_partial(data->buffer, ranges->array[j], data->main->output.to.stream); @@ -420,8 +440,8 @@ extern "C" { } } else { - if (substitutionss[j].used) { - iki_read_substitutions_print(data, *iki_data, *ranges, substitutionss[j], j, content_only); + if (replacements[j].replace.used || substitutionss[j].used) { + iki_read_substitutions_print(data, *iki_data, *ranges, replacements[j], substitutionss[j], j, content_only); } else { f_print_dynamic_partial(data->buffer, ranges->array[j], data->main->output.to.stream); @@ -557,6 +577,42 @@ extern "C" { } #endif // _di_iki_read_process_buffer_total_ +#ifndef _di_iki_read_replacements_identify_ + f_status_t iki_read_replacements_identify(iki_read_data_t * const data, f_iki_vocabulary_t *vocabulary, iki_read_substitution_t *replacements) { + + if (data->main->parameters.array[iki_read_parameter_replace_e].result != f_console_result_additional_e) { + return F_none; + } + + f_status_t status = F_none; + + f_array_length_t i = 0; + f_array_length_t j = 0; + + f_array_length_t index = 0; + f_array_length_t index2 = 0; + + f_console_parameter_t *parameter = &data->main->parameters.array[iki_read_parameter_replace_e]; + + for (; i < parameter->values.used; i += 3) { + + index = parameter->values.array[i]; + + for (j = 0; j < vocabulary->used; ++j) { + + if (fl_string_dynamic_partial_compare_string(data->argv[index].string, data->buffer, data->argv[index].used, vocabulary->array[j]) == F_equal_to) { + replacements[j].replace.used = F_true; + + index2 = parameter->values.array[i + 1]; + replacements[j].with = data->argv[index2]; + } + } // for + } // for + + return F_none; + } +#endif // _di_iki_read_replacements_identify_ + #ifndef _di_iki_read_substitutions_identify_ f_status_t iki_read_substitutions_identify(iki_read_data_t * const data, f_iki_vocabulary_t *vocabulary, iki_read_substitutions_t *substitutionss) { @@ -570,7 +626,7 @@ extern "C" { f_array_length_t j = 0; f_array_length_t index = 0; - f_array_length_t index_2 = 0; + f_array_length_t index2 = 0; f_console_parameter_t *parameter = &data->main->parameters.array[iki_read_parameter_substitute_e]; @@ -584,12 +640,11 @@ extern "C" { macro_f_memory_structure_increment(status, substitutionss[j], 1, F_iki_default_allocation_small_d, macro_iki_read_substitutions_t_resize, F_array_too_large); if (F_status_is_error(status)) return status; - index = parameter->values.array[i + 1]; - index_2 = substitutionss[j].used; - substitutionss[j].array[index_2].replace = data->argv[index]; + index2 = parameter->values.array[i + 1]; + substitutionss[j].array[substitutionss[j].used].replace = data->argv[index2]; - index = parameter->values.array[i + 2]; - substitutionss[j].array[index_2].with = data->argv[index]; + index2 = parameter->values.array[i + 2]; + substitutionss[j].array[substitutionss[j].used].with = data->argv[index2]; ++substitutionss[j].used; } diff --git a/level_3/iki_read/c/private-read.h b/level_3/iki_read/c/private-read.h index 3899367..34e4b4a 100644 --- a/level_3/iki_read/c/private-read.h +++ b/level_3/iki_read/c/private-read.h @@ -116,14 +116,40 @@ extern "C" { #endif // _di_iki_read_process_buffer_total_ /** - * Process the arguments, associating substitions with a given vocabulary. + * Process the arguments, associating replacement with a given vocabulary. + * + * The replace property is not used by the --replace option parameter. + * The replace property is instead used to designate whether or not a match is found. + * The replace.string property should, therefore, never be accessed because this would likely result in an invalid read. + * + * When multiple replacements are found, only use the last specified replacement (right-most). + * + * @param data + * The program data. + * @param vocabulary + * The ranges representing a vocabulary. + * @param replacements + * An array of replacements representing an index in the respective vocabulary array. + * This sets replacements[].replace.used to F_false when there are no matches and F_true when there are matches. + * + * @return + * F_none on success. + * + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_iki_read_replacements_identify_ + extern f_status_t iki_read_replacements_identify(iki_read_data_t * const data, f_iki_vocabulary_t *vocabulary, iki_read_substitution_t *replacements) F_attribute_visibility_internal_d; +#endif // _di_iki_read_replacements_identify_ + +/** + * Process the arguments, associating substitutions with a given vocabulary. * * @param data * The program data. * @param vocabulary * The ranges representing a vocabulary. * @param substitutionss - * An array of substitutionss with each index representing an index for in the respective vocabulary array. + * An array of substitutions with each index representing an index for in the respective vocabulary array. * * @return * F_none on success. diff --git a/specifications/iki.txt b/specifications/iki.txt index 7c84ab3..10dfe6b 100644 --- a/specifications/iki.txt +++ b/specifications/iki.txt @@ -7,9 +7,9 @@ IKI Specifications: IKI is a minimally structured WIKI-like syntax meant to be simpler than WIKI syntax. The IKI syntax provides a vocabulary name (with specific context associated with it) followed by quoted code that is associated with the given vocabulary name. - The vocabulary represents a list of allowed object names that may also have specific contextual meaning defined by a given IKI specification. + The vocabulary represents a list of allowed variable names that may also have specific contextual meaning defined by a given IKI specification. The variable name is considered the "Object". - The variable variable is considered the "Content". + The variable value is considered the "Content". The IKI format will use iki-0000 to represent an IKI with no explicitly defined vocabulary. Whereas iki-0001 and beyond represent a specific IKI vocabulary. -- 1.8.3.1