]> Kevux Git Server - fll/commitdiff
Update: finish implementing IKI Read program.
authorKevin Day <thekevinday@gmail.com>
Mon, 29 Jun 2020 00:09:25 +0000 (19:09 -0500)
committerKevin Day <thekevinday@gmail.com>
Mon, 29 Jun 2020 00:09:25 +0000 (19:09 -0500)
The resulting design made --expand redundant, so it is removed.

Substitution is implemented and works independent of the --name parameter.

Added a new macro to the FLL project called f_macro_memory_structure_macro_increment().
Too often do I have to create those structures, so here is a macro to perform the increment.
I started to update the rest of the project and then decided not to spend time on that right now.
This, therefore, primarily focuses on getting the macro working in IKI.

IKI Read is now considered usable, except for the UTF-8 support.
The UTF-8 support is dependent on updating a ton of UTF-8 codes.
This will be done at a later time.

The IKI Read program will eventually need to be reviewed for mistakes and cleanups.

16 files changed:
level_0/f_console/c/console.c
level_0/f_console/c/console.h
level_0/f_directory/c/directory.c
level_0/f_directory/c/directory.h
level_0/f_memory/c/memory-structure.h
level_0/f_path/c/path.c
level_0/f_serialize/c/serialize.c
level_0/f_serialize/c/serialize.h
level_1/fl_directory/c/private-directory.c
level_1/fl_directory/c/private-directory.h
level_2/fll_program/c/program.c
level_2/fll_program/c/program.h
level_3/iki_read/c/iki_read.c
level_3/iki_read/c/iki_read.h
level_3/iki_read/c/private-iki_read.c
level_3/iki_read/c/private-iki_read.h

index 58e054c1c296584591e6a9b29b7916c52f100011..0ac63da1006b48f5452afa7a00f9ce5ed6b6a695 100644 (file)
@@ -286,8 +286,7 @@ extern "C" {
         if (!found) {
           // populate list of remaining parameters.parameter not associated with anything.
           if (remaining->used >= remaining->size) {
-            f_macro_string_lengths_resize(status, (*remaining), remaining->size + f_console_default_allocation_step);
-
+            f_macro_memory_structure_macro_increment(status, (*remaining), 1, f_console_default_allocation_step, f_macro_string_lengths_resize, F_buffer_too_large);
             if (F_status_is_error(status)) {
               f_macro_string_lengths_delete_simple(needs_additional);
               return status;
index 62129f79f74a2ff6ad983a89bb280f400998c631..1d151bae27737913b85b8e9ebc4b8de5aa03f307 100644 (file)
@@ -327,6 +327,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_data_not if "additional" parameters were expected but not found.
+ *   F_buffer_too_large (with error bit) if a buffer would exceed max length.
  *   F_failure (with error bit) if width is not long enough to convert when processing arguments as UTF-8.
  *   F_parameter (with error bit) if a parameter is invalid.
  *   F_utf (with error bit) if character is an invalid UTF-8 character, when processing arguments.
index 5a10089108537999548d179ac595114296d5d746..b37bf203928e68634641358b34c577bf83af4229 100644 (file)
@@ -191,7 +191,7 @@ extern "C" {
       }
 
       if (names->used >= names->size) {
-        f_macro_string_dynamics_resize(status, (*names), names->size + f_directory_default_allocation_step);
+        f_macro_memory_structure_macro_increment(status, (*names), 1, f_directory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
         if (F_status_is_error(status)) break;
       }
 
index 493300fee283378cfbd10d74174165e76848e80a..f66ff927903c0fd4473fde167046b541032253fb 100644 (file)
@@ -284,6 +284,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_data_not if directory is empty.
+ *   F_buffer_too_large (with error bit) if the directory buffer max length would be exceeded.
  *   F_failure (with error bit) if failed to read directory information.
  *   F_memory_reallocation (with error bit) on memory reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
index d8a583fccc17bfdb605fe545063eb5511a897316..e330133190c31dc906012a1af9d7189e94d4a623 100644 (file)
@@ -328,6 +328,39 @@ extern "C" {
     }
 #endif // _di_f_macro_memory_structures_adjust_
 
+/**
+ * Provide a macro for calling other macros for incrementing a buffer.
+ *
+ * If the used + step is greater than size, then increase by step_default.
+ * If step_default exceeds f_array_length_size, then attempt to increment by step.
+ * If step exceeds f_array_length_size, set status to error_too_large.
+ *
+ * Be sure to check size for error after calling this.
+ *
+ * status:          the status to return.
+ * structures:      the structures to operate on.
+ * step:            the step to increase by, must be less than or equal to step_default.
+ * step_default:    the default step to increase by if memory allows.
+ * macro_resize:    the resize structure macro to call that excepts the exact arguments: (status, structure, new_length).
+ * error_too_large: the error status to return when f_array_length_size would be exceeded.
+ */
+#ifndef _di_f_macro_memory_structure_macro_increment_
+  #define f_macro_memory_structure_macro_increment(status, structure, step, step_default, macro_resize, error_too_large) \
+    if (structure.used + step > structure.size) { \
+      if (structure.used + step_default > f_array_length_size) { \
+        if (structure.used + step > structure.size > f_array_length_size) { \
+          status = F_status_set_error(error_too_large); \
+        } \
+        else { \
+          macro_resize(status, structure, structure.size + step); \
+        } \
+      } \
+      else { \
+        macro_resize(status, structure, structure.size + step_default); \
+      } \
+    }
+#endif // _di_f_macro_memory_structure_macro_increment_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 3ec5dec0b7ffa0fa5b521f5b1d432731c5825d54..634e3b4d842f8efaeb5715db68d14b15971dcf01 100644 (file)
@@ -17,20 +17,8 @@ extern "C" {
     if (length == 0) {
       // When PATH is "", this is actually a valid search path for PWD.
       // Therefore append an equivalent representation of PWD (string used length is 0).
-      if (paths->used + 1 > paths->size) {
-        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (paths->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       f_macro_string_dynamic_clear(paths->array[paths->used]);
       paths->used++;
@@ -44,20 +32,8 @@ extern "C" {
 
     for (i = 0; i <= length; i++) {
       if (i == length || path[i] == f_path_separator_variable[0]) {
-        if (paths->used + 1 > paths->size) {
-          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-            if (paths->size + 1 > f_array_length_size) {
-              return F_status_set_error(F_buffer_too_large);
-            }
-
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-            if (F_status_is_error(status)) return status;
-          }
-          else {
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-            if (F_status_is_error(status)) return status;
-          }
-        }
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (i == 0) {
           f_macro_string_dynamic_clear(paths->array[paths->used]);
@@ -115,20 +91,8 @@ extern "C" {
     if (path.used == 0) {
       // When PATH is "", this is actually a valid search path for PWD.
       // Therefore append an equivalent representation of PWD (string used length is 0).
-      if (paths->used + 1 > paths->size) {
-        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (paths->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       f_macro_string_dynamic_clear(paths->array[paths->used]);
       paths->used++;
@@ -145,20 +109,8 @@ extern "C" {
 
     for (i = 0; i <= path.used; i++) {
       if (i == path.used || path.string[i] == f_path_separator_variable[0]) {
-        if (paths->used + 1 > paths->size) {
-          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-            if (paths->size + 1 > f_array_length_size) {
-              return F_status_set_error(F_buffer_too_large);
-            }
-
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-            if (F_status_is_error(status)) return status;
-          }
-          else {
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-            if (F_status_is_error(status)) return status;
-          }
-        }
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (i == 0) {
           f_macro_string_dynamic_clear(paths->array[paths->used]);
@@ -216,20 +168,8 @@ extern "C" {
     if (length == 0) {
       // When PATH is "", this is actually a valid search path for PWD.
       // Therefore append an equivalent representation of PWD (string used length is 0).
-      if (paths->used + 1 > paths->size) {
-        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (paths->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       paths->array[paths->used].string = 0;
       paths->array[paths->used].used = 0;
@@ -250,20 +190,8 @@ extern "C" {
       j--;
 
       if (j == 0 || path[j] == f_path_separator_variable[0]) {
-        if (paths->used + 1 > paths->size) {
-          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-            if (paths->size + 1 > f_array_length_size) {
-              return F_status_set_error(F_buffer_too_large);
-            }
-
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-            if (F_status_is_error(status)) return status;
-          }
-          else {
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-            if (F_status_is_error(status)) return status;
-          }
-        }
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (path[j] == f_path_separator_variable[0]) {
           total = last - i;
@@ -335,20 +263,8 @@ extern "C" {
     if (path.used == 0) {
       // When PATH is "", this is actually a valid search path for PWD.
       // Therefore append an equivalent representation of PWD (string used length is 0).
-      if (paths->used + 1 > paths->size) {
-        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (paths->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       f_macro_string_dynamic_clear(paths->array[paths->used]);
       paths->used++;
@@ -368,20 +284,8 @@ extern "C" {
       j--;
 
       if (j == 0 || path.string[j] == f_path_separator_variable[0]) {
-        if (paths->used + 1 > paths->size) {
-          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
-            if (paths->size + 1 > f_array_length_size) {
-              return F_status_set_error(F_buffer_too_large);
-            }
-
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
-            if (F_status_is_error(status)) return status;
-          }
-          else {
-            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
-            if (F_status_is_error(status)) return status;
-          }
-        }
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (path.string[j] == f_path_separator_variable[0]) {
           total = last - i;
index 9afea81bcfbf3b75d25ffdaa7c9564cd6e7e0def..86324bfaa1e98f1d65d3d21b7706ea66c4912cd7 100644 (file)
@@ -50,10 +50,8 @@ extern "C" {
       width = f_macro_utf_byte_width(serialize.string[i]);
 
       if (serialize.string[i] == f_serialize_simple_splitter || i + 1 >= serialize.used) {
-        if (strings->used >= strings->size) {
-          f_macro_string_dynamics_resize(status, (*strings), strings->size + f_serialize_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
+        f_macro_memory_structure_macro_increment(status, (*strings), 1, f_serialize_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (start == i) {
           strings->array[strings->used].used = 0;
@@ -118,10 +116,8 @@ extern "C" {
       width = f_macro_utf_byte_width(serialize.string[i]);
 
       if (serialize.string[i] == f_serialize_simple_splitter || i + 1 >= serialize.used) {
-        if (locations->used >= locations->size) {
-          f_macro_string_ranges_resize(status, (*locations), locations->size + f_serialize_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
+        f_macro_memory_structure_macro_increment(status, (*locations), 1, f_serialize_default_allocation_step, f_macro_string_ranges_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
 
         if (start == i) {
           // provide an invalid start to stop range to communicate that there is no data.
index 959f64918f35e0823034b3e0f7a21abff16d9be4..1012cb1c7381d138e14dd91ebdf927cb35e2469f 100644 (file)
@@ -83,6 +83,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_incomplete_utf_eos if end of sting is reached before a complete UTF-8 character can be processed.
+ *   F_buffer_too_large (with error bit) if a buffer would exceed maximum length.
  *   F_memory_reallocation (with error bit) on memory reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
  */
@@ -108,6 +109,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_incomplete_utf_eos if end of sting is reached before a complete UTF-8 character can be processed.
+ *   F_buffer_too_large (with error bit) if a buffer would exceed memory max length.
  *   F_memory_reallocation (with error bit) on memory reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
  */
index c70276d8f57151acca1ca6dc8f2875eb0b490c36..595965746bc823a9372790b6ae39284b05f34f91 100644 (file)
@@ -165,20 +165,8 @@ extern "C" {
 
       const f_status status_failure = status;
 
-      if (failures->used + 1 > failures->size) {
-        if (failures->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (failures->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_directory_statuss_resize(status, (*failures), failures->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_directory_statuss_resize(status, (*failures), failures->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       f_directory_status failure = f_directory_status_initialize;
       f_string_length size = 0;
@@ -387,20 +375,8 @@ extern "C" {
 
       const f_status status_failure = status;
 
-      if (failures->used + 1 > failures->size) {
-        if (failures->size + f_memory_default_allocation_step > f_array_length_size) {
-          if (failures->size + 1 > f_array_length_size) {
-            return F_status_set_error(F_buffer_too_large);
-          }
-
-          f_macro_directory_statuss_resize(status, (*failures), failures->used + 1);
-          if (F_status_is_error(status)) return status;
-        }
-        else {
-          f_macro_directory_statuss_resize(status, (*failures), failures->used + f_memory_default_allocation_step);
-          if (F_status_is_error(status)) return status;
-        }
-      }
+      f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
 
       f_directory_status failure = f_directory_status_initialize;
       f_string_length size = 0;
index 529928a13db35ce3e85c8345a2b97e92b78381dc..003a234c1f8ef7cdeaa1e9471a7a231037627ed6 100644 (file)
@@ -96,6 +96,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_data_not if directory is empty.
+ *   F_buffer_too_large (with error bit) if a buffer would exceed max length.
  *   F_directory_descriptor (with error bit) on directory file descriptor error.
  *   F_directory_open (with error bit) on directory open error.
  *   F_directory_stream (with error bit) on directory stream error.
index deeed71b8701a6d3534c2663115db36cc13e660b..ce2fa612530e2cf9cfe981c8b8b5ef977e5c92dd 100644 (file)
@@ -271,10 +271,8 @@ extern "C" {
           status = F_none;
         }
         else {
-          if (destination->used >= destination->size) {
-            f_macro_string_dynamics_resize(status, (*destination), destination->size + f_console_default_allocation_step);
-            if (F_status_is_error(status)) return status;
-          }
+          f_macro_memory_structure_macro_increment(status, (*destination), 1, f_console_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+          if (F_status_is_error(status)) break;
 
           destination->array[destination->used] = ripped;
           destination->used++;
index 226f129f1dc3ccdf13b5ad55d2feb9a221422fba..4afe1cbd3dfec84720644582bcbb7bf52c301d0b 100644 (file)
@@ -246,6 +246,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_data_not if nothing to rip, no allocations or reallocations are performed.
+ *   F_buffer_too_large (with error bit) if a buffer would exceed max length.
  *   F_memory_allocation (with error bit) on memory allocation error.
  *   F_memory_reallocation (with error bit) on memory reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
index 6d8fbe00da58a63577865d53fc769475350a881e..ee6decc3536c26796d2fe34abcb0c80c35fd9ee8 100644 (file)
@@ -33,7 +33,6 @@ extern "C" {
     printf("%c", f_string_eol[0]);
 
     fll_program_print_help_option(context, iki_read_short_substitute, iki_read_long_substitute, f_console_symbol_short_enable, f_console_symbol_long_enable,"Substitute the entire variable for the given name and content value with the given string.");
-    fll_program_print_help_option(context, iki_read_short_expand, iki_read_long_expand, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Expand variables into their respective content.");
 
     fll_program_print_help_usage(context, iki_read_name, "filename(s)");
 
@@ -50,25 +49,25 @@ extern "C" {
     printf(" option, requires 3 additional parameters: ");
 
     fl_color_print(f_type_output, context.notable, context.reset, "<");
-    printf("%s", iki_read_replacement_vocabulary);
+    printf("%s", iki_read_substitution_vocabulary);
     fl_color_print(f_type_output, context.notable, context.reset, ">");
     printf(" ");
     fl_color_print(f_type_output, context.notable, context.reset, "<");
-    printf("%s", iki_read_replacement_replace);
+    printf("%s", iki_read_substitution_replace);
     fl_color_print(f_type_output, context.notable, context.reset, ">");
     printf(" ");
     fl_color_print(f_type_output, context.notable, context.reset, "<");
-    printf("%s", iki_read_replacement_with);
+    printf("%s", iki_read_substitution_with);
     fl_color_print(f_type_output, context.notable, context.reset, ">");
     printf(".%c", f_string_eol[0]);
 
-    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_vocabulary);
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_substitution_vocabulary);
     printf(": The name of the vocabulary whose content is to be substituted.%c", f_string_eol[0]);
 
-    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_replace);
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_substitution_replace);
     printf(":    The content matching this exact string will be substituted.%c", f_string_eol[0]);
 
-    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_with);
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_substitution_with);
     printf(":       The new string to use as the substitute.%c", f_string_eol[0]);
 
     printf("%c", f_string_eol[0]);
@@ -77,14 +76,6 @@ extern "C" {
 
     printf("%c", f_string_eol[0]);
 
-    printf("  All substitution is applied before any expansion when both the ", f_string_eol[0]);
-    fl_color_print(f_type_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_substitute);
-    printf(" option and the ");
-    fl_color_print(f_type_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_expand);
-    printf(" option are specified.%c", f_string_eol[0]);
-
-    printf("%c", f_string_eol[0]);
-
     printf("  The default behavior is to only display content portion of the IKI variable.%c", f_string_eol[0]);
 
     printf("%c", f_string_eol[0]);
@@ -255,21 +246,6 @@ extern "C" {
           }
         }
 
-        if (data->parameters[iki_read_parameter_expand].result == f_console_result_found) {
-          if (data->parameters[iki_read_parameter_total].result == f_console_result_found) {
-            if (data->verbosity != iki_read_verbosity_quiet) {
-              fprintf(f_type_error, "%c", f_string_eol[0]);
-              fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
-              fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_expand);
-              fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
-              fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_total);
-              fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
-            }
-
-            status = F_status_set_error(F_parameter);
-          }
-        }
-
         if (data->parameters[iki_read_parameter_literal].result == f_console_result_found) {
           if (data->parameters[iki_read_parameter_object].result == f_console_result_found) {
             if (data->verbosity != iki_read_verbosity_quiet) {
index fdaa1e14d8dc35e5b952cf74f97d32805ed4763e..3b97178ea8c38df135c28337b866e2c9f6e1a408 100644 (file)
@@ -76,7 +76,6 @@ extern "C" {
   };
 
   #define iki_read_short_at         "a"
-  #define iki_read_short_expand     "e"
   #define iki_read_short_line       "l"
   #define iki_read_short_literal    "L"
   #define iki_read_short_name       "n"
@@ -86,7 +85,6 @@ extern "C" {
   #define iki_read_short_whole      "w"
 
   #define iki_read_long_at         "at"
-  #define iki_read_long_expand     "expand"
   #define iki_read_long_line       "line"
   #define iki_read_long_literal    "literal"
   #define iki_read_long_name       "name"
@@ -105,7 +103,6 @@ extern "C" {
     iki_read_parameter_version,
 
     iki_read_parameter_at,
-    iki_read_parameter_expand,
     iki_read_parameter_line,
     iki_read_parameter_literal,
     iki_read_parameter_name,
@@ -125,7 +122,6 @@ extern "C" {
       f_console_parameter_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
       f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
       f_console_parameter_initialize(iki_read_short_at, iki_read_long_at, 0, 1, f_console_type_normal), \
-      f_console_parameter_initialize(iki_read_short_expand, iki_read_long_expand, 0, 0, f_console_type_normal), \
       f_console_parameter_initialize(iki_read_short_line, iki_read_long_line, 0, 1, f_console_type_normal), \
       f_console_parameter_initialize(iki_read_short_literal, iki_read_long_literal, 0, 0, f_console_type_normal), \
       f_console_parameter_initialize(iki_read_short_name, iki_read_long_name, 0, 1, f_console_type_normal), \
@@ -135,64 +131,61 @@ extern "C" {
       f_console_parameter_initialize(iki_read_short_total, iki_read_long_total, 0, 0, f_console_type_normal), \
     }
 
-  #define iki_read_total_parameters 16
+  #define iki_read_total_parameters 15
 #endif // _di_iki_read_defines_
 
-#ifndef _di_iki_read_replacement_
-  #define iki_read_replacement_vocabulary "vocabulary"
-  #define iki_read_replacement_replace    "replace"
-  #define iki_read_replacement_with       "with"
+#ifndef _di_iki_read_substitution_
+  #define iki_read_substitution_vocabulary "vocabulary"
+  #define iki_read_substitution_replace    "replace"
+  #define iki_read_substitution_with       "with"
 
   typedef struct {
-    f_string_static vocabulary;
     f_string_static replace;
     f_string_static with;
-  } iki_read_replacement;
+  } iki_read_substitution;
 
-  #define iki_read_replacement_initialize \
+  #define iki_read_substitution_initialize \
     { \
       f_string_static_initialize, \
       f_string_static_initialize, \
-      f_string_static_initialize, \
     }
 
-  #define macro_iki_read_replacement_initialize(vocabulary, replace, with) \
+  #define macro_iki_read_substitution_initialize(replace, with) \
     { \
-      f_macro_string_static_initialize(vocabulary), \
       f_macro_string_static_initialize(replace), \
       f_macro_string_static_initialize(with), \
     }
-#endif // _di_iki_read_replacement_
+#endif // _di_iki_read_substitution_
 
-#ifndef _di_iki_read_replacements_
+#ifndef _di_iki_read_substitutions_
   typedef struct {
-    iki_read_replacement *array;
+    iki_read_substitution *array;
 
     f_array_length size;
     f_array_length used;
-  } iki_read_replacements;
+  } iki_read_substitutions;
 
-  #define iki_read_replacements_initialize {0, 0, 0}
+  #define iki_read_substitutions_initialize {0, 0, 0}
 
-  #define macro_iki_read_replacements_clear(replacements) f_macro_memory_structure_clear(replacements)
+  #define macro_iki_read_substitutions_clear(replacements) f_macro_memory_structure_clear(replacements)
 
-  #define macro_iki_read_replacements_new(status, replacements, length) f_macro_memory_structure_new(status, replacements, iki_read_replacement, length)
+  #define macro_iki_read_substitutions_new(status, replacements, length) f_macro_memory_structure_new(status, replacements, iki_read_substitution, length)
 
-  #define macro_iki_read_replacements_delete_simple(replacements) \
+  #define macro_iki_read_substitutions_delete_simple(replacements) \
     replacements.used = replacements.size; \
     while (replacements.used > 0) { \
       replacements.used--; \
     } \
-    if (replacements.used == 0) f_macro_memory_structure_delete_simple(replacements, iki_read_replacement)
+    if (replacements.used == 0) f_macro_memory_structure_delete_simple(replacements, iki_read_substitution)
 
-  #define macro_iki_read_replacements_destroy_simple(replacements) \
+  #define macro_iki_read_substitutions_destroy_simple(replacements) \
     replacements.used = replacements.size; \
     while (replacements.used > 0) { \
       replacements.used--; \
     } \
-    if (replacements.used == 0) f_macro_memory_structure_destroy_simple(replacements, iki_read_replacement)
+    if (replacements.used == 0) f_macro_memory_structure_destroy_simple(replacements, iki_read_substitution)
 
-  #define macro_iki_read_replacements_resize(status, replacements, new_length) \
+  #define macro_iki_read_substitutions_resize(status, replacements, new_length) \
     status = F_none; \
     if (new_length < replacements.size) { \
       f_array_length i = replacements.size - new_length; \
@@ -200,19 +193,19 @@ extern "C" {
         if (status != F_none) break; \
       } \
     } \
-    if (status == F_none) status = f_memory_resize((void **) & replacements.array, sizeof(iki_read_replacement), replacements.size, new_length); \
+    if (status == F_none) status = f_memory_resize((void **) & replacements.array, sizeof(iki_read_substitution), replacements.size, new_length); \
     if (status == F_none) { \
       if (new_length > replacements.size) { \
         f_array_length i = replacements.size; \
         for (; i < new_length; i++) { \
-          memset(&replacements.array[i], 0, sizeof(iki_read_replacement)); \
+          memset(&replacements.array[i], 0, sizeof(iki_read_substitution)); \
         } \
       } \
       replacements.size = new_length; \
       if (replacements.used > replacements.size) replacements.used = new_length; \
     }
 
-  #define macro_iki_read_replacements_adjust(status, replacements, new_length) \
+  #define macro_iki_read_substitutions_adjust(status, replacements, new_length) \
     status = F_none; \
     if (new_length < replacements.size) { \
       f_array_length i = replacements.size - new_length; \
@@ -220,18 +213,18 @@ extern "C" {
         if (status != F_none) break; \
       } \
     } \
-    if (status == F_none) status = f_memory_adjust((void **) & replacements.array, sizeof(iki_read_replacement), replacements.size, new_length); \
+    if (status == F_none) status = f_memory_adjust((void **) & replacements.array, sizeof(iki_read_substitution), replacements.size, new_length); \
     if (status == F_none) { \
       if (new_length > replacements.size) { \
         f_array_length i = replacements.size; \
         for (; i < new_length; i++) { \
-          memset(&replacements.array[i], 0, sizeof(iki_read_replacement)); \
+          memset(&replacements.array[i], 0, sizeof(iki_read_substitution)); \
         } \
       } \
       replacements.size = new_length; \
       if (replacements.used > replacements.size) replacements.used = new_length; \
     }
-#endif // _di_iki_read_replacements_
+#endif // _di_iki_read_substitutions_
 
 #ifndef _di_iki_read_data_
   typedef struct {
@@ -248,7 +241,7 @@ extern "C" {
 
     f_string_dynamic buffer;
 
-    iki_read_replacements replacements;
+    iki_read_substitutions replacements;
 
     fl_color_context context;
   } iki_read_data;
@@ -263,7 +256,7 @@ extern "C" {
       0, \
       0, \
       f_string_dynamic_initialize, \
-      iki_read_replacements_initialize, \
+      iki_read_substitutions_initialize, \
       fl_color_context_initialize, \
     }
 #endif // _di_iki_read_data_
index 04ac184c4fc76949d25069618ac19aef07d9938d..d4210932a8f40ef5ebc1c4fac6c2c56f298f5fce 100644 (file)
@@ -402,13 +402,31 @@ extern "C" {
       return status;
     }
 
+    bool content_only = data->mode == iki_read_mode_content;
+
+    iki_read_substitutions substitutionss[variable->used];
+
+    memset(substitutionss, 0, sizeof(iki_read_substitutions) * variable->used);
+
+    if (data->mode == iki_read_mode_literal || data->mode == iki_read_mode_content) {
+      status = iki_read_substitutions_identify(arguments, file_name, data, vocabulary, substitutionss);
+      if (F_status_is_error(status)) {
+        iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_substitutions_identify", F_true);
+
+        for (f_array_length i = 0; i < variable->used; i++) {
+          macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+        } // for
+
+        return status;
+      }
+    }
+
     if (data->parameters[iki_read_parameter_name].result == f_console_result_additional) {
       f_string_dynamic name = f_string_dynamic_initialize;
 
       f_array_length index = 0;
       f_array_length i = 0;
       f_array_length j = 0;
-
       buffer_range->start = 0;
 
       for (; i < data->parameters[iki_read_parameter_name].additional.used; i++) {
@@ -419,6 +437,10 @@ extern "C" {
         if (F_status_is_error(status)) {
           iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "fl_string_append_nulless", F_true);
 
+          for (f_array_length i = 0; i < variable->used; i++) {
+            macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+          } // for
+
           f_macro_string_dynamic_delete_simple(name);
           return status;
         }
@@ -431,7 +453,13 @@ extern "C" {
           if (status == F_equal_to) {
             unmatched = F_false;
 
-            f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
+            if (substitutionss[j].used) {
+              iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, content_only);
+            }
+            else {
+              f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
+            }
+
             printf("%c", f_string_eol[0]);
           }
         } // for
@@ -439,19 +467,36 @@ extern "C" {
 
       f_macro_string_dynamic_delete_simple(name);
 
-      if (unmatched) return F_data_not;
+      if (unmatched) status = F_data_not;
+      else status = F_none;
     }
     else if (ranges->used) {
-      for (f_array_length i = 0; i < ranges->used; i++) {
-        f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[i]);
+      f_array_length i = 0;
+      f_string_length j = 0;
+
+      for (; i < ranges->used; i++) {
+
+        if (substitutionss[i].used) {
+          iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[i], i, content_only);
+        }
+        else {
+          f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[i]);
+        }
+
         printf("%c", f_string_eol[0]);
       } // for
+
+      status = F_none;
     }
     else {
-      return F_data_not;
+      status = F_data_not;
     }
 
-    return F_none;
+    for (f_array_length i = 0; i < variable->used; i++) {
+      macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+    } // for
+
+    return status;
   }
 #endif // _di_iki_read_process_buffer_ranges_
 
@@ -471,10 +516,31 @@ extern "C" {
       return F_none;
     }
 
+    iki_read_substitutions substitutionss[variable->used];
+
+    memset(substitutionss, 0, sizeof(iki_read_substitutions) * variable->used);
+
+    if (data->mode == iki_read_mode_literal || data->mode == iki_read_mode_content) {
+      status = iki_read_substitutions_identify(arguments, file_name, data, vocabulary, substitutionss);
+      if (F_status_is_error(status)) {
+        iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_substitutions_identify", F_true);
+
+        for (f_array_length i = 0; i < variable->used; i++) {
+          macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+        } // for
+
+        return status;
+      }
+    }
+
     f_string_dynamics names = f_string_dynamics_initialize;
     f_string_range name_range = f_string_range_initialize;
+    f_string_range substitution_range = f_string_range_initialize;
+
     bool name_missed = F_true;
 
+    substitution_range.start = 0;
+
     if (data->parameters[iki_read_parameter_name].result == f_console_result_additional) {
       f_array_length i = 0;
       f_array_length j = 0;
@@ -494,97 +560,106 @@ extern "C" {
         } // for
 
         if (name_missed) {
-          if (names.used + 1 > names.size) {
-            if (names.used + f_iki_default_allocation_step > f_array_length_size) {
-              if (names.used + 1 > names.size > f_array_length_size) {
-                iki_read_print_error(data->context, data->verbosity, F_buffer_too_large, "iki_read_process_buffer_ranges_whole", F_true);
-
-                f_macro_string_dynamics_delete_simple(names);
-                return F_status_set_error(F_buffer_too_large);
-              }
-              else {
-                f_macro_string_dynamics_resize(status, names, names.used + 1);
-              }
-            }
-            else {
-              f_macro_string_dynamics_resize(status, names, names.used + f_iki_default_allocation_step);
-            }
-
-            if (F_status_is_error(status)) {
-              iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_process_buffer_ranges_whole", F_true);
-
-              f_macro_string_dynamics_delete_simple(names);
-              return status;
-            }
+          f_macro_memory_structure_macro_increment(status, names, 1, f_iki_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+          if (F_status_is_error(status)) {
+            iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_process_buffer_ranges_whole", F_true);
+            break;
           }
 
           status = fl_string_append_nulless(arguments.argv[index], length_argument, &names.array[names.used]);
           if (F_status_is_error(status)) {
             iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "fl_string_append_nulless", F_true);
-
-            f_macro_string_dynamics_delete_simple(names);
-            return status;
+            break;
           }
 
           names.used++;
         }
       } // for
+
+      if (F_status_is_error(status)) {
+        for (i = 0; i < variable->used; i++) {
+          macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+        } // for
+
+        f_macro_string_dynamics_delete_simple(names);
+        return status;
+      }
     }
 
-    f_string_length i = buffer_range.start;
-    f_array_length j = 0;
-    f_array_length k = 0;
+    {
+      f_string_length i = buffer_range.start;
+      f_array_length j = 0;
+      f_array_length k = 0;
 
-    range = buffer_range;
-    name_range.start = 0;
+      range = buffer_range;
+      name_range.start = 0;
 
-    while (i <= range.stop && j < variable->used) {
-      if (i < variable->array[j].start) {
-        range.stop = variable->array[j].start - 1;
+      while (i <= range.stop && j < variable->used) {
+        if (i < variable->array[j].start) {
+          range.stop = variable->array[j].start - 1;
 
-        f_print_string_dynamic_partial(f_type_output, data->buffer, range);
+          f_print_string_dynamic_partial(f_type_output, data->buffer, range);
 
-        range.start = variable->array[j].stop + 1;
-        range.stop = buffer_range.stop;
+          range.start = variable->array[j].stop + 1;
+          range.stop = buffer_range.stop;
 
-        i = variable->array[j].start;
-      }
+          i = variable->array[j].start;
+        }
 
-      // @todo handle expansion and substitution.
-      if (names.used) {
-        name_missed = F_true;
+        if (names.used) {
+          name_missed = F_true;
 
-        for (k = 0; k < names.used; k++) {
-          name_range.stop = names.array[k].used - 1;
+          for (k = 0; k < names.used; k++) {
+            name_range.stop = names.array[k].used - 1;
 
-          status = fl_string_dynamic_partial_compare(data->buffer, names.array[k], vocabulary->array[j], name_range);
+            status = fl_string_dynamic_partial_compare(data->buffer, names.array[k], vocabulary->array[j], name_range);
 
-          if (status == F_equal_to) {
-            name_missed = F_false;
-            break;
-          }
-        } // for
+            if (status == F_equal_to) {
+              name_missed = F_false;
+              break;
+            }
+          } // for
 
-        if (name_missed) {
-          f_print_string_dynamic_partial(f_type_output, data->buffer, variable->array[j]);
+          if (name_missed) {
+            if (substitutionss[j].used) {
+              iki_read_substitutions_print(*data, *variable, *content, *variable, substitutionss[j], j, F_false);
+            }
+            else {
+              f_print_string_dynamic_partial(f_type_output, data->buffer, variable->array[j]);
+            }
+          }
+          else {
+            if (substitutionss[j].used) {
+              iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, F_true);
+            }
+            else {
+              f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
+            }
+          }
         }
         else {
-          f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
+          if (substitutionss[j].used) {
+            iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, F_true);
+          }
+          else {
+            f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
+          }
         }
-      }
-      else {
-        f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]);
-      }
 
-      i = variable->array[j].stop + 1;
-      j++;
-    } // while
+        i = variable->array[j].stop + 1;
+        j++;
+      } // while
 
-    if (i <= buffer_range.stop) {
-      range.start = i;
-      f_print_string_dynamic_partial(f_type_output, data->buffer, range);
+      if (i <= buffer_range.stop) {
+        range.start = i;
+        f_print_string_dynamic_partial(f_type_output, data->buffer, range);
+      }
     }
 
+    for (f_array_length i = 0; i < variable->used; i++) {
+      macro_iki_read_substitutions_delete_simple(substitutionss[i]);
+    } // for
+
     f_macro_string_dynamics_delete_simple(names);
     return F_none;
   }
@@ -658,6 +733,93 @@ extern "C" {
   }
 #endif // _di_iki_read_process_buffer_total_
 
+#ifndef _di_iki_read_substitutions_identify_
+  f_return_status iki_read_substitutions_identify(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_vocabulary *vocabulary, iki_read_substitutions *substitutionss) {
+    if (data->parameters[iki_read_parameter_substitute].result != f_console_result_additional) return F_none;
+
+    f_status status = F_none;
+
+    f_array_length i = 0;
+    f_array_length j = 0;
+
+    f_array_length index = 0;
+    f_array_length index_2 = 0;
+
+    f_string_length length = 0;
+
+    f_console_parameter *parameter = &data->parameters[iki_read_parameter_substitute];
+
+    for (; i < parameter->additional.used; i += 3) {
+      index = parameter->additional.array[i];
+      length = strnlen(arguments.argv[index], f_console_length_size);
+
+      for (j = 0; j < vocabulary->used; j++) {
+        status = fl_string_compare(arguments.argv[index], data->buffer.string + vocabulary->array[j].start, length, (vocabulary->array[j].stop - vocabulary->array[j].start) + 1);
+
+        if (status == F_equal_to) {
+          f_macro_memory_structure_macro_increment(status, substitutionss[j], 1, f_iki_default_allocation_step, macro_iki_read_substitutions_resize, F_buffer_too_large);
+          if (F_status_is_error(status)) return status;
+
+          index = parameter->additional.array[i + 1];
+          index_2 = substitutionss[j].used;
+          substitutionss[j].array[index_2].replace.string = arguments.argv[index];
+          substitutionss[j].array[index_2].replace.used = strnlen(arguments.argv[index], f_console_length_size);
+          substitutionss[j].array[index_2].replace.size = substitutionss[j].array[index_2].replace.used;
+
+          index = parameter->additional.array[i + 2];
+          substitutionss[j].array[index_2].with.string = arguments.argv[index];
+          substitutionss[j].array[index_2].with.used = strnlen(arguments.argv[index], f_console_length_size);
+          substitutionss[j].array[index_2].with.size = substitutionss[j].array[index_2].with.used;
+
+          substitutionss[j].used++;
+        }
+      } // for
+    } // for
+
+    return F_none;
+  }
+#endif // _di_iki_read_substitutions_identify_
+
+#ifndef _di_iki_read_substitutions_print_
+  void iki_read_substitutions_print(const iki_read_data data, const f_iki_variable variable, const f_iki_content content, const f_string_ranges ranges, const iki_read_substitutions substitutions, const f_string_length index, const bool content_only) {
+    f_status status = F_none;
+
+    f_string_length i = 0;
+    f_string_range range = f_string_range_initialize;
+
+    range.start = 0;
+
+    for (; i < substitutions.used; i++) {
+      range.stop = substitutions.array[i].replace.used - 1;
+
+      status = fl_string_dynamic_partial_compare(substitutions.array[i].replace, data.buffer, range, content.array[index]);
+      if (status == F_equal_to) break;
+    } // for
+
+    if (status == F_equal_to) {
+      if (content_only) {
+        f_print_string_dynamic(f_type_output, substitutions.array[i].with);
+      }
+      else {
+        range.start = variable.array[index].start;
+        range.stop = content.array[index].start - 1;
+
+        f_print_string_dynamic_partial(f_type_output, data.buffer, range);
+
+        f_print_string_dynamic(f_type_output, substitutions.array[i].with);
+
+        range.start = content.array[index].stop + 1;
+        range.stop = variable.array[index].stop;
+
+        f_print_string_dynamic_partial(f_type_output, data.buffer, range);
+      }
+    }
+    else {
+      f_print_string_dynamic_partial(f_type_output, data.buffer, ranges.array[index]);
+    }
+  }
+#endif // _di_iki_read_substitutions_print_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 437ed93fd49fc3b7ab4fd0f9bd7ae8c575d40c93..0860b8b0068f51704d414badaae63280f4c329ab 100644 (file)
@@ -223,6 +223,52 @@ extern "C" {
   extern f_return_status iki_read_process_buffer_total(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_variable *variable, f_iki_vocabulary *vocabulary, f_iki_content *content) f_gcc_attribute_visibility_internal;
 #endif // _di_iki_read_process_buffer_total_
 
+/**
+ * Process the arguments, associating substitions with a given vocabulary.
+ *
+ * @param arguments
+ *   The console arguments passed to the program.
+ * @param file_name
+ *   The name of the file being processed.
+ * @param data
+ *   The program specific 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.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_iki_read_substitutions_identify_
+  extern f_return_status iki_read_substitutions_identify(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_vocabulary *vocabulary, iki_read_substitutions *substitutionss) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_substitutions_identify_
+
+/**
+ * Print any applicable substition and if there is non then print the given range at the given index.
+ *
+ * @param data
+ *   The program specific data.
+ * @param variable
+ *   The ranges representing a variable.
+ * @param content
+ *   The ranges representing a content.
+ * @param ranges
+ *   The ranges containing the desired range to print as specified by index.
+ * @param substitutions
+ *   The substitions 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
+ *   Set to TRUE to only print the content when printing substituted text.
+ *   Set to FALSE to print the entire variable when printing substituted text.
+ */
+#ifndef _di_iki_read_substitutions_print_
+  extern void iki_read_substitutions_print(const iki_read_data data, const f_iki_variable variable, const f_iki_content content, const f_string_ranges ranges, const iki_read_substitutions substitutions, const f_string_length index, const bool content_only) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_substitutions_print_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif