]> Kevux Git Server - fll/commitdiff
Feature: The iki_read program should support a more generalized substitution process...
authorKevin Day <thekevinday@gmail.com>
Sun, 15 May 2022 21:31:11 +0000 (16:31 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 15 May 2022 21:38:41 +0000 (16:38 -0500)
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
level_3/iki_read/c/common.h
level_3/iki_read/c/iki_read.c
level_3/iki_read/c/private-print.c
level_3/iki_read/c/private-print.h
level_3/iki_read/c/private-read.c
level_3/iki_read/c/private-read.h
specifications/iki.txt

index e2283a6784f5cdda1644425f3f7d05d66630f643..6b31f5f55558c18ae634b20c890e2cd969bd0ac1 100644 (file)
@@ -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);
index 4c8b2404753abadab9d85e3c9f7a552fb7593112..e0d0f2ffed715e2c8501e86cb5be5ea06f91deb9 100644 (file)
@@ -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_
index 8d5f7551a068493315bcc1fd63b0a330a243c009..5c85e3a21bb3c4a62e3dd81c90928c04979421eb 100644 (file)
@@ -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) {
index 1dfafea448302069712c5a425dd51b8d61482af1..8c2ffeb434e3646ca42bbab057d5b1ddf7ab0954 100644 (file)
@@ -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;
index 8687a22c741b1d0b0e2c2f1ad55e5b06c45dc387..03b0e639f66d5a48b4ceb05e0cbf58273be65982 100644 (file)
@@ -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
index 494c28679800494c88980e4cbe420e433ed4aa4d..af4c03599b9b935b5a15ec118c724514da86700e 100644 (file)
@@ -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;
         }
index 3899367d6364f3a3aceb2ced43891d5ace363b94..34e4b4a79c747ad3c07591076d1fa188d1746c85 100644 (file)
@@ -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.
index 7c84ab33e45d94384ce082b6e06e8028bcb61130..10dfe6bc3e493fda27134ac39a8ce9e99cc77c81 100644 (file)
@@ -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.