]> Kevux Git Server - fll/commitdiff
Progress: Continue fixing iki_read (and eki_read).
authorKevin Day <Kevin@kevux.org>
Mon, 16 Dec 2024 04:00:04 +0000 (22:00 -0600)
committerKevin Day <Kevin@kevux.org>
Mon, 16 Dec 2024 04:00:04 +0000 (22:00 -0600)
I am using the 0.6.x iki_read runtime tests files to help identify problems.
This will also help identify problems with the 0.6.x iki_read.
(Of which I believe that there are some.)

This has a huge focus on addressing the `--line` and `--total`.
There are still known problems to solve, such as:
```
iki_read tests/runtime/iki/source/test-0000-basic.iki -L -a 1 -n hello
iki_read tests/runtime/iki/source/test-0000-basic.iki -L -a 1 -n hello -t
```

The EKI code is being partially updated while I am working on the IKI code.
However, big parts of it that are outdated are being left alone until I have IKI working correctly.
I will then update EKI accordingly and write the appropriate runtime tests.

17 files changed:
level_3/iki_read/c/eki/print.c
level_3/iki_read/c/eki/print.h
level_3/iki_read/c/eki/process.c
level_3/iki_read/c/eki/process.h
level_3/iki_read/c/iki/print.c
level_3/iki_read/c/iki/print.h
level_3/iki_read/c/iki/process.c
level_3/iki_read/c/iki/process.h
level_3/iki_read/c/main/common/print.c
level_3/iki_read/c/main/common/print.h
level_3/iki_read/c/main/common/type.c
level_3/iki_read/c/main/common/type.h
level_3/iki_read/c/main/print/data.c
level_3/iki_read/c/main/print/data.h
level_3/iki_read/c/main/process.c
level_3/iki_read/c/main/process.h
level_3/iki_read/data/build/testfile

index 743ede7c7a367e4f2b2bc0c359314210de2a1f81..35bada7a7ad240baeec8e370e6780bd6bcd7b7af 100644 (file)
@@ -17,16 +17,24 @@ extern "C" {
 
     if (index >= data->vocabularys.used) return;
 
-    f_number_unsigned_t at = main->setting.reassign.used;
+    // @todo This needs to handle order of operations such that it does not return immediately after say a reassign or a substitution.
+    //       When a substitution or a re-assign is matched, then all things to the right can be ignored.
+
+    f_number_unsigned_t i = 0;
+    f_number_unsigned_t j = main->setting.reassign.used;
     f_range_t range = f_range_t_initialize;
 
-    if (main->setting.reassign.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
-      at = iki_read_identify_substitution(main, data->vocabularys.array[index].array[0], data->content.array[index], &main->setting.reassign);
-    }
+    for (; i < data->vocabularys.array[index].used; ++i) {
+
+      if (main->setting.reassign.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+        j = iki_read_identify_substitution(main, data->vocabularys.array[index].array[i], data->content.array[index], &main->setting.reassign);
+        if (j < main->setting.reassign.used) break;
+      }
+    } // for
 
-    if (at < main->setting.reassign.used) {
+    if (j < main->setting.reassign.used) {
       if (main->setting.flag & iki_read_main_flag_content_d) {
-        f_print_dynamic(main->setting.reassign.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.reassign.array[j].c, main->program.output.to);
       }
       else {
         range.start = data->variable.array[index].start;
@@ -34,7 +42,7 @@ extern "C" {
 
         f_print_dynamic_partial(main->cache.buffer, range, main->program.output.to);
 
-        f_print_dynamic(main->setting.reassign.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.reassign.array[j].c, main->program.output.to);
 
         range.start = data->content.array[index].stop + 1;
         range.stop = data->variable.array[index].stop;
@@ -45,17 +53,21 @@ extern "C" {
       return;
     }
 
-    at = main->setting.substitute.used;
+    j = main->setting.substitute.used;
 
-    if (main->setting.substitute.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
-      at = iki_read_identify_substitution(main, data->vocabularys.array[index].array[0], data->content.array[index], &main->setting.substitute);
-    }
+    for (i = 0; i < data->vocabularys.array[index].used; ++i) {
+
+      if (main->setting.substitute.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+        j = iki_read_identify_substitution(main, data->vocabularys.array[index].array[i], data->content.array[index], &main->setting.substitute);
+        if (j < main->setting.substitute.used) break;
+      }
+    } // for
 
-    if (at < main->setting.substitute.used) {
+    if (j < main->setting.substitute.used) {
       if (main->setting.flag & iki_read_main_flag_content_d) {
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        f_print_dynamic(main->setting.substitute.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.substitute.array[j].c, main->program.output.to);
 
         iki_read_print_data_wrap_append(&main->program.output, index);
       }
@@ -67,7 +79,7 @@ extern "C" {
 
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        f_print_dynamic(main->setting.substitute.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.substitute.array[j].c, main->program.output.to);
 
         iki_read_print_data_wrap_append(&main->program.output, index);
 
@@ -81,10 +93,10 @@ extern "C" {
       if (main->setting.flag & iki_read_main_flag_content_d) {
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        for (at = 0; at < main->setting.map_replacess.array[index].used; ++at) {
+        for (j = 0; j < main->setting.map_replacess.array[index].used; ++j) {
 
-          if (main->setting.map_replacess.array[index].array[at] < main->setting.replace.used) {
-            f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[at]].value, main->program.output.to);
+          if (main->setting.map_replacess.array[index].array[j] < main->setting.replace.used) {
+            f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[j]].value, main->program.output.to);
           }
         } // for
 
@@ -97,10 +109,10 @@ extern "C" {
           }
         }
         else {
-          for (at = 0; at < main->setting.map_replacess.array[index].used; ++at) {
+          for (j = 0; j < main->setting.map_replacess.array[index].used; ++j) {
 
-            if (main->setting.map_replacess.array[index].array[at] < main->setting.replace.used) {
-              f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[at]].key, main->program.output.to);
+            if (main->setting.map_replacess.array[index].array[j] < main->setting.replace.used) {
+              f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[j]].key, main->program.output.to);
             }
           } // for
         }
@@ -113,14 +125,13 @@ extern "C" {
 
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        for (at = 0; at < main->setting.map_replacess.array[index].used; ++at) {
+        for (j = 0; j < main->setting.map_replacess.array[index].used; ++j) {
 
-          if (main->setting.map_replacess.array[index].array[at] < main->setting.replace.used) {
-            f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[at]].value, main->program.output.to);
+          if (main->setting.map_replacess.array[index].array[j] < main->setting.replace.used) {
+            f_print_dynamic(main->setting.replace.array[main->setting.map_replacess.array[index].array[j]].value, main->program.output.to);
           }
         } // for
 
-
         iki_read_print_data_wrap_append(&main->program.output, index);
 
         range.start = data->content.array[index].stop + 1;
@@ -143,11 +154,11 @@ extern "C" {
         }
       }
       else {
-        for (at = 0; at < data->vocabularys.array[index].used; ) {
+        for (j = 0; j < data->vocabularys.array[index].used; ) {
 
-          f_print_dynamic_partial(main->cache.buffer, data->vocabularys.array[index].array[at], main->program.output.to);
+          f_print_dynamic_partial(main->cache.buffer, data->vocabularys.array[index].array[j], main->program.output.to);
 
-          if (++at < data->vocabularys.array[index].used) {
+          if (++j < data->vocabularys.array[index].used) {
             f_print_dynamic_raw(f_string_space_s, print->to);
           }
         } // for
index cef4cd9486be6bf0fbc8699ece2f59e3aa6f9780..3eeb09b02a9e85d9b8934f588e9b62bca27d056d 100644 (file)
@@ -38,8 +38,8 @@ extern "C" {
  * @see f_print_dynamic_partial()
  *
  * @see iki_read_identify_substitution()
- * @see iki_read_print_data_wrap_prepend()
  * @see iki_read_print_data_wrap_append()
+ * @see iki_read_print_data_wrap_prepend()
  */
 #ifndef _di_iki_read_eki_print_data_
   extern void iki_read_eki_print_data(fl_print_t * const print, const f_number_unsigned_t index);
index 87911666a762f6210ce906b13c506dc7444c7624..006a7c2968ba93e5ff336f548bd8197e921bec47 100644 (file)
@@ -4,6 +4,211 @@
 extern "C" {
 #endif
 
+#ifndef _di_iki_read_eki_process_buffer_line_
+  void iki_read_eki_process_buffer_line(iki_read_main_t * const main, const f_number_unsigned_t index) {
+
+    if (!main || F_status_is_error(main->setting.state.status)) return;
+
+    // @todo replace all of this with what is in iki_read_eki_print_data() once that is updated/fixed appropriately.
+
+    if (!main->data) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+    }
+    else {
+      f_iki_eki_t * const data = (f_iki_eki_t *) main->data;
+
+      if (index >= data->vocabularys.used) {
+        main->setting.state.status = F_data_not;
+
+        return;
+      }
+
+      f_number_unsigned_t i = main->setting.reassign.used;
+      f_number_unsigned_t j = 0;
+      f_range_t range = f_range_t_initialize;
+
+      // @todo this needs to handle all j where .array[0].
+      if (main->setting.reassign.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+        i = iki_read_identify_substitution(main, data->vocabularys.array[index].array[0], data->content.array[index], &main->setting.reassign);
+      }
+
+      if (i < main->setting.reassign.used) {
+        if (main->setting.flag & iki_read_main_flag_content_d) {
+          main->setting.state.status = f_string_dynamic_append_nulless(main->setting.reassign.array[i].c, &main->cache.expand);
+        }
+        else {
+          range.start = data->variable.array[index].start;
+          range.stop = data->content.array[index].start - 1;
+
+          main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_append_nulless(main->setting.reassign.array[i].c, &main->cache.expand);
+          }
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            range.start = data->content.array[index].stop + 1;
+            range.stop = data->variable.array[index].stop;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+          }
+        }
+      }
+      else {
+        i = main->setting.substitute.used;
+
+        if (main->setting.substitute.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+          i = iki_read_identify_substitution(main, data->vocabularys.array[index].array[0], data->content.array[index], &main->setting.substitute);
+        }
+
+        if (i < main->setting.substitute.used) {
+          if (main->setting.flag & iki_read_main_flag_content_d) {
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.substitute.array[i].c, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+          }
+          else {
+            range.start = data->variable.array[index].start;
+            range.stop = data->content.array[index].start - 1;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.substitute.array[i].c, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              range.start = data->content.array[index].stop + 1;
+              range.stop = data->variable.array[index].stop;
+
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+            }
+          }
+        }
+        else if (main->setting.replace.used && main->setting.map_replacess.array[index].used) {
+          if (main->setting.flag & iki_read_main_flag_content_d) {
+            iki_read_process_wrap_prepend(main, index);
+
+            for (i = 0; F_status_is_error_not(main->setting.state.status) && i < main->setting.map_replacess.array[index].used; ++i) {
+
+              if (main->setting.map_replacess.array[index].array[i] < main->setting.replace.used) {
+                main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[i]].value, &main->cache.expand);
+              }
+            } // for
+
+            iki_read_process_wrap_append(main, index);
+          }
+          else if (main->setting.flag & iki_read_main_flag_object_d) {
+            if (main->setting.flag & iki_read_main_flag_select_d) {
+              if (main->setting.select < main->setting.map_replacess.array[index].used) {
+                main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[main->setting.select]].key, &main->cache.expand);
+              }
+            }
+            else {
+              for (i = 0; F_status_is_error_not(main->setting.state.status) && i < main->setting.map_replacess.array[index].used; ++i) {
+
+                if (main->setting.map_replacess.array[index].array[i] < main->setting.replace.used) {
+                  main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[i]].key, &main->cache.expand);
+                }
+              } // for
+            }
+          }
+          else {
+            range.start = data->variable.array[index].start;
+            range.stop = data->content.array[index].start - 1;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+            iki_read_process_wrap_prepend(main, index);
+
+            for (i = 0; F_status_is_error_not(main->setting.state.status) && i < main->setting.map_replacess.array[index].used; ++i) {
+
+              if (main->setting.map_replacess.array[index].array[i] < main->setting.replace.used) {
+                main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[i]].value, &main->cache.expand);
+              }
+            } // for
+
+
+            iki_read_process_wrap_append(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              range.start = data->content.array[index].stop + 1;
+              range.stop = data->variable.array[index].stop;
+
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+            }
+          }
+        }
+        else if (main->setting.flag & iki_read_main_flag_content_d) {
+          iki_read_process_wrap_prepend(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->content.array[index], &main->cache.expand);
+          }
+
+          iki_read_process_wrap_append(main, index);
+        }
+        else if (main->setting.flag & iki_read_main_flag_object_d) {
+          if (main->setting.flag & iki_read_main_flag_select_d) {
+            if (main->setting.select < data->vocabularys.array[index].used) {
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->vocabularys.array[index].array[main->setting.select], &main->cache.expand);
+            }
+          }
+          else {
+            for (i = 0; F_status_is_error_not(main->setting.state.status) && i < data->vocabularys.array[index].used; ) {
+
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->vocabularys.array[index].array[i], &main->cache.expand);
+
+              if (F_status_is_error_not(main->setting.state.status)) {
+                if (++i < data->vocabularys.array[index].used) {
+                  main->setting.state.status = f_string_dynamic_append_nulless(f_string_space_s, &main->cache.expand);
+                }
+              }
+            } // for
+          }
+        }
+        else {
+          range.start = data->variable.array[index].start;
+          range.stop = data->content.array[index].start - 1;
+
+          main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+          iki_read_process_wrap_prepend(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->content.array[index], &main->cache.expand);
+          }
+
+          iki_read_process_wrap_append(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            range.start = data->content.array[index].stop + 1;
+            range.stop = data->variable.array[index].stop;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+          }
+        }
+      }
+    }
+
+    if (F_status_is_error(main->setting.state.status)) {
+      iki_read_print_error(&main->program.error, macro_iki_read_f(iki_read_callback_process_buffer_line));
+
+      return;
+    }
+
+    main->setting.state.status = main->cache.expand.used ? F_okay : F_data_not;
+  }
+#endif // _di_iki_read_eki_process_buffer_line_
+
 #ifndef _di_iki_read_eki_process_buffer_ranges_
   void iki_read_eki_process_buffer_ranges(iki_read_main_t * const main, f_range_t * const range_buffer) {
 
@@ -14,100 +219,106 @@ extern "C" {
     iki_read_eki_process_buffer_ranges_prepare(main, range_buffer, data);
     if (F_status_is_error(main->setting.state.status)) return;
 
-    if ((main->setting.flag & iki_read_main_flag_total_d) && !(main->setting.flag & iki_read_main_flag_name_d)) {
-      fll_print_format(
-        "%ul%r",
-        main->program.output.to,
-        (main->setting.flag & iki_read_main_flag_at_d)
-          ? main->setting.at < data->variable.used ? 1 : 0
-          : data->variable.used,
-        f_string_eol_s
-      );
-
-      main->setting.state.status = F_okay;
-
-      return;
-    }
-
     // When --at and --line are specified, the only value for --line that will print anything is 0 when using --object.
     if ((main->setting.flag & iki_read_main_flag_at_d) && (main->setting.flag & iki_read_main_flag_line_d)) {
       if ((main->setting.flag & iki_read_main_flag_object_d) && main->setting.line) {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          fll_print_format("0%r", main->program.output.to, f_string_eol_s);
+        }
+
         main->setting.state.status = F_data_not;
 
         return;
       }
     }
 
+    main->cache.expand.used = 0;
+
     f_number_unsigned_t i = 0;
+    f_number_unsigned_t j = 0;
 
     if (main->setting.flag & iki_read_main_flag_name_d) {
-      f_number_unsigned_t j = 0;
+      f_number_unsigned_t k = 0;
       f_number_unsigned_t matches = 0;
-      uint8_t unmatched = 0x1; // 0x1 = unmatched, 0x2 = line break.
-
-      if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-        f_file_stream_lock(main->program.output.to);
-      }
+      uint8_t matched = 0x0; // 0x0 = unmatched, 0x1 = matched.
 
       for (i = 0; i < data->vocabularys.used; ++i) {
 
-        if (iki_read_signal_check(main)) {
-          if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-            f_file_stream_unlock(main->program.output.to);
-          }
+        if (iki_read_signal_check(main)) return;
 
-          return;
-        }
+        for (j = 0; j < data->vocabularys.array[i].used; ++j) {
 
-        for (j = 0; j < main->setting.names.used; ++j) {
+          if (iki_read_signal_check(main)) return;
 
-          if (iki_read_signal_check(main)) {
-            if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-              f_file_stream_unlock(main->program.output.to);
-            }
+          for (k = 0; k < main->setting.names.used; ++k) {
 
-            return;
-          }
+            if (iki_read_signal_check(main)) return;
+
+            if (f_compare_dynamic_partial_string(main->setting.names.array[k].string, main->cache.buffer, main->setting.names.array[k].used, data->vocabularys.array[i].array[j]) == F_equal_to) {
+              matched |= 0x1;
 
-          if (f_compare_dynamic_partial_string(main->setting.names.array[j].string, main->cache.buffer, main->setting.names.array[j].used, data->vocabularys.array[i].array[0]) == F_equal_to) {
-            unmatched &= ~0x1;
+              if (main->setting.flag & iki_read_main_flag_at_d) {
+                if (matches < main->setting.at) {
+                  matches++;
 
-            if (main->setting.flag & iki_read_main_flag_at_d) {
-              if (matches < main->setting.at) {
-                matches++;
+                  continue;
+                }
 
-                continue;
+                if (matches++ > main->setting.at) break;
               }
 
-              if (matches++ > main->setting.at) break;
-            }
+              if (main->setting.flag & iki_read_main_flag_total_d) {
+                if (!(main->setting.flag & iki_read_main_flag_at_d)) {
+                  ++matches;
+                }
+
+                if (main->setting.flag & iki_read_main_flag_line_d) { // @todo handle --at.
+                  iki_read_eki_process_buffer_line(main, i);
 
-            if (main->setting.flag & iki_read_main_flag_total_d) {
-              if (!(main->setting.flag & iki_read_main_flag_at_d)) {
-                ++matches;
+                  // Ensure that a newline is always at the end.
+                  if (main->setting.state.status == F_okay) {
+                    main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+                  }
+                }
               }
-            }
-            else {
-              if (main->callback.print_data) {
-                main->callback.print_data(&main->program.output, i);
+              else if (main->setting.flag & iki_read_main_flag_line_d) {
+                iki_read_eki_process_buffer_line(main, i);
+
+                // Ensure that a newline is always at the end.
+                if (main->setting.state.status == F_okay) {
+                  main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+                }
               }
+              else {
+                f_file_stream_lock(main->program.output.to);
 
-              f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+                if (main->callback.print_data) {
+                  main->callback.print_data(&main->program.output, i);
+                }
+
+                f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+                f_file_stream_unlock(main->program.output.to);
+              }
             }
-          }
+          } // for
         } // for
-
-        if (unmatched & 0x2) break;
       } // for
 
-      if ((main->setting.flag & iki_read_main_flag_total_d)) {
-        fll_print_format(
-          "%ul%r",
-          main->program.output.to,
-          (main->setting.flag & iki_read_main_flag_at_d)
+      if (main->setting.flag & iki_read_main_flag_line_d) {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          iki_read_print_data_line_total(&main->program.output);
+        }
+        else {
+          iki_read_print_data_line(&main->program.output);
+        }
+      }
+      else if ((main->setting.flag & iki_read_main_flag_total_d)) {
+        iki_read_print_data_total(
+          &main->program.output,
+          (main->setting.flag & iki_read_main_flag_line_d)
             ? main->setting.at < matches ? 1 : 0
-            : matches,
-          f_string_eol_s
+            : matches
         );
 
         main->setting.state.status = F_okay;
@@ -118,28 +329,69 @@ extern "C" {
         f_file_stream_unlock(main->program.output.to);
       }
 
-      main->setting.state.status = (unmatched & 0x1) ? F_data_not : F_okay;
+      main->setting.state.status = matched ? F_okay : F_data_not;
     }
     else {
       if (data->variable.used) {
         if (main->setting.flag & iki_read_main_flag_at_d) {
           if (main->setting.at < data->variable.used) {
-            f_file_stream_lock(main->program.output.to);
+            if (main->setting.flag & iki_read_main_flag_line_d) {
+              iki_read_eki_process_buffer_line(main, main->setting.at);
 
-            if (main->callback.print_data) {
-              main->callback.print_data(&main->program.output, main->setting.at);
+              // Ensure that a newline is always at the end.
+              if (main->setting.state.status == F_okay) {
+                main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+              }
+
+              if (main->setting.flag & iki_read_main_flag_total_d) {
+                iki_read_print_data_line_total(&main->program.output);
+              }
+              else {
+                iki_read_print_data_line(&main->program.output);
+              }
             }
+            else {
+              f_file_stream_lock(main->program.output.to);
 
-            f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+              if (main->callback.print_data) {
+                main->callback.print_data(&main->program.output, main->setting.at);
+              }
+
+              f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+              f_file_stream_unlock(main->program.output.to);
 
-            f_file_stream_unlock(main->program.output.to);
+              main->setting.state.status = F_okay;
+            }
 
-            main->setting.state.status = F_okay;
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = F_okay;
+            }
           }
           else {
             main->setting.state.status = F_data_not;
           }
         }
+        else if (main->setting.flag & iki_read_main_flag_line_d) {
+          for (i = 0; F_status_is_error_not(main->setting.state.status) && i < data->variable.used; ++i) {
+
+            if (iki_read_signal_check(main)) return;
+
+            iki_read_eki_process_buffer_line(main, i);
+
+            // Ensure that a newline is always at the end.
+            if (main->setting.state.status == F_okay) {
+              main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+            }
+          } // for
+
+          if (main->setting.flag & iki_read_main_flag_total_d) {
+            iki_read_print_data_line_total(&main->program.output);
+          }
+          else {
+            iki_read_print_data_line(&main->program.output);
+          }
+        }
         else {
           f_file_stream_lock(main->program.output.to);
 
@@ -147,12 +399,6 @@ extern "C" {
 
             if (iki_read_signal_check(main)) return;
 
-            // The variable parts, when not using --wrap, each is represented on its own line.
-            if (main->setting.flag & iki_read_main_flag_line_d) {
-              if (i < main->setting.line) continue;
-              if (i > main->setting.line) break;
-            }
-
             if (main->callback.print_data) {
               main->callback.print_data(&main->program.output, i);
             }
@@ -166,6 +412,10 @@ extern "C" {
         }
       }
       else {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          iki_read_print_data_total(&main->program.output, 0);
+        }
+
         main->setting.state.status = F_data_not;
       }
     }
@@ -345,7 +595,7 @@ extern "C" {
 
       f_range_t range = macro_f_range_t_initialize_2(main->cache.buffer.used);
 
-      iki_read_process_line(main, &range);
+      iki_read_process_line(main, &range); // @fixme is this valid here anymore?
 
       if (main->setting.state.status == F_true || main->setting.state.status == F_data_not) {
         if (main->setting.state.status == F_data_not || range.start > main->cache.buffer.used) {
@@ -380,6 +630,7 @@ extern "C" {
 
           f_number_unsigned_t index = 0;
           f_number_unsigned_t j = 0;
+          f_number_unsigned_t k = 0;
 
           range.start = 0;
 
@@ -404,9 +655,16 @@ extern "C" {
 
             for (j = 0; j < data->vocabularys.used; ++j) {
 
-              main->setting.state.status = f_compare_dynamic_partial(name, main->cache.buffer, range, data->vocabularys.array[j].array[0]);
+              if (iki_read_signal_check(main)) return;
+
+              for (k = 0; k < data->vocabularys.array[j].used; ++k) {
+
+                if (iki_read_signal_check(main)) return;
+
+                main->setting.state.status = f_compare_dynamic_partial(name, main->cache.buffer, range, data->vocabularys.array[j].array[k]);
 
-              if (main->setting.state.status == F_equal_to) ++total;
+                if (main->setting.state.status == F_equal_to) ++total;
+              } // for
             } // for
           } // for
 
@@ -423,7 +681,7 @@ extern "C" {
       }
     }
 
-    fll_print_format("%ul%r", main->program.output.to, total, f_string_eol_s);
+    iki_read_print_data_total(&main->program.output, total);
 
     main->setting.state.status = F_okay;
   }
index b306449ee1242e543f242acf212782004538a76f..492c83752a29b7ce9038f3e0310505a7f7aeeccb 100644 (file)
@@ -17,6 +17,35 @@ extern "C" {
 #endif
 
 /**
+ * Print the given range at the given index for EKI read, for when printing a single Line in Content and Literal modes.
+ *
+ * This expects the caller to have the output locked appropriately.
+ *
+ * This detects and prints any applicable substitution matching the vocabulary at the given index.
+ * If there is no substitution, then this prints the given range at the given index.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   The setting.map_wrapss is expected to be defined as a valid pointer to an array.
+ *   The setting.map_replacess is expected to be defined as a valid pointer to an array.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param index
+ *   The index used to identify the desired range in variable, content, and ranges.
+ *
+ * @see f_print_dynamic()
+ * @see f_print_dynamic_partial()
+ *
+ * @see iki_read_identify_substitution()
+ * @see iki_read_print_data_wrap_append()
+ * @see iki_read_print_data_wrap_prepend()
+ */
+#ifndef _di_iki_read_eki_process_buffer_line_
+  extern void iki_read_eki_process_buffer_line(iki_read_main_t * const main, const f_number_unsigned_t index);
+#endif // _di_iki_read_eki_process_buffer_line_
+
+/**
  * Process a given buffer, printing the given range for EKI read.
  *
  * @param main
index 01916ad648adce202f9c92502e5b04386d56a1f6..a948f0f30ccf2cac91763ab146a1f6e878f86590 100644 (file)
@@ -17,16 +17,16 @@ extern "C" {
 
     if (index >= data->vocabulary.used) return;
 
-    f_number_unsigned_t at = main->setting.reassign.used;
+    f_number_unsigned_t i = main->setting.reassign.used;
     f_range_t range = f_range_t_initialize;
 
     if (main->setting.reassign.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
-      at = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.reassign);
+      i = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.reassign);
     }
 
-    if (at < main->setting.reassign.used) {
+    if (i < main->setting.reassign.used) {
       if (main->setting.flag & iki_read_main_flag_content_d) {
-        f_print_dynamic(main->setting.reassign.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.reassign.array[i].c, main->program.output.to);
       }
       else {
         range.start = data->variable.array[index].start;
@@ -34,7 +34,7 @@ extern "C" {
 
         f_print_dynamic_partial(main->cache.buffer, range, main->program.output.to);
 
-        f_print_dynamic(main->setting.reassign.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.reassign.array[i].c, main->program.output.to);
 
         range.start = data->content.array[index].stop + 1;
         range.stop = data->variable.array[index].stop;
@@ -45,17 +45,17 @@ extern "C" {
       return;
     }
 
-    at = main->setting.substitute.used;
+    i = main->setting.substitute.used;
 
     if (main->setting.substitute.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
-      at = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.substitute);
+      i = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.substitute);
     }
 
-    if (at < main->setting.substitute.used) {
+    if (i < main->setting.substitute.used) {
       if (main->setting.flag & iki_read_main_flag_content_d) {
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        f_print_dynamic(main->setting.substitute.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.substitute.array[i].c, main->program.output.to);
 
         iki_read_print_data_wrap_append(&main->program.output, index);
       }
@@ -67,7 +67,7 @@ extern "C" {
 
         iki_read_print_data_wrap_prepend(&main->program.output, index);
 
-        f_print_dynamic(main->setting.substitute.array[at].c, main->program.output.to);
+        f_print_dynamic(main->setting.substitute.array[i].c, main->program.output.to);
 
         iki_read_print_data_wrap_append(&main->program.output, index);
 
index 371e2a9e9c17e21b9a8c5945f529402e659aaed2..2b325848c0fd32304b84928d49b9e2b6f3e96cbe 100644 (file)
@@ -38,8 +38,8 @@ extern "C" {
  * @see f_print_dynamic_partial()
  *
  * @see iki_read_identify_substitution()
- * @see iki_read_print_data_wrap_prepend()
  * @see iki_read_print_data_wrap_append()
+ * @see iki_read_print_data_wrap_prepend()
  */
 #ifndef _di_iki_read_iki_print_data_
   extern void iki_read_iki_print_data(fl_print_t * const print, const f_number_unsigned_t index);
index d0fdecb62bf62015ac010a3e16bed33d81fc12ab..6d0b0a740482f91cff6cf337bc5a91743c6f36b5 100644 (file)
@@ -4,6 +4,183 @@
 extern "C" {
 #endif
 
+#ifndef _di_iki_read_iki_process_buffer_line_
+  void iki_read_iki_process_buffer_line(iki_read_main_t * const main, const f_number_unsigned_t index) {
+
+    if (!main || F_status_is_error(main->setting.state.status)) return;
+
+    const f_number_unsigned_t original = main->cache.expand.used;
+
+    if (!main->data) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+    }
+    else {
+      f_iki_data_t * const data = (f_iki_data_t *) main->data;
+
+      if (index >= data->vocabulary.used) {
+        main->setting.state.status = F_data_not;
+
+        return;
+      }
+
+      f_number_unsigned_t i = main->setting.reassign.used;
+      f_range_t range = f_range_t_initialize;
+
+      if (main->setting.reassign.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+        i = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.reassign);
+      }
+
+      if (i < main->setting.reassign.used) {
+        if (main->setting.flag & iki_read_main_flag_content_d) {
+          main->setting.state.status = f_string_dynamic_append_nulless(main->setting.reassign.array[i].c, &main->cache.expand);
+        }
+        else {
+          range.start = data->variable.array[index].start;
+          range.stop = data->content.array[index].start - 1;
+
+          main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_append_nulless(main->setting.reassign.array[i].c, &main->cache.expand);
+          }
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            range.start = data->content.array[index].stop + 1;
+            range.stop = data->variable.array[index].stop;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+          }
+        }
+      }
+      else {
+        i = main->setting.substitute.used;
+
+        if (main->setting.substitute.used && (main->setting.flag & (iki_read_main_flag_content_d | iki_read_main_flag_literal_d))) {
+          i = iki_read_identify_substitution(main, data->vocabulary.array[index], data->content.array[index], &main->setting.substitute);
+        }
+
+        if (i < main->setting.substitute.used) {
+          if (main->setting.flag & iki_read_main_flag_content_d) {
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.substitute.array[i].c, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+          }
+          else {
+            range.start = data->variable.array[index].start;
+            range.stop = data->content.array[index].start - 1;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.substitute.array[i].c, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              range.start = data->content.array[index].stop + 1;
+              range.stop = data->variable.array[index].stop;
+
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+            }
+          }
+        }
+        else if (main->setting.replace.used && main->setting.map_replacess.array[index].used) {
+          if (main->setting.flag & iki_read_main_flag_content_d) {
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status) && main->setting.map_replacess.array[index].array[0] < main->setting.replace.used) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[0]].value, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+          }
+          else if (main->setting.flag & iki_read_main_flag_object_d) {
+            if (!(main->setting.flag & iki_read_main_flag_select_d) || !main->setting.select) {
+              if (main->setting.map_replacess.array[index].array[0] < main->setting.replace.used) {
+                main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[0]].key, &main->cache.expand);
+              }
+            }
+          }
+          else {
+            range.start = data->variable.array[index].start;
+            range.stop = data->content.array[index].start - 1;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+            iki_read_process_wrap_prepend(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status) && main->setting.map_replacess.array[index].array[0] < main->setting.replace.used) {
+              main->setting.state.status = f_string_dynamic_append_nulless(main->setting.replace.array[main->setting.map_replacess.array[index].array[0]].value, &main->cache.expand);
+            }
+
+            iki_read_process_wrap_append(main, index);
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              range.start = data->content.array[index].stop + 1;
+              range.stop = data->variable.array[index].stop;
+
+              main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+            }
+          }
+        }
+        else if (main->setting.flag & iki_read_main_flag_content_d) {
+          iki_read_process_wrap_prepend(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->content.array[index], &main->cache.expand);
+          }
+
+          iki_read_process_wrap_append(main, index);
+        }
+        else if (main->setting.flag & iki_read_main_flag_object_d) {
+          if (!(main->setting.flag & iki_read_main_flag_select_d) || !main->setting.select) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->vocabulary.array[index], &main->cache.expand);
+          }
+          else if ((main->setting.flag & iki_read_main_flag_select_d) && main->setting.select) {
+            main->setting.state.status = F_data_not;
+          }
+        }
+        else {
+          range.start = data->variable.array[index].start;
+          range.stop = data->content.array[index].start - 1;
+
+          main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+
+          iki_read_process_wrap_prepend(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, data->content.array[index], &main->cache.expand);
+          }
+
+          iki_read_process_wrap_append(main, index);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            range.start = data->content.array[index].stop + 1;
+            range.stop = data->variable.array[index].stop;
+
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.expand);
+          }
+        }
+      }
+    }
+
+    if (F_status_is_error(main->setting.state.status)) {
+      iki_read_print_error(&main->program.error, macro_iki_read_f(iki_read_callback_process_buffer_line));
+
+      return;
+    }
+
+    main->setting.state.status = main->cache.expand.used == original ? F_data_not : F_okay;
+  }
+#endif // _di_iki_read_iki_process_buffer_line_
+
 #ifndef _di_iki_read_iki_process_buffer_ranges_
   void iki_read_iki_process_buffer_ranges(iki_read_main_t * const main, f_range_t * const range_buffer) {
 
@@ -14,63 +191,38 @@ extern "C" {
     iki_read_iki_process_buffer_ranges_prepare(main, range_buffer, data);
     if (F_status_is_error(main->setting.state.status)) return;
 
-    if ((main->setting.flag & iki_read_main_flag_total_d) && !(main->setting.flag & iki_read_main_flag_name_d)) {
-      fll_print_format(
-        "%ul%r",
-        main->program.output.to,
-        (main->setting.flag & iki_read_main_flag_at_d)
-          ? main->setting.at < data->variable.used ? 1 : 0
-          : data->variable.used,
-        f_string_eol_s
-      );
-
-      main->setting.state.status = F_okay;
-
-      return;
-    }
-
     // When --at and --line are specified, the only value for --line that will print anything is 0 when using --object.
     if ((main->setting.flag & iki_read_main_flag_at_d) && (main->setting.flag & iki_read_main_flag_line_d)) {
       if ((main->setting.flag & iki_read_main_flag_object_d) && main->setting.line) {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          fll_print_format("0%r", main->program.output.to, f_string_eol_s);
+        }
+
         main->setting.state.status = F_data_not;
 
         return;
       }
     }
 
+    main->cache.expand.used = 0;
+
     f_number_unsigned_t i = 0;
 
     if (main->setting.flag & iki_read_main_flag_name_d) {
       f_number_unsigned_t j = 0;
       f_number_unsigned_t matches = 0;
-      uint8_t unmatched = 0x1; // 0x1 = unmatched, 0x2 = line break.
-
-      if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-        f_file_stream_lock(main->program.output.to);
-      }
+      uint8_t matched = 0x0; // 0x0 = unmatched, 0x1 = matched.
 
       for (i = 0; i < data->vocabulary.used; ++i) {
 
-        if (iki_read_signal_check(main)) {
-          if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-            f_file_stream_unlock(main->program.output.to);
-          }
-
-          return;
-        }
+        if (iki_read_signal_check(main)) return;
 
         for (j = 0; j < main->setting.names.used; ++j) {
 
-          if (iki_read_signal_check(main)) {
-            if (!(main->setting.flag & iki_read_main_flag_total_d)) {
-              f_file_stream_unlock(main->program.output.to);
-            }
-
-            return;
-          }
+          if (iki_read_signal_check(main)) return;
 
           if (f_compare_dynamic_partial_string(main->setting.names.array[j].string, main->cache.buffer, main->setting.names.array[j].used, data->vocabulary.array[i]) == F_equal_to) {
-            unmatched &= ~0x1;
+            matched |= 0x1;
 
             if (main->setting.flag & iki_read_main_flag_at_d) {
               if (matches < main->setting.at) {
@@ -86,60 +238,131 @@ extern "C" {
               if (!(main->setting.flag & iki_read_main_flag_at_d)) {
                 ++matches;
               }
+
+              if (main->setting.flag & iki_read_main_flag_line_d) { // @todo handle --at.
+                iki_read_iki_process_buffer_line(main, i);
+
+                // Ensure that a newline is always at the end.
+                if (main->setting.state.status == F_okay) {
+                  main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+                }
+              }
+            }
+            else if (main->setting.flag & iki_read_main_flag_line_d) {
+              iki_read_iki_process_buffer_line(main, i);
+
+              // Ensure that a newline is always at the end.
+              if (main->setting.state.status == F_okay) {
+                main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+              }
             }
             else {
+              f_file_stream_lock(main->program.output.to);
+
               if (main->callback.print_data) {
                 main->callback.print_data(&main->program.output, i);
               }
 
               f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+              f_file_stream_unlock(main->program.output.to);
             }
           }
         } // for
-
-        if (unmatched & 0x2) break;
       } // for
 
-      if (main->setting.flag & iki_read_main_flag_total_d) {
-        fll_print_format(
-          "%ul%r",
-          main->program.output.to,
-          (main->setting.flag & iki_read_main_flag_at_d)
-            ? main->setting.at < matches ? 1 : 0
-            : matches,
-          f_string_eol_s
-        );
+      if (main->setting.flag & iki_read_main_flag_line_d) {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          iki_read_print_data_line_total(&main->program.output);
+        }
+        else {
+          iki_read_print_data_line(&main->program.output);
+        }
+      }
+      else if (main->setting.flag & iki_read_main_flag_total_d) {
+        if (main->setting.flag & iki_read_main_flag_line_d) {
+          for (i = 0; F_status_is_error_not(main->setting.state.status) && i < data->variable.used; ++i) {
+
+            if (iki_read_signal_check(main)) return;
 
-        main->setting.state.status = F_okay;
+            iki_read_iki_process_buffer_line(main, i);
+
+            // Ensure that a newline is always at the end.
+            if (main->setting.state.status == F_okay) {
+              main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+            }
+          } // for
+        }
+        else {
+          iki_read_print_data_total(&main->program.output, matches);
+        }
+
+        main->setting.state.status = matched ? F_okay : F_data_not;
 
         return;
       }
-      else {
-        f_file_stream_unlock(main->program.output.to);
-      }
 
-      main->setting.state.status = (unmatched & 0x1) ? F_data_not : F_okay;
+      main->setting.state.status = matched ? F_okay : F_data_not;
     }
     else {
       if (data->variable.used) {
         if (main->setting.flag & iki_read_main_flag_at_d) {
-          if ((main->setting.flag & iki_read_main_flag_line_d) && main->setting.line < data->variable.used && !main->setting.at || main->setting.at < data->variable.used) {
-            f_file_stream_lock(main->program.output.to);
+          if (main->setting.at < data->variable.used) {
+            if (main->setting.flag & iki_read_main_flag_line_d) {
+              iki_read_iki_process_buffer_line(main, main->setting.at);
 
-            if (main->callback.print_data) {
-              main->callback.print_data(&main->program.output, (main->setting.flag & iki_read_main_flag_line_d) ? main->setting.line : main->setting.at);
+              // Ensure that a newline is always at the end.
+              if (main->setting.state.status == F_okay) {
+                main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+              }
+
+              if (main->setting.flag & iki_read_main_flag_total_d) {
+                iki_read_print_data_line_total(&main->program.output);
+              }
+              else {
+                iki_read_print_data_line(&main->program.output);
+              }
             }
+            else {
+              f_file_stream_lock(main->program.output.to);
 
-            f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+              if (main->callback.print_data) {
+                main->callback.print_data(&main->program.output, main->setting.at);
+              }
 
-            f_file_stream_unlock(main->program.output.to);
+              f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
 
-            main->setting.state.status = F_okay;
+              f_file_stream_unlock(main->program.output.to);
+            }
+
+            if (F_status_is_error_not(main->setting.state.status)) {
+              main->setting.state.status = F_okay;
+            }
           }
           else {
             main->setting.state.status = F_data_not;
           }
         }
+        else if (main->setting.flag & iki_read_main_flag_line_d) {
+          for (i = 0; F_status_is_error_not(main->setting.state.status) && i < data->variable.used; ++i) {
+
+            if (iki_read_signal_check(main)) return;
+
+            iki_read_iki_process_buffer_line(main, i);
+
+            // Ensure that a newline is always at the end.
+            if (main->setting.state.status == F_okay) {
+              main->setting.state.status = f_string_dynamic_append(f_string_eol_s, &main->cache.expand);
+            }
+          } // for
+
+          if (main->setting.flag & iki_read_main_flag_total_d) {
+            iki_read_print_data_line_total(&main->program.output);
+          }
+          else {
+            iki_read_print_data_line(&main->program.output);
+          }
+        }
         else {
           f_file_stream_lock(main->program.output.to);
 
@@ -147,12 +370,6 @@ extern "C" {
 
             if (iki_read_signal_check(main)) return;
 
-            // The variable parts, when not using --wrap, each is represented on its own line.
-            if (main->setting.flag & iki_read_main_flag_line_d) {
-              if (i < main->setting.line) continue;
-              if (i > main->setting.line) break;
-            }
-
             if (main->callback.print_data) {
               main->callback.print_data(&main->program.output, i);
             }
@@ -166,6 +383,10 @@ extern "C" {
         }
       }
       else {
+        if (main->setting.flag & iki_read_main_flag_total_d) {
+          iki_read_print_data_total(&main->program.output, 0);
+        }
+
         main->setting.state.status = F_data_not;
       }
     }
@@ -339,7 +560,7 @@ extern "C" {
 
       f_range_t range = macro_f_range_t_initialize_2(main->cache.buffer.used);
 
-      iki_read_process_line(main, &range);
+      iki_read_process_line(main, &range); // @fixme is this valid here anymore?
 
       if (main->setting.state.status == F_true || main->setting.state.status == F_data_not) {
         if (main->setting.state.status == F_data_not || range.start > main->cache.buffer.used) {
@@ -398,6 +619,8 @@ extern "C" {
 
             for (j = 0; j < data->vocabulary.used; ++j) {
 
+              if (iki_read_signal_check(main)) return;
+
               main->setting.state.status = f_compare_dynamic_partial(name, main->cache.buffer, range, data->vocabulary.array[j]);
 
               if (main->setting.state.status == F_equal_to) ++total;
@@ -417,7 +640,7 @@ extern "C" {
       }
     }
 
-    fll_print_format("%ul%r", main->program.output.to, total, f_string_eol_s);
+    iki_read_print_data_total(&main->program.output, total);
 
     main->setting.state.status = F_okay;
   }
index 44173a2c7ad3e5c1eeecc267278f58068f7afebe..d84896b059751e8d654830d96995c734d48964ed 100644 (file)
@@ -17,8 +17,51 @@ extern "C" {
 #endif
 
 /**
+ * Process and print the given range at the given index for IKI read, for when printing a single Line in Content and Literal modes.
+ *
+ * This expects the caller to have the output locked appropriately.????
+ *
+ * This detects and prints any applicable substitution matching the vocabulary at the given index.
+ * If there is no substitution, then this prints the given range at the given index.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ *
+ *   The setting.map_wrapss is expected to be defined as a valid pointer to an array.
+ *   The setting.map_replacess is expected to be defined as a valid pointer to an array.
+ *
+ *   This alters setting.state.status:
+ *     F_okay on success.
+ *     F_data_not on success, but nothing done.
+ *
+ *     F_interrupt (with error bit) on (exit) signal received.
+ *
+ *     Errors (with error bit) from: f_string_dynamic_append_nulless().
+ *     Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
+ *
+ *     Errors (with error bit) from: iki_read_process_wrap_append().
+ *     Errors (with error bit) from: iki_read_process_wrap_prepend().
+ * @param index
+ *   The index used to identify the desired range in variable, content, and ranges.
+ *
+ * @see f_string_dynamic_append_nulless()
+ * @see f_string_dynamic_partial_append_nulless()
+ *
+ * @see iki_read_identify_substitution()
+ * @see iki_read_process_wrap_append()
+ * @see iki_read_process_wrap_prepend()
+ */
+#ifndef _di_iki_read_iki_process_buffer_line_
+  extern void iki_read_iki_process_buffer_line(iki_read_main_t * const main, const f_number_unsigned_t index);
+#endif // _di_iki_read_iki_process_buffer_line_
+
+/**
  * Process a given buffer, printing the given range for IKI read.
  *
+ * This prints error messages.
+ *
  * @param main
  *   The main program data.
  *
@@ -28,6 +71,7 @@ extern "C" {
  *     F_okay on success.
  *     F_data_not on success, but nothing done.
  *
+ *     F_parameter (with error bit) if a parameter is invalid.
  *     F_interrupt (with error bit) on (exit) signal received.
  *
  *     Errors (with error bit) from: iki_read_iki_process_buffer_ranges_prepare().
index 0a47f481294da53865cf6ae86d0a2d0d4038aaa7..115468068e1bae2e6ce7ec17c85de54162c19829 100644 (file)
@@ -18,12 +18,18 @@ extern "C" {
     "f_memory_array_resize",
     "f_memory_arrays_resize",
     "f_string_dynamic_append_nulless",
+    "f_string_dynamic_partial_append_nulless",
     "f_string_dynamics_append",
+    "f_string_dynamics_increase_by",
+    "f_string_dynamics_resize",
     "f_thread_create",
     "fl_iki_eki_read",
     "fl_iki_read",
     "fll_program_parameter_process_context_standard",
     "fll_program_parameter_process_verbosity_standard",
+    "iki_read_callback_process_buffer_line",
+    "iki_read_process_wrap_append",
+    "iki_read_process_wrap_prepend",
   };
 #endif // _di_iki_read_f_a_
 
index deb3f068d65726164e75fbea8ac25b251d8cf060..1f5f7e7859674fc954a8a18bf85bd0585bdb34b3 100644 (file)
@@ -51,6 +51,7 @@ extern "C" {
     iki_read_f_f_memory_array_resize_e,
     iki_read_f_f_memory_arrays_resize_e,
     iki_read_f_f_string_dynamic_append_nulless_e,
+    iki_read_f_f_string_dynamic_partial_append_nulless_e,
     iki_read_f_f_string_dynamics_append_e,
     iki_read_f_f_string_dynamics_increase_by_e,
     iki_read_f_f_string_dynamics_resize_e,
@@ -59,6 +60,9 @@ extern "C" {
     iki_read_f_fl_iki_read_e,
     iki_read_f_fll_program_parameter_process_context_standard_e,
     iki_read_f_fll_program_parameter_process_verbosity_standard_e,
+    iki_read_f_iki_read_callback_process_buffer_line_e,
+    iki_read_f_iki_read_process_wrap_append_e,
+    iki_read_f_iki_read_process_wrap_prepend_e,
   }; // enum
 #endif // _di_iki_read_f_e_
 
index 8c432d9474adbc2cabe7c4ac694cc7bd5fc50631..a2612bfa1a50745ad33f71c12605221ed591dfb9 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
     if (!cache) return;
 
     f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->buffer.string, &cache->buffer.used, &cache->buffer.size);
+    f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->expand.string, &cache->expand.used, &cache->expand.size);
   }
 #endif // _di_iki_read_cache_delete_
 
index 513557a983212dcc6607494fd4568a2d96b2e45b..16cfa86632df14e16c8f1b4931fdc5b30ddcbe2c 100644 (file)
@@ -28,15 +28,18 @@ extern "C" {
  *
  * Properties:
  *   - buffer: A buffer used for loading the files and other miscellaneous tasks.
+ *   - expand: A buffer used in certain cases for the expanded output that is to be printed.
  */
 #ifndef _di_iki_read_setting_t_
   typedef struct {
     f_string_dynamic_t buffer;
+    f_string_dynamic_t expand;
   } iki_read_cache_t;
 
   #define iki_read_cache_t_initialize \
     { \
       f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
     }
 #endif // _di_iki_read_cache_t_
 
@@ -49,9 +52,9 @@ extern "C" {
  *   - print_data: Print IKI/EKI data at the given index.
  *   - print_help: Print the main help message.
  *
- *   - process_buffer_ranges: Process and print the given reange.
+ *   - process_buffer_ranges:       Process and print the given range.
  *   - process_buffer_ranges_whole: Process and print the given ranges in whole mode.
- *   - process_buffer_total: Process and print the total.
+ *   - process_buffer_total:        Process and print the total.
  *
  *   - delete_data: Delete the IKI/EKI data.
  */
index 5733337d4836ac9764dbd3b2442d0daaa32ec423..08e68b4352d74400827fda02b86c96a6b04bcc63 100644 (file)
@@ -4,6 +4,91 @@
 extern "C" {
 #endif
 
+#ifndef _di_iki_read_print_data_line_
+  void iki_read_print_data_line(fl_print_t * const print) {
+
+    if (!print || !print->custom) return;
+
+    iki_read_main_t * const main = (iki_read_main_t *) print->custom;
+
+    if (F_status_is_error(main->setting.state.status) || !main->cache.expand.used) return;
+
+    f_number_unsigned_t i = 0;
+    f_range_t range = macro_f_range_t_initialize_2(main->cache.expand.used);
+    f_status_t status;
+
+    for (f_number_unsigned_t first = 0; range.start <= range.stop && range.start < main->cache.expand.used; ) {
+
+      status = f_string_dynamic_seek_line(main->cache.expand, &range);
+      if (F_status_is_error(status)) return;
+
+      if (status == F_okay) {
+        if (i == main->setting.line) {
+          range.stop = range.start;
+          range.start = first;
+
+          f_print_dynamic_partial(main->cache.expand, range, main->program.output.to);
+
+          break;
+        }
+        else {
+          first = ++range.start;
+          ++i;
+        }
+      }
+      else {
+        if (i == main->setting.line) {
+          range.stop = range.start;
+          range.start = first;
+
+          f_print_dynamic_partial(main->cache.expand, range, main->program.output.to);
+          f_print_dynamic(f_string_eol_s, main->program.output.to);
+        }
+
+        break;
+      }
+    } // for
+  }
+#endif // _di_iki_read_print_data_line_
+
+#ifndef _di_iki_read_print_data_line_total_
+  void iki_read_print_data_line_total(fl_print_t * const print) {
+
+    if (!print || !print->custom) return;
+
+    iki_read_main_t * const main = (iki_read_main_t *) print->custom;
+
+    if (F_status_is_error(main->setting.state.status)) return;
+
+    f_number_unsigned_t total = 0;
+
+    {
+      f_range_t range = macro_f_range_t_initialize_2(main->cache.expand.used);
+
+      for (; range.start <= range.stop && range.start < main->cache.expand.used; ++total, ++range.start) {
+
+        if (iki_read_signal_check(main)) return;
+
+        main->setting.state.status = f_string_dynamic_seek_line(main->cache.expand, &range);
+        if (F_status_is_error(main->setting.state.status)) return;
+      } // for
+    }
+
+    iki_read_print_data_total(print, main->setting.line < total ? 1 : 0);
+
+    main->setting.state.status = main->setting.line < total ? F_okay : F_data_not;
+  }
+#endif // _di_iki_read_print_data_line_total_
+
+#ifndef _di_iki_read_print_data_total_
+  void iki_read_print_data_total(fl_print_t * const print, const f_number_unsigned_t total) {
+
+    if (!print) return;
+
+    fll_print_format("%ul%r", print->to, total, f_string_eol_s);
+  }
+#endif // _di_iki_read_print_data_total_
+
 #ifndef _di_iki_read_print_data_wrap_append_
   void iki_read_print_data_wrap_append(fl_print_t * const print, const f_number_unsigned_t index) {
 
index 2f02a4745941eafce19e772d1e7a25c8689b99b4..d2fd0b9dfbae0fce463a1836a9f75905b1df8c93 100644 (file)
@@ -17,6 +17,58 @@ extern "C" {
 #endif
 
 /**
+ * Print the data from the expand cache at the line.
+ *
+ * This requires that the expand cache is properly populated.
+ * The expand cache may be empty.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_read_print_data_line_
+  extern void iki_read_print_data_line(fl_print_t * const print);
+#endif // _di_iki_read_print_data_line_
+
+/**
+ * Print the total from the data in the expand cache at the line.
+ *
+ * This requires that the expand cache is properly populated.
+ * The expand cache may be empty.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_read_print_data_line_total_
+  extern void iki_read_print_data_line_total(fl_print_t * const print);
+#endif // _di_iki_read_print_data_line_total_
+
+/**
+ * Print the number that represents the total.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This alters print.custom.setting.state.status:
+ *     F_okay on success and data was processed.
+ *     F_data_not on success, but there was no data to process (0 is printed).
+ *
+ *     Signal from iki_read_signal_check().
+ *
+ *     Error (with error bit set) from f_string_dynamic_seek_line()
+ *
+ * @see f_string_dynamic_seek_line()
+ *
+ * @see iki_read_signal_check()
+ */
+#ifndef _di_iki_read_print_data_total_
+  extern void iki_read_print_data_total(fl_print_t * const print, const f_number_unsigned_t);
+#endif // _di_iki_read_print_data_total_
+
+/**
  * Print the append part of the wrap at the given index, if valid.
  *
  * This expects the caller to have the output locked appropriately.
index 72d6106f2abd695b05cea130f007fa73f14003a7..f793cb0c8e2a97876a0680cd7c3d05857eb02c52 100644 (file)
@@ -4,6 +4,50 @@
 extern "C" {
 #endif
 
+#ifndef _di_iki_read_process_buffer_
+  void iki_read_process_buffer(iki_read_main_t * const main) {
+
+    if (F_status_is_error(main->setting.state.status)) return;
+
+    f_range_t buffer_range = macro_f_range_t_initialize_2(main->cache.buffer.used);
+
+    if (main->setting.flag & iki_read_main_flag_whole_d) {
+      iki_read_process_line(main, &buffer_range);
+
+      if (main->setting.state.status == F_data_not || main->setting.state.status == F_true && buffer_range.start > main->cache.buffer.used) {
+        main->setting.state.status = F_data_not;
+
+        return;
+      }
+
+      if (main->setting.flag & iki_read_main_flag_total_d) {
+        if (main->callback.process_buffer_total) {
+          main->callback.process_buffer_total(main);
+
+          if (F_status_is_error_not(main->setting.state.status)) {
+            main->setting.state.status = F_okay;
+          }
+        }
+
+        return;
+      }
+
+      if (main->callback.process_buffer_ranges_whole) {
+        main->callback.process_buffer_ranges_whole(main, &buffer_range);
+      }
+    }
+    else {
+      if (main->callback.process_buffer_ranges) {
+        main->callback.process_buffer_ranges(main, &buffer_range);
+      }
+    }
+
+    if (F_status_is_error_not(main->setting.state.status)) {
+      main->setting.state.status = F_okay;
+    }
+  }
+#endif // _di_iki_read_process_buffer_
+
 #ifndef _di_iki_read_process_line_
   void iki_read_process_line(iki_read_main_t * const main, f_range_t * const range) {
 
@@ -16,6 +60,7 @@ extern "C" {
     f_number_unsigned_t line = 0;
 
     range->start = 0;
+
     if (main->setting.line) {
       for (; line < main->setting.line && range->start < main->cache.buffer.used; ++range->start) {
         if (main->cache.buffer.string[range->start] == f_string_eol_s.string[0]) ++line;
@@ -37,47 +82,55 @@ extern "C" {
   }
 #endif // _di_iki_read_process_line_
 
-#ifndef _di_iki_read_process_buffer_
-  void iki_read_process_buffer(iki_read_main_t * const main) {
+#ifndef _di_iki_read_process_wrap_append_
+  void iki_read_process_wrap_append(iki_read_main_t * const main, const f_number_unsigned_t index) {
 
-    f_range_t buffer_range = macro_f_range_t_initialize_2(main->cache.buffer.used);
+    if (!main || F_status_is_error(main->setting.state.status)) return;
 
-    if (main->setting.flag & iki_read_main_flag_whole_d) {
-      iki_read_process_line(main, &buffer_range);
+    if (index >= main->setting.map_wrapss.used) {
+      main->setting.state.status = F_data_not;
 
-      if (main->setting.state.status == F_data_not || main->setting.state.status == F_true && buffer_range.start > main->cache.buffer.used) {
-        main->setting.state.status = F_data_not;
+      return;
+    }
 
-        return;
+    f_number_unsigned_t * const array = main->setting.map_wrapss.array[index].array;
+
+    for (f_number_unsigned_t i = 0; i < main->setting.map_wrapss.array[index].used; ++i) {
+
+      if (array[i] < main->setting.wrap.used && main->setting.wrap.array[array[i]].c.used) {
+        main->setting.state.status = f_string_dynamic_append_nulless(main->setting.wrap.array[array[i]].c, &main->cache.expand);
+        if (F_status_is_error(main->setting.state.status)) return;
       }
+    } // for
 
-      if (main->setting.flag & iki_read_main_flag_total_d) {
-        if (main->callback.process_buffer_total) {
-          main->callback.process_buffer_total(main);
+    main->setting.state.status = F_okay;
+  }
+#endif // _di_iki_read_process_wrap_append_
 
-          if (F_status_is_error_not(main->setting.state.status)) {
-            main->setting.state.status = F_okay;
-          }
-        }
+#ifndef _di_iki_read_process_wrap_prepend_
+  void iki_read_process_wrap_prepend(iki_read_main_t * const main, const f_number_unsigned_t index) {
 
-        return;
-      }
+    if (!main || F_status_is_error(main->setting.state.status)) return;
 
-      if (main->callback.process_buffer_ranges_whole) {
-        main->callback.process_buffer_ranges_whole(main, &buffer_range);
-      }
+    if (index >= main->setting.map_wrapss.used) {
+      main->setting.state.status = F_data_not;
+
+      return;
     }
-    else {
-      if (main->callback.process_buffer_ranges) {
-        main->callback.process_buffer_ranges(main, &buffer_range);
+
+    f_number_unsigned_t * const array = main->setting.map_wrapss.array[index].array;
+
+    for (f_number_unsigned_t i = 0; i < main->setting.map_wrapss.array[index].used; ++i) {
+
+      if (array[i] < main->setting.wrap.used && main->setting.wrap.array[array[i]].b.used) {
+        main->setting.state.status = f_string_dynamic_append_nulless(main->setting.wrap.array[array[i]].b, &main->cache.expand);
+        if (F_status_is_error(main->setting.state.status)) return;
       }
-    }
+    } // for
 
-    if (F_status_is_error_not(main->setting.state.status)) {
-      main->setting.state.status = F_okay;
-    }
+    main->setting.state.status = F_okay;
   }
-#endif // _di_iki_read_process_buffer_
+#endif // _di_iki_read_process_wrap_prepend_
 
 #ifdef __cplusplus
 } // extern "C"
index ba9268577189abd3eee9d485b12435f81a91430d..0306446ab8057f158768292d865431c9f080e98a 100644 (file)
@@ -17,6 +17,35 @@ extern "C" {
 #endif
 
 /**
+ * Process a given buffer.
+ *
+ * This will print error messages, except for errors in callbacks.
+ * The callbacks should handle their own error printing.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters setting.state.status:
+ *     F_okay on success.
+ *     F_data_not on success, but nothing done.
+ *
+ *     F_interrupt (with error bit) on (exit) signal received.
+ *
+ *     Errors (with error bit) from: main.callback.process_buffer_ranges().
+ *     Errors (with error bit) from: main.callback.process_buffer_ranges_whole().
+ *     Errors (with error bit) from: main.callback.process_buffer_total().
+ *
+ * @see main.callback.process_buffer_ranges()
+ * @see main.callback.process_buffer_ranges_whole()
+ * @see main.callback.process_buffer_total()
+ */
+#ifndef _di_iki_read_process_buffer_
+  extern void iki_read_process_buffer(iki_read_main_t * const main);
+#endif // _di_iki_read_process_buffer_
+
+/**
  * Determine the range based on the --line parameter.
  *
  * If the --line parameter is not specified in the console arguments, then range is untouched.
@@ -39,10 +68,31 @@ extern "C" {
 #endif // _di_iki_read_process_line_
 
 /**
- * Process a given buffer.
+ * Process the append part of the wrap at the given index adding it to the expand cache, if valid.
  *
- * This will print error messages, except for errors in callbacks.
- * The callbacks should handle their own error printing.
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters setting.state.status:
+ *     F_okay on success.
+ *     F_data_not on success, but nothing added to the expand cache.
+ *
+ *     Errors (with error bit) from: f_string_dynamic_append_nulless()
+ *
+ *     F_failure (with error bit) for any other failure.
+ * @param index
+ *   The index within the setting->map_wrapss array to print.
+ *
+ * @see f_string_dynamic_append_nulless()
+ */
+#ifndef _di_iki_read_process_wrap_append_
+  extern void iki_read_process_wrap_append(iki_read_main_t * const main, const f_number_unsigned_t index);
+#endif // _di_iki_read_process_wrap_append_
+
+/**
+ * Print the prepend part of the wrap at the given index adding it to the expand cache, if valid.
  *
  * @param main
  *   The main program data.
@@ -51,21 +101,19 @@ extern "C" {
  *
  *   This alters setting.state.status:
  *     F_okay on success.
- *     F_data_not on success, but nothing done.
+ *     F_data_not on success, but nothing added to the expand cache.
  *
- *     F_interrupt (with error bit) on (exit) signal received.
+ *     Errors (with error bit) from: f_string_dynamic_append_nulless()
  *
- *     Errors (with error bit) from: main.callback.process_buffer_ranges().
- *     Errors (with error bit) from: main.callback.process_buffer_ranges_whole().
- *     Errors (with error bit) from: main.callback.process_buffer_total().
+ *     F_failure (with error bit) for any other failure.
+ * @param index
+ *   The index within the setting->map_wrapss array to print.
  *
- * @see main.callback.process_buffer_ranges()
- * @see main.callback.process_buffer_ranges_whole()
- * @see main.callback.process_buffer_total()
+ * @see f_string_dynamic_append_nulless()
  */
-#ifndef _di_iki_read_process_buffer_
-  extern void iki_read_process_buffer(iki_read_main_t * const main);
-#endif // _di_iki_read_process_buffer_
+#ifndef _di_iki_read_process_wrap_prepend_
+  extern void iki_read_process_wrap_prepend(iki_read_main_t * const main, const f_number_unsigned_t index);
+#endif // _di_iki_read_process_wrap_prepend_
 
 #ifdef __cplusplus
 } // extern "C"
index 69f59614fb6bc88db2beedac6cabf37a6c4a9a0a..d067395be104834ede3775b9104e24fa174c2c9f 100644 (file)
@@ -18,6 +18,8 @@ settings:
 
 main:
   build settings
+  build settings.eki_read 
+  build settings.iki_read
 
   operate build_path
   operate ld_library_path