]> Kevux Git Server - fll/commitdiff
Progress: Begin adding the eki_write program by extending iki_write.
authorKevin Day <Kevin@kevux.org>
Tue, 26 Nov 2024 06:01:15 +0000 (00:01 -0600)
committerKevin Day <Kevin@kevux.org>
Tue, 26 Nov 2024 06:01:15 +0000 (00:01 -0600)
This is a bit rushed, so I will have additional passes to make.

40 files changed:
level_3/iki_write/c/eki/common.c [new file with mode: 0644]
level_3/iki_write/c/eki/common.h [new file with mode: 0644]
level_3/iki_write/c/eki/eki_write.c [new file with mode: 0644]
level_3/iki_write/c/eki/eki_write.h [new file with mode: 0644]
level_3/iki_write/c/eki/main.c [new file with mode: 0644]
level_3/iki_write/c/eki/main.h [moved from level_3/iki_write/c/main/main.h with 83% similarity]
level_3/iki_write/c/eki/print.c [new file with mode: 0644]
level_3/iki_write/c/eki/print.h [new file with mode: 0644]
level_3/iki_write/c/eki/process.c [new file with mode: 0644]
level_3/iki_write/c/eki/process.h [new file with mode: 0644]
level_3/iki_write/c/iki/common.c [new file with mode: 0644]
level_3/iki_write/c/iki/common.h [new file with mode: 0644]
level_3/iki_write/c/iki/iki_write.c [new file with mode: 0644]
level_3/iki_write/c/iki/iki_write.h [new file with mode: 0644]
level_3/iki_write/c/iki/main.c [moved from level_3/iki_write/c/main/main.c with 84% similarity]
level_3/iki_write/c/iki/main.h [new file with mode: 0644]
level_3/iki_write/c/iki/print.c [new file with mode: 0644]
level_3/iki_write/c/iki/print.h [new file with mode: 0644]
level_3/iki_write/c/iki/process.c [new file with mode: 0644]
level_3/iki_write/c/iki/process.h [new file with mode: 0644]
level_3/iki_write/c/main/common.c
level_3/iki_write/c/main/common.h
level_3/iki_write/c/main/common/print.c
level_3/iki_write/c/main/common/print.h
level_3/iki_write/c/main/common/string.c
level_3/iki_write/c/main/common/string.h
level_3/iki_write/c/main/common/type.c
level_3/iki_write/c/main/common/type.h
level_3/iki_write/c/main/iki_write.c
level_3/iki_write/c/main/iki_write.h
level_3/iki_write/c/main/print/error.c
level_3/iki_write/c/main/print/error.h
level_3/iki_write/c/main/print/message.c
level_3/iki_write/c/main/print/message.h
level_3/iki_write/c/main/process.c [deleted file]
level_3/iki_write/c/main/process.h [deleted file]
level_3/iki_write/data/build/fakefile
level_3/iki_write/data/build/settings
level_3/iki_write/data/build/settings.eki_write [new file with mode: 0644]
level_3/iki_write/data/build/settings.iki_write [new file with mode: 0644]

diff --git a/level_3/iki_write/c/eki/common.c b/level_3/iki_write/c/eki/common.c
new file mode 100644 (file)
index 0000000..ea8b1ef
--- /dev/null
@@ -0,0 +1,127 @@
+#include "eki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_eki_s_
+  const f_string_static_t iki_write_program_name_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_s, 0, IKI_WRITE_program_name_s_length);
+  const f_string_static_t iki_write_program_name_long_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_long_s, 0, IKI_WRITE_program_name_long_s_length);
+#endif // _di_iki_write_eki_s_
+
+#ifndef _di_iki_write_eki_setting_load_
+  void iki_write_eki_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main) {
+
+    if (!main) return;
+
+    if (main->program.parameters.array[f_console_standard_parameter_copyright_e].result & f_console_result_found_e) return;
+    if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) return;
+    if (main->program.parameters.array[f_console_standard_parameter_version_e].result & f_console_result_found_e) return;
+
+    f_number_unsigned_t index = 0;
+    f_console_parameter_t * const content = &main->program.parameters.array[iki_write_parameter_content_e];
+
+    if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_value_e) {
+      f_console_parameter_t * const object = &main->program.parameters.array[iki_write_parameter_object_e];
+      f_string_dynamicss_t * const objectss = &main->setting.objectss;
+
+      objectss->used = 0;
+
+      main->setting.state.status = f_memory_arrays_resize(object->values.used, sizeof(f_string_dynamics_t), (void **) &objectss->array, &objectss->used, &objectss->size, &f_string_dynamicss_delete_callback);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
+
+        return;
+      }
+
+      f_number_unsigned_t at_content = 0;
+      f_number_unsigned_t at_object = 0;
+
+      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
+      for (index = 0; at_object < object->values.used; ) {
+
+        main->setting.state.status = f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamic_t), (void **) &objectss->array[objectss->used].array, &objectss->array[objectss->used].used, &objectss->array[objectss->used].size);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_array_increase));
+
+          return;
+        }
+
+        index = object->values.array[at_object];
+
+        objectss->array[objectss->used].array[objectss->array[objectss->used].used].string = main->program.parameters.arguments.array[index].string;
+        objectss->array[objectss->used].array[objectss->array[objectss->used].used].used = main->program.parameters.arguments.array[index].used;
+        objectss->array[objectss->used].array[objectss->array[objectss->used].used].size = 0;
+        ++objectss->array[objectss->used].used;
+
+        if (++at_object >= object->locations.used || object->locations.array[at_object] > content->locations.array[at_content] || object->locations.array[at_object] == content->locations.array[at_content] && object->locations_sub.array[at_object] > content->locations_sub.array[at_content]) {
+          main->setting.state.status = f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamics_t), (void **) &objectss->array, &objectss->used, &objectss->size);
+
+          if (F_status_is_error(main->setting.state.status)) {
+            iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_array_increase));
+
+            return;
+          }
+
+          objectss->used++;
+          ++at_content;
+
+
+          if (at_object < object->values.used && at_content >= content->values.used) {
+            iki_write_print_eki_error_objects_match_content(&main->program.error);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+      } // for
+
+      main->setting.flag |= iki_write_main_flag_object_d;
+    }
+    else if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_found_e) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_object_s);
+
+      return;
+    }
+
+    if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_value_e) {
+      main->setting.contents.used = 0;
+
+      main->setting.state.status = f_memory_arrays_resize(content->values.used, sizeof(f_string_dynamic_t), (void **) &main->setting.contents.array, &main->setting.contents.used, &main->setting.contents.size, &f_string_dynamics_delete_callback);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
+
+        return;
+      }
+
+      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
+      for (index = 0; main->setting.contents.used < content->values.used; ) {
+
+        index = content->values.array[main->setting.contents.used];
+
+        main->setting.contents.array[main->setting.contents.used].string = main->program.parameters.arguments.array[index].string;
+        main->setting.contents.array[main->setting.contents.used].used = main->program.parameters.arguments.array[index].used;
+        main->setting.contents.array[main->setting.contents.used++].size = 0;
+      } // for
+
+      main->setting.flag |= iki_write_main_flag_content_d;
+    }
+    else if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_found_e) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_content_s);
+
+      return;
+    }
+  }
+#endif // _di_iki_write_eki_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/eki/common.h b/level_3/iki_write/c/eki/common.h
new file mode 100644 (file)
index 0000000..b213ed3
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common data structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _iki_write_eki_common_h
+#define _iki_write_eki_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The EKI write specific strings.
+ */
+#ifndef _di_iki_write_eki_s_
+  #define IKI_WRITE_program_name_s      "eki_write"
+  #define IKI_WRITE_program_name_long_s "EKI Write"
+
+  #define IKI_WRITE_program_name_s_length      9
+  #define IKI_WRITE_program_name_long_s_length 9
+
+  extern const f_string_static_t iki_write_program_name_s;
+  extern const f_string_static_t iki_write_program_name_long_s;
+#endif // _di_iki_write_eki_s_
+
+/**
+ * Perform the program setting load process for EKI.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately returns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The program and settings data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: f_file_stream_open().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *     Errors (with error bit) from: fll_program_parameter_process_verbosity_standard().
+ *
+ * @see f_console_parameter_process()
+ * @see f_file_stream_open()
+ * @see fll_program_parameter_process_context()
+ * @see fll_program_parameter_process_verbosity_standard()
+ */
+#ifndef _di_iki_write_eki_setting_load_
+  extern void iki_write_eki_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main);
+#endif // _di_iki_write_eki_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_eki_common_h
diff --git a/level_3/iki_write/c/eki/eki_write.c b/level_3/iki_write/c/eki/eki_write.c
new file mode 100644 (file)
index 0000000..eafe507
--- /dev/null
@@ -0,0 +1,10 @@
+#include "eki_write.h"
+#include "../main/iki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/eki/eki_write.h b/level_3/iki_write/c/eki/eki_write.h
new file mode 100644 (file)
index 0000000..01f4c32
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS Read
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This program provides EKI write.
+ */
+#ifndef _iki_write_eki_write_h
+#define _iki_write_eki_write_h
+
+// Libc includes.
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// FLL-0 includes.
+#include <fll/level_0/type.h>
+#include <fll/level_0/status.h>
+#include <fll/level_0/memory.h>
+#include <fll/level_0/string.h>
+#include <fll/level_0/utf.h>
+#include <fll/level_0/color.h>
+#include <fll/level_0/compare.h>
+#include <fll/level_0/console.h>
+#include <fll/level_0/conversion.h>
+#include <fll/level_0/file.h>
+#include <fll/level_0/iki.h>
+#include <fll/level_0/pipe.h>
+#include <fll/level_0/print.h>
+#include <fll/level_0/rip.h>
+#include <fll/level_0/signal.h>
+
+#ifndef _di_thread_support_
+  #include <fll/level_0/thread.h>
+#endif // _di_thread_support_
+
+// FLL-1 includes.
+#include <fll/level_1/conversion.h>
+#include <fll/level_1/iki.h>
+#include <fll/level_1/print.h>
+
+// FLL-2 includes.
+#include <fll/level_2/error.h>
+#include <fll/level_2/file.h>
+#include <fll/level_2/iki.h>
+#include <fll/level_2/print.h>
+#include <fll/level_2/program.h>
+
+// IKI Write includes.
+#include <program/iki_write/main/common/define.h>
+#include <program/iki_write/main/common/enumeration.h>
+#include <program/iki_write/main/common/print.h>
+#include <program/iki_write/main/common/string.h>
+#include <program/iki_write/main/common/type.h>
+#include <program/iki_write/main/common.h>
+#include <program/iki_write/main/print/error.h>
+#include <program/iki_write/main/print/message.h>
+#include <program/iki_write/main/signal.h>
+#include <program/iki_write/main/thread.h>
+#include <program/iki_write/eki/common.h>
+#include <program/iki_write/eki/print.h>
+#include <program/iki_write/eki/process.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_eki_write_h
diff --git a/level_3/iki_write/c/eki/main.c b/level_3/iki_write/c/eki/main.c
new file mode 100644 (file)
index 0000000..f410530
--- /dev/null
@@ -0,0 +1,77 @@
+#include "eki_write.h"
+#include "../main/iki_write.h"
+
+int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
+
+  iki_write_main_t data = iki_write_main_t_initialize;
+
+  data.program.debug.flag |= iki_write_print_flag_debug_d | iki_write_print_flag_out_d;
+  data.program.error.flag |= iki_write_print_flag_error_d | iki_write_print_flag_out_d;
+  data.program.output.flag |= iki_write_print_flag_out_d;
+  data.program.message.flag |= iki_write_print_flag_message_d | iki_write_print_flag_out_d;
+  data.program.warning.flag |= iki_write_print_flag_warning_d | iki_write_print_flag_out_d;
+  data.program.error.custom = (void *) &data;
+  data.program.debug.custom = (void *) &data;
+  data.program.message.custom = (void *) &data;
+  data.program.output.custom = (void *) &data;
+  data.program.warning.custom = (void *) &data;
+
+  data.callback.load_objects_content_pipe = &iki_write_eki_load_objects_content_pipe;
+  data.callback.print_help = &iki_write_eki_print_message_help;
+  data.callback.process_objects_content = &iki_write_eki_process_objects_content;
+
+  f_console_parameter_t parameters[] = iki_write_console_parameter_t_initialize;
+  data.program.parameters.array = parameters;
+  data.program.parameters.used = iki_write_parameter_total_d;
+  data.program.environment = envp;
+
+  if (f_pipe_input_exists()) {
+    data.program.pipe = fll_program_data_pipe_input_e;
+  }
+
+  fll_program_standard_set_up(&data.program);
+
+  f_file_umask_get(&data.program.umask);
+
+  #ifdef _di_thread_support_
+    {
+      const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+
+      iki_write_setting_load(arguments, &data, &iki_write_eki_setting_load);
+    }
+
+    iki_write_main(&data);
+  #else
+    {
+      f_thread_id_t id_signal;
+
+      memset(&id_signal, 0, sizeof(f_thread_id_t));
+
+      data.setting.state.status = f_thread_create(0, &id_signal, &iki_write_thread_signal, (void *) &data);
+
+      if (F_status_is_error(data.setting.state.status)) {
+        iki_write_print_error(&data.program.error, macro_iki_write_f(f_thread_create));
+      }
+      else {
+        {
+          const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+
+          iki_write_setting_load(arguments, &data, &iki_write_eki_setting_load);
+        }
+
+        if (!iki_write_signal_check(&data)) {
+          iki_write_main(&data);
+        }
+
+        f_thread_cancel(id_signal);
+        f_thread_join(id_signal, 0);
+      }
+    }
+  #endif // _di_thread_support_
+
+  iki_write_main_delete(&data);
+
+  fll_program_standard_set_down(&data.program);
+
+  return F_status_is_error(data.setting.state.status) ? 1 : 0;
+}
similarity index 83%
rename from level_3/iki_write/c/main/main.h
rename to level_3/iki_write/c/eki/main.h
index 15e6e38ce99b4f1bb6624b9eefcf9e0a7afef116..5dfff03e9fde82671fa0cce510a2606b1cd91f93 100644 (file)
@@ -6,10 +6,10 @@
  * Licenses: lgpl-2.1-or-later
  *
  * This file is only ever included by main/main.c and should not normally be included anywhere else.
- * Anything that wants to include this should be providing the "iki_write" program functionality in some manner.
+ * Anything that wants to include this should be providing the "fss_write" program functionality in some manner.
  */
-#ifndef _iki_write_main_h
-#define _iki_write_main_h
+#ifndef _iki_write_eki_main_h
+#define _iki_write_eki_main_h
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,4 +35,4 @@ extern int main(const int argc, const f_string_t *argv, const f_string_t *envp);
 } // extern "C"
 #endif
 
-#endif // _iki_write_main_h
+#endif // _iki_write_eki_main_h
diff --git a/level_3/iki_write/c/eki/print.c b/level_3/iki_write/c/eki/print.c
new file mode 100644 (file)
index 0000000..b3201ef
--- /dev/null
@@ -0,0 +1,84 @@
+#include "eki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_print_eki_error_objects_match_content_
+  f_status_t iki_write_print_eki_error_objects_match_content(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    fll_print_format("%[%QThe Objects must have a matching Content.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_okay;
+  }
+#endif // _di_iki_write_print_eki_error_objects_match_content_
+
+#ifndef _di_iki_write_eki_print_error_objects_not_valid_
+  f_status_t iki_write_eki_print_error_objects_not_valid(fl_print_t * const print, const f_string_statics_t objects) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QOne or more of the Objects ", print->to, print->set->error, print->prefix);
+
+    for (f_number_unsigned_t i = 0; i < objects.used; ++i) {
+
+      fl_print_format("'%]", print->to, print->set->error);
+      fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, objects.array[i], print->set->notable);
+      fl_print_format("%['%Q", print->to, print->set->error);
+
+      if (i + 1 < objects.used) {
+        fl_print_format(", ", print->to);
+      }
+    } // for
+
+    fl_print_format(" is not a valid IKI Object (IKI Vocabulary).%]%r", print->to, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_okay;
+  }
+#endif // _di_iki_write_eki_print_error_objects_not_valid_
+
+#ifndef _di_iki_write_eki_print_message_help_
+  void iki_write_eki_print_message_help(fl_print_t * const print) {
+
+    if (!print) return;
+
+    f_file_stream_lock(print->to);
+
+    fll_program_print_help_header(print, iki_write_program_name_long_s, iki_write_program_version_s);
+
+    iki_write_print_message_help(print);
+
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    fll_program_print_help_usage(print, iki_write_program_name_s, f_string_empty_s);
+
+    iki_write_print_message_help_note(print);
+
+    iki_write_eki_print_message_help_note_pipe(print);
+
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
+  }
+#endif // _di_iki_write_eki_print_message_help_
+
+#ifndef _di_iki_write_eki_print_message_help_note_pipe_
+  void iki_write_eki_print_message_help_note_pipe(fl_print_t * const print) {
+
+    if (!print) return;
+    fl_print_format("%r  When piping main to this program, a single form-feed character (\\f) (U+000C) must be used to separate each Object set from the Content.%r", print->to, f_string_eol_s, f_string_eol_s);
+    fl_print_format("  Each Object within an Object set is is separated by a single backspace character (\\b) (U+0008).%r", print->to, f_string_eol_s);
+    fl_print_format("  Each Object set must be followed by a Content.%r", print->to, f_string_eol_s);
+  }
+#endif // _di_iki_write_eki_print_message_help_note_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/eki/print.h b/level_3/iki_write/c/eki/print.h
new file mode 100644 (file)
index 0000000..69824e9
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _eki_write_eki_print_h
+#define _eki_write_eki_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print error message about the Objects not having a matching Content.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_iki_write_print_eki_error_objects_match_content_
+  extern f_status_t iki_write_print_eki_error_objects_match_content(fl_print_t * const print);
+#endif // _di_iki_write_print_eki_error_objects_match_content_
+
+/**
+ * Print error message about an Object not being valid.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param objects
+ *   The a strings representing the objects that are not valid.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_iki_write_print_eki_error_objects_not_valid_
+  extern f_status_t iki_write_eki_print_error_objects_not_valid(fl_print_t * const print, const f_string_statics_t objects);
+#endif // _di_iki_write_print_eki_error_objects_not_valid_
+
+/**
+ * Print help for EKI write.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_write_eki_print_message_help_
+  extern void iki_write_eki_print_message_help(fl_print_t * const print);
+#endif // _di_iki_write_eki_print_message_help_
+
+/**
+ * Print note pipe help for EKI write.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_write_eki_print_message_help_note_pipe_
+  extern void iki_write_eki_print_message_help_note_pipe(fl_print_t * const print);
+#endif // _di_iki_write_eki_print_message_help_note_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _eki_write_eki_print_h
diff --git a/level_3/iki_write/c/eki/process.c b/level_3/iki_write/c/eki/process.c
new file mode 100644 (file)
index 0000000..8316c4c
--- /dev/null
@@ -0,0 +1,127 @@
+#include "eki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_eki_load_objects_content_pipe_
+  void iki_write_eki_load_objects_content_pipe(void * const void_main, const f_range_t range, bool * const object_ended) {
+
+    if (!void_main) return;
+
+    iki_write_main_t * const main = (iki_write_main_t *) void_main;
+
+    if (!object_ended || !main->callback.process_objects_content) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      iki_write_print_error(&main->program.error, macro_iki_write_f(iki_write_callback_load_objects_content_pipe));
+
+      return;
+    }
+
+    if (*object_ended) {
+      main->cache.content.used = 0;
+
+      if (main->cache.buffer.used) {
+        main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.content);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
+
+          *object_ended = F_false;
+
+          return;
+        }
+      }
+
+      main->callback.process_objects_content((void *) main, main->cache.objects, main->cache.content);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        *object_ended = F_false;
+
+        return;
+      }
+
+      fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+      *object_ended = F_false;
+      main->cache.objects.used = 0;
+    }
+    else {
+      f_range_t range_object = range;
+
+      f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamic_t), (void **) &main->cache.objects.array, &main->cache.objects.used, &main->cache.objects.size);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_array_increase));
+
+        *object_ended = F_false;
+
+        return;
+      }
+
+      main->cache.objects.array[0].used = 0;
+
+      main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.objects.array[0]);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
+
+        *object_ended = F_false;
+
+        return;
+      }
+
+      *object_ended = F_true;
+      ++main->cache.objects.used;
+    }
+  }
+#endif // _di_iki_write_eki_load_objects_content_pipe_
+
+#ifndef _di_iki_write_eki_process_objects_content_
+  void iki_write_eki_process_objects_content(void * const void_main, const f_string_statics_t objects, const f_string_static_t content) {
+
+    if (!void_main) return;
+
+    iki_write_main_t * const main = (iki_write_main_t *) void_main;
+
+    {
+      f_number_unsigned_t i = 0;
+
+      for (; i < objects.used; ++i) {
+        if (objects.array[i].used) break;
+      } // for
+
+      if (!objects.used || i == objects.used) {
+        main->setting.state.status = F_status_set_error(F_failure);
+
+        fll_program_print_error_missing_variable_not_zero(&main->program.error, iki_write_object_s);
+
+        return;
+      }
+    }
+
+    main->cache.iki.used = 0;
+
+    f_iki_eki_write(objects, content, main->setting.quote, &main->cache.iki, &main->setting.state);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if (F_status_set_fine(main->setting.state.status) == F_syntax) {
+        iki_write_eki_print_error_objects_not_valid(&main->program.error, objects);
+      }
+      else {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_iki_write));
+      }
+
+      return;
+    }
+
+    f_print_dynamic(main->cache.iki, main->program.output.to);
+
+    main->setting.state.status = F_okay;
+  }
+#endif // _di_iki_write_eki_process_objects_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/eki/process.h b/level_3/iki_write/c/eki/process.h
new file mode 100644 (file)
index 0000000..e9fadc5
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the process functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _iki_write_eki_process_h
+#define _iki_write_eki_process_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Load the Objects and Content from the given pipe information.
+ *
+ * This function prints errors.
+ *
+ * @param main
+ *   The program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_iki_write().
+ *
+ *     F_failure (with error bit) for any other failure.
+ * @param objects
+ *   The objects to process and print.
+ * @param content
+ *   The content to process and print.
+ *
+ * @see f_iki_write()
+ */
+#ifndef _di_iki_write_eki_load_objects_content_pipe_
+  extern void iki_write_eki_load_objects_content_pipe(void * const main, const f_range_t range, bool * const object_ended);
+#endif // _di_iki_write_eki_load_objects_content_pipe_
+
+/**
+ * Process a given object and content, printing it.
+ *
+ * This function prints errors.
+ *
+ * @param main
+ *   The program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_iki_eki_write().
+ *
+ *     F_failure (with error bit) for any other failure.
+ * @param objects
+ *   The objects to process and print.
+ * @param content
+ *   The content to process and print.
+ *
+ * @see f_iki_eki_write()
+ */
+#ifndef _di_iki_write_eki_process_objects_content_
+  extern void iki_write_eki_process_objects_content(void * const main, const f_string_statics_t objects, const f_string_static_t content);
+#endif // _di_iki_write_eki_process_objects_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_eki_process_h
diff --git a/level_3/iki_write/c/iki/common.c b/level_3/iki_write/c/iki/common.c
new file mode 100644 (file)
index 0000000..bd9b0a1
--- /dev/null
@@ -0,0 +1,102 @@
+#include "iki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_iki_s_
+  const f_string_static_t iki_write_program_name_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_s, 0, IKI_WRITE_program_name_s_length);
+  const f_string_static_t iki_write_program_name_long_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_long_s, 0, IKI_WRITE_program_name_long_s_length);
+#endif // _di_iki_write_iki_s_
+
+#ifndef _di_iki_write_iki_setting_load_
+  void iki_write_iki_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main) {
+
+    if (!main) return;
+
+    if (main->program.parameters.array[f_console_standard_parameter_copyright_e].result & f_console_result_found_e) return;
+    if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) return;
+    if (main->program.parameters.array[f_console_standard_parameter_version_e].result & f_console_result_found_e) return;
+
+    f_number_unsigned_t index = 0;
+
+    if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_value_e) {
+      f_number_unsigneds_t * const values = &main->program.parameters.array[iki_write_parameter_object_e].values;
+
+      main->setting.objectss.used = 0;
+
+      main->setting.state.status = f_memory_arrays_resize(values->used, sizeof(f_string_dynamics_t), (void **) &main->setting.objectss.array, &main->setting.objectss.used, &main->setting.objectss.size, &f_string_dynamicss_delete_callback);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
+
+        return;
+      }
+
+      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
+      for (index = 0; main->setting.objectss.used < values->used; ) {
+
+        main->setting.state.status = f_memory_arrays_resize(1, sizeof(f_string_dynamic_t), (void **) &main->setting.objectss.array[main->setting.objectss.used].array, &main->setting.objectss.array[main->setting.objectss.used].used, &main->setting.objectss.array[main->setting.objectss.used].size, &f_string_dynamics_delete_callback);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
+
+          return;
+        }
+
+        index = values->array[main->setting.objectss.used];
+
+        main->setting.objectss.array[main->setting.objectss.used].array[0].string = main->program.parameters.arguments.array[index].string;
+        main->setting.objectss.array[main->setting.objectss.used].array[0].used = main->program.parameters.arguments.array[index].used;
+        main->setting.objectss.array[main->setting.objectss.used].array[0].size = 0;
+        main->setting.objectss.array[main->setting.objectss.used++].used = 1;
+      } // for
+
+      main->setting.flag |= iki_write_main_flag_object_d;
+    }
+    else if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_found_e) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_object_s);
+
+      return;
+    }
+
+    if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_value_e) {
+      f_number_unsigneds_t * const values = &main->program.parameters.array[iki_write_parameter_content_e].values;
+
+      main->setting.contents.used = 0;
+
+      main->setting.state.status = f_memory_arrays_resize(values->used, sizeof(f_string_dynamic_t), (void **) &main->setting.contents.array, &main->setting.contents.used, &main->setting.contents.size, &f_string_dynamics_delete_callback);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
+
+        return;
+      }
+
+      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
+      for (index = 0; main->setting.contents.used < values->used; ) {
+
+        index = values->array[main->setting.contents.used];
+
+        main->setting.contents.array[main->setting.contents.used].string = main->program.parameters.arguments.array[index].string;
+        main->setting.contents.array[main->setting.contents.used].used = main->program.parameters.arguments.array[index].used;
+        main->setting.contents.array[main->setting.contents.used++].size = 0;
+      } // for
+
+      main->setting.flag |= iki_write_main_flag_content_d;
+    }
+    else if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_found_e) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_content_s);
+
+      return;
+    }
+  }
+#endif // _di_iki_write_iki_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/iki/common.h b/level_3/iki_write/c/iki/common.h
new file mode 100644 (file)
index 0000000..c4afb16
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common data structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _iki_write_iki_common_h
+#define _iki_write_iki_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The IKI write specific strings.
+ */
+#ifndef _di_iki_write_iki_s_
+  #define IKI_WRITE_program_name_s      "iki_write"
+  #define IKI_WRITE_program_name_long_s "IKI Write"
+
+  #define IKI_WRITE_program_name_s_length      9
+  #define IKI_WRITE_program_name_long_s_length 9
+
+  extern const f_string_static_t iki_write_program_name_s;
+  extern const f_string_static_t iki_write_program_name_long_s;
+#endif // _di_iki_write_iki_s_
+
+/**
+ * Perform the program setting load process for IKI.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately returns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The program and settings data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: f_file_stream_open().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *     Errors (with error bit) from: fll_program_parameter_process_verbosity_standard().
+ *
+ * @see f_console_parameter_process()
+ * @see f_file_stream_open()
+ * @see fll_program_parameter_process_context()
+ * @see fll_program_parameter_process_verbosity_standard()
+ */
+#ifndef _di_iki_write_iki_setting_load_
+  extern void iki_write_iki_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main);
+#endif // _di_iki_write_iki_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_iki_common_h
diff --git a/level_3/iki_write/c/iki/iki_write.c b/level_3/iki_write/c/iki/iki_write.c
new file mode 100644 (file)
index 0000000..42626dd
--- /dev/null
@@ -0,0 +1,10 @@
+#include "iki_write.h"
+#include "../main/iki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/iki/iki_write.h b/level_3/iki_write/c/iki/iki_write.h
new file mode 100644 (file)
index 0000000..f2f2c45
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This program provides IKI write.
+ */
+#ifndef _iki_write_iki_write_h
+#define _iki_write_iki_write_h
+
+// Libc includes.
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// FLL-0 includes.
+#include <fll/level_0/type.h>
+#include <fll/level_0/status.h>
+#include <fll/level_0/memory.h>
+#include <fll/level_0/string.h>
+#include <fll/level_0/utf.h>
+#include <fll/level_0/color.h>
+#include <fll/level_0/compare.h>
+#include <fll/level_0/console.h>
+#include <fll/level_0/conversion.h>
+#include <fll/level_0/file.h>
+#include <fll/level_0/iki.h>
+#include <fll/level_0/pipe.h>
+#include <fll/level_0/print.h>
+#include <fll/level_0/rip.h>
+#include <fll/level_0/signal.h>
+
+#ifndef _di_thread_support_
+  #include <fll/level_0/thread.h>
+#endif // _di_thread_support_
+
+// FLL-1 includes.
+#include <fll/level_1/conversion.h>
+#include <fll/level_1/iki.h>
+#include <fll/level_1/print.h>
+
+// FLL-2 includes.
+#include <fll/level_2/error.h>
+#include <fll/level_2/file.h>
+#include <fll/level_2/iki.h>
+#include <fll/level_2/print.h>
+#include <fll/level_2/program.h>
+
+// IKI Write includes.
+#include <program/iki_write/main/common/define.h>
+#include <program/iki_write/main/common/enumeration.h>
+#include <program/iki_write/main/common/print.h>
+#include <program/iki_write/main/common/string.h>
+#include <program/iki_write/main/common/type.h>
+#include <program/iki_write/main/common.h>
+#include <program/iki_write/main/print/error.h>
+#include <program/iki_write/main/print/message.h>
+#include <program/iki_write/main/signal.h>
+#include <program/iki_write/main/thread.h>
+#include <program/iki_write/iki/common.h>
+#include <program/iki_write/iki/print.h>
+#include <program/iki_write/iki/process.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_iki_write_h
similarity index 84%
rename from level_3/iki_write/c/main/main.c
rename to level_3/iki_write/c/iki/main.c
index 68f6e87e0cfd253dbc6f5195eb1eb4c02b1d1ace..a0686051798ef77a9a644be90e7439e0e927526d 100644 (file)
@@ -1,4 +1,5 @@
 #include "iki_write.h"
+#include "../main/iki_write.h"
 
 int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
@@ -15,6 +16,10 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
   data.program.output.custom = (void *) &data;
   data.program.warning.custom = (void *) &data;
 
+  data.callback.load_objects_content_pipe = &iki_write_iki_load_objects_content_pipe;
+  data.callback.print_help = &iki_write_iki_print_message_help;
+  data.callback.process_objects_content = &iki_write_iki_process_objects_content;
+
   f_console_parameter_t parameters[] = iki_write_console_parameter_t_initialize;
   data.program.parameters.array = parameters;
   data.program.parameters.used = iki_write_parameter_total_d;
@@ -32,7 +37,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
     {
       const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
 
-      iki_write_setting_load(arguments, &data);
+      iki_write_setting_load(arguments, &data, &iki_write_iki_setting_load);
     }
 
     iki_write_main(&data);
@@ -51,7 +56,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
         {
           const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
 
-          iki_write_setting_load(arguments, &data);
+          iki_write_setting_load(arguments, &data, &iki_write_iki_setting_load);
         }
 
         if (!iki_write_signal_check(&data)) {
diff --git a/level_3/iki_write/c/iki/main.h b/level_3/iki_write/c/iki/main.h
new file mode 100644 (file)
index 0000000..a316d96
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This file is only ever included by main/main.c and should not normally be included anywhere else.
+ * Anything that wants to include this should be providing the "fss_write" program functionality in some manner.
+ */
+#ifndef _iki_write_iki_main_h
+#define _iki_write_iki_main_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Standard program entry point.
+ *
+ * @param argc
+ *   The number of arguments.
+ * @param argv
+ *   The array of arguments.
+ * @param envp
+ *   The array of all environment variables on program start.
+ *
+ * @return
+ *   0 on success.
+ *   1 on error.
+ */
+extern int main(const int argc, const f_string_t *argv, const f_string_t *envp);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_iki_main_h
diff --git a/level_3/iki_write/c/iki/print.c b/level_3/iki_write/c/iki/print.c
new file mode 100644 (file)
index 0000000..68788c4
--- /dev/null
@@ -0,0 +1,61 @@
+#include "iki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_iki_print_error_object_not_valid_
+  f_status_t iki_write_iki_print_error_object_not_valid(fl_print_t * const print, const f_string_static_t object) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe Object '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, object, print->set->notable);
+    fl_print_format("%[' is not a valid IKI Object (IKI Vocabulary).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_okay;
+  }
+#endif // _di_iki_write_iki_print_error_object_not_valid_
+
+#ifndef _di_iki_write_iki_print_message_help_
+  void iki_write_iki_print_message_help(fl_print_t * const print) {
+
+    if (!print) return;
+
+    f_file_stream_lock(print->to);
+
+    fll_program_print_help_header(print, iki_write_program_name_long_s, iki_write_program_version_s);
+
+    iki_write_print_message_help(print);
+
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    fll_program_print_help_usage(print, iki_write_program_name_s, f_string_empty_s);
+
+    iki_write_print_message_help_note(print);
+
+    iki_write_iki_print_message_help_note_pipe(print);
+
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
+  }
+#endif // _di_iki_write_iki_print_message_help_
+
+#ifndef _di_iki_write_iki_print_message_help_note_pipe_
+  void iki_write_iki_print_message_help_note_pipe(fl_print_t * const print) {
+
+    if (!print) return;
+
+    fl_print_format("%r  When piping main to this program, a single form-feed character (\\f) (U+000C) must be used to separate each Object from each Content.%r", print->to, f_string_eol_s, f_string_eol_s);
+    fl_print_format("  Each Object must be followed by a Content.%r", print->to, f_string_eol_s);
+  }
+#endif // _di_iki_write_iki_print_message_help_note_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/iki/print.h b/level_3/iki_write/c/iki/print.h
new file mode 100644 (file)
index 0000000..a75e0b6
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _iki_write_iki_print_h
+#define _iki_write_iki_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print error message about an Object not being valid.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param object
+ *   The a string representing the object that is not valid.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_iki_write_iki_print_error_object_not_valid_
+  extern f_status_t iki_write_iki_print_error_object_not_valid(fl_print_t * const print, const f_string_static_t object);
+#endif // _di_iki_write_iki_print_error_object_not_valid_
+
+/**
+ * Print help for IKI write.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_write_iki_print_message_help_
+  extern void iki_write_iki_print_message_help(fl_print_t * const print);
+#endif // _di_iki_write_iki_print_message_help_
+
+/**
+ * Print note pipe help for IKI write.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_write_iki_print_message_help_note_pipe_
+  extern void iki_write_iki_print_message_help_note_pipe(fl_print_t * const print);
+#endif // _di_iki_write_iki_print_message_help_note_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_iki_print_h
diff --git a/level_3/iki_write/c/iki/process.c b/level_3/iki_write/c/iki/process.c
new file mode 100644 (file)
index 0000000..8ff02b4
--- /dev/null
@@ -0,0 +1,118 @@
+#include "iki_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_write_iki_load_objects_content_pipe_
+  void iki_write_iki_load_objects_content_pipe(void * const void_main, const f_range_t range, bool * const object_ended) {
+
+    if (!void_main) return;
+
+    iki_write_main_t * const main = (iki_write_main_t *) void_main;
+
+    if (!object_ended || !main->callback.process_objects_content) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      iki_write_print_error(&main->program.error, macro_iki_write_f(iki_write_callback_load_objects_content_pipe));
+
+      return;
+    }
+
+    if (*object_ended) {
+      main->cache.content.used = 0;
+
+      if (main->cache.buffer.used) {
+        main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.content);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
+
+          *object_ended = F_false;
+
+          return;
+        }
+      }
+
+      main->callback.process_objects_content((void *) main, main->cache.objects, main->cache.content);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        *object_ended = F_false;
+
+        return;
+      }
+
+      fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+      *object_ended = F_false;
+      main->cache.objects.used = 0;
+    }
+    else {
+      f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamic_t), (void **) &main->cache.objects.array, &main->cache.objects.used, &main->cache.objects.size);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_array_increase));
+
+        *object_ended = F_false;
+
+        return;
+      }
+
+      main->cache.objects.array[main->cache.objects.used].used = 0;
+
+      main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.objects.array[0]);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
+
+        *object_ended = F_false;
+
+        return;
+      }
+
+      *object_ended = F_true;
+      ++main->cache.objects.used;
+    }
+  }
+#endif // _di_iki_write_iki_load_objects_content_pipe_
+
+#ifndef _di_iki_write_iki_process_objects_content_
+  void iki_write_iki_process_objects_content(void * const void_main, const f_string_statics_t objects, const f_string_static_t content) {
+
+    if (!void_main) return;
+
+    iki_write_main_t * const main = (iki_write_main_t *) void_main;
+
+    // Only the first index is used because IKI only supports one Object (Vocabulary).
+    if (!objects.used || !objects.array[0].used) {
+      main->setting.state.status = F_status_set_error(F_failure);
+
+      fll_program_print_error_missing_variable_not_zero(&main->program.error, iki_write_object_s);
+
+      return;
+    }
+
+    main->cache.iki.used = 0;
+
+    f_iki_write(objects.array[0], content, main->setting.quote, &main->cache.iki, &main->setting.state);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if (F_status_set_fine(main->setting.state.status) == F_syntax) {
+        iki_write_iki_print_error_object_not_valid(&main->program.error, objects.array[0]);
+      }
+      else {
+        iki_write_print_error(&main->program.error, macro_iki_write_f(f_iki_write));
+      }
+
+      return;
+    }
+
+    f_print_dynamic(main->cache.iki, main->program.output.to);
+
+    main->setting.state.status = F_okay;
+  }
+#endif // _di_iki_write_iki_process_objects_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_write/c/iki/process.h b/level_3/iki_write/c/iki/process.h
new file mode 100644 (file)
index 0000000..30da911
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI Write
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the process functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _iki_write_iki_process_h
+#define _iki_write_iki_process_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Load the Objects and Content from the given pipe information.
+ *
+ * This function prints errors.
+ *
+ * @param main
+ *   The program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_iki_write().
+ *
+ *     F_failure (with error bit) for any other failure.
+ * @param objects
+ *   The objects to process and print.
+ * @param content
+ *   The content to process and print.
+ *
+ * @see f_iki_write()
+ */
+#ifndef _di_iki_write_iki_load_objects_content_pipe_
+  extern void iki_write_iki_load_objects_content_pipe(void * const main, const f_range_t range, bool * const object_ended);
+#endif // _di_iki_write_iki_load_objects_content_pipe_
+
+/**
+ * Process a given object and content, printing it.
+ *
+ * This function prints errors.
+ *
+ * @param main
+ *   The program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters main.setting.state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_iki_write().
+ *
+ *     F_failure (with error bit) for any other failure.
+ * @param objects
+ *   The objects to process and print.
+ * @param content
+ *   The content to process and print.
+ *
+ * @see f_iki_write()
+ */
+#ifndef _di_iki_write_iki_process_objects_content_
+  extern void iki_write_iki_process_objects_content(void * const main, const f_string_statics_t objects, const f_string_static_t content);
+#endif // _di_iki_write_iki_process_objects_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_write_iki_process_h
index cf62d631d00c1716e12963b4841c53610842847a..2ef9099fbacc44d8fe61e83e0ce40f01ceb6d45d 100644 (file)
@@ -5,7 +5,7 @@ extern "C" {
 #endif
 
 #ifndef _di_iki_write_setting_load_
-  void iki_write_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main) {
+  void iki_write_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main, void (*callback)(const f_console_arguments_t arguments, iki_write_main_t * const main)) {
 
     if (!main) return;
 
@@ -41,6 +41,17 @@ extern "C" {
     main->program.output.to.stream = F_type_output_d;
     main->program.output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d;
 
+    if (callback) {
+      callback(arguments, main);
+      if (F_status_is_error(main->setting.state.status)) return;
+
+      if (main->setting.state.status == F_done) {
+        main->setting.state.status = F_okay;
+
+        return;
+      }
+    }
+
     if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) {
       main->setting.flag |= iki_write_main_flag_help_d;
 
@@ -98,72 +109,6 @@ extern "C" {
       return;
     }
 
-    if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_value_e) {
-      f_number_unsigneds_t * const values = &main->program.parameters.array[iki_write_parameter_object_e].values;
-
-      main->setting.objects.used = 0;
-
-      main->setting.state.status = f_memory_arrays_resize(values->used, sizeof(f_string_dynamic_t), (void **) &main->setting.objects.array, &main->setting.objects.used, &main->setting.objects.size, &f_string_dynamics_delete_callback);
-
-      if (F_status_is_error(main->setting.state.status)) {
-        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
-
-        return;
-      }
-
-      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
-      for (f_number_unsigned_t index = 0; main->setting.objects.used < values->used; ) {
-
-        index = values->array[main->setting.objects.used];
-
-        main->setting.objects.array[main->setting.objects.used].string = main->program.parameters.arguments.array[index].string;
-        main->setting.objects.array[main->setting.objects.used].used = main->program.parameters.arguments.array[index].used;
-        main->setting.objects.array[main->setting.objects.used++].size = 0;
-      } // for
-
-      main->setting.flag |= iki_write_main_flag_object_d;
-    }
-    else if (main->program.parameters.array[iki_write_parameter_object_e].result & f_console_result_found_e) {
-      main->setting.state.status = F_status_set_error(F_parameter);
-
-      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_object_s);
-
-      return;
-    }
-
-    if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_value_e) {
-      f_number_unsigneds_t * const values = &main->program.parameters.array[iki_write_parameter_content_e].values;
-
-      main->setting.contents.used = 0;
-
-      main->setting.state.status = f_memory_arrays_resize(values->used, sizeof(f_string_dynamic_t), (void **) &main->setting.contents.array, &main->setting.contents.used, &main->setting.contents.size, &f_string_dynamics_delete_callback);
-
-      if (F_status_is_error(main->setting.state.status)) {
-        iki_write_print_error(&main->program.error, macro_iki_write_f(f_memory_arrays_resize));
-
-        return;
-      }
-
-      // Construct the array without allocating any more memory by setting this as a static string (used > 0, size = 0).
-      for (f_number_unsigned_t index = 0; main->setting.contents.used < values->used; ) {
-
-        index = values->array[main->setting.contents.used];
-
-        main->setting.contents.array[main->setting.contents.used].string = main->program.parameters.arguments.array[index].string;
-        main->setting.contents.array[main->setting.contents.used].used = main->program.parameters.arguments.array[index].used;
-        main->setting.contents.array[main->setting.contents.used++].size = 0;
-      } // for
-
-      main->setting.flag |= iki_write_main_flag_content_d;
-    }
-    else if (main->program.parameters.array[iki_write_parameter_content_e].result & f_console_result_found_e) {
-      main->setting.state.status = F_status_set_error(F_parameter);
-
-      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, iki_write_long_content_s);
-
-      return;
-    }
-
     if (!(main->program.pipe & fll_program_data_pipe_input_e) && !(main->setting.flag & (iki_write_main_flag_content_d | iki_write_parameter_object_e))) {
       main->setting.state.status = F_status_set_error(F_parameter);
 
index 4dc2388838c3cccd338ef65f76dd484fceea36fc..aff245ce22e1a9d5246f0b3445b9d73f4c1cdc90 100644 (file)
@@ -35,6 +35,10 @@ extern "C" {
  *     Errors (with error bit) from: f_file_stream_open().
  *     Errors (with error bit) from: fll_program_parameter_process_context().
  *     Errors (with error bit) from: fll_program_parameter_process_verbosity_standard().
+ * @param callback
+ *   (optional) Designate a function to call after performing the initial processing, but before printing help.
+ *   If the function returns F_done, then this function immediately returns, resetting status to F_okay.
+ *   Set to NULL to disable.
  *
  * @see f_console_parameter_process()
  * @see f_file_stream_open()
@@ -42,7 +46,7 @@ extern "C" {
  * @see fll_program_parameter_process_verbosity_standard()
  */
 #ifndef _di_iki_write_setting_load_
-  extern void iki_write_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main);
+  extern void iki_write_setting_load(const f_console_arguments_t arguments, iki_write_main_t * const main, void (*callback)(const f_console_arguments_t arguments, iki_write_main_t * const main));
 #endif // _di_iki_write_setting_load_
 
 #ifdef __cplusplus
index d22642b6eaf2900919424b285303a7f55d7d610a..9f1b5464b021e3eed3467cb877167da4115e4086 100644 (file)
@@ -10,12 +10,14 @@ extern "C" {
     "f_file_read",
     "f_file_stream_open",
     "f_iki_write",
+    "f_memory_array_increase",
     "f_memory_arrays_resize",
     "f_string_dynamic_partial_append_nulless",
     "f_string_dynamic_seek_to",
     "f_thread_create",
     "fll_program_parameter_process_context_standard",
     "fll_program_parameter_process_verbosity_standard",
+    "iki_write_callback_load_objects_content_pipe",
   };
 #endif // _di_iki_write_f_a_
 
index bba8c099407d886fdb39b04f0f79953b04b8abe6..c4cfb9d5b4224d9160812f6ba59195e4a64d612e 100644 (file)
@@ -43,12 +43,14 @@ extern "C" {
     iki_write_f_f_file_read_e,
     iki_write_f_f_file_stream_open_e,
     iki_write_f_f_iki_write_e,
+    iki_write_f_f_memory_array_increase_e,
     iki_write_f_f_memory_arrays_resize_e,
     iki_write_f_f_string_dynamic_partial_append_nulless_e,
     iki_write_f_f_string_dynamic_seek_to_e,
     iki_write_f_f_thread_create_e,
     iki_write_f_fll_program_parameter_process_context_standard_e,
     iki_write_f_fll_program_parameter_process_verbosity_standard_e,
+    iki_write_f_iki_write_callback_load_objects_content_pipe_e,
   }; // enum
 #endif // _di_iki_write_f_e_
 
index eb4f9254b1116c53d14a8497600ea7c296d24ae2..24ac386935b6f7ff84092e1e774fd06accd1215b 100644 (file)
@@ -8,11 +8,6 @@ extern "C" {
   const f_string_static_t iki_write_program_version_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_version_s, 0, IKI_WRITE_program_version_s_length);
 #endif // _di_iki_write_program_version_s_
 
-#ifndef _di_iki_write_program_name_s_
-  const f_string_static_t iki_write_program_name_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_s, 0, IKI_WRITE_program_name_s_length);
-  const f_string_static_t iki_write_program_name_long_s = macro_f_string_static_t_initialize_1(IKI_WRITE_program_name_long_s, 0, IKI_WRITE_program_name_long_s_length);
-#endif // _di_iki_write_program_name_s_
-
 #ifndef _di_iki_write_s_
   const f_string_static_t iki_write_object_s = macro_f_string_static_t_initialize_1(IKI_WRITE_object_s, 0, IKI_WRITE_object_s_length);
 #endif // _di_iki_write_s_
index c1468f5407523692b8c6b900fecb05bd7f65f1c4..17058fc56dc4f40b5f27d6712561b01a623586b1 100644 (file)
@@ -46,20 +46,6 @@ extern "C" {
 #endif // _di_iki_write_program_version_s_
 
 /**
- * The program name.
- */
-#ifndef _di_iki_write_program_name_s_
-  #define IKI_WRITE_program_name_s      "iki_write"
-  #define IKI_WRITE_program_name_long_s "IKI Write"
-
-  #define IKI_WRITE_program_name_s_length      9
-  #define IKI_WRITE_program_name_long_s_length 9
-
-  extern const f_string_static_t iki_write_program_name_s;
-  extern const f_string_static_t iki_write_program_name_long_s;
-#endif // _di_iki_write_program_name_s_
-
-/**
  * Special strings used by this program.
  */
 #ifndef _di_iki_write_s_
@@ -68,6 +54,10 @@ extern "C" {
   #define IKI_WRITE_object_s_length 6
 
   extern const f_string_static_t iki_write_object_s;
+
+  // These are defined by the individual programs.
+  extern const f_string_static_t iki_write_program_name_s;
+  extern const f_string_static_t iki_write_program_name_long_s;
 #endif // _di_iki_write_s_
 
 /**
index 11f9da4035c235a6b2432a0dbe8535e3741cde33..c91ad318d2479468101a2f0de0d93feebd43aa87 100644 (file)
@@ -12,7 +12,8 @@ extern "C" {
     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->content.string, &cache->content.used, &cache->content.size);
     f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->iki.string, &cache->iki.used, &cache->iki.size);
-    f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->object.string, &cache->object.used, &cache->object.size);
+
+    f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &cache->objects.array, &cache->objects.used, &cache->objects.size, &f_string_dynamics_delete_callback);
   }
 #endif // _di_iki_write_cache_delete_
 
@@ -33,8 +34,8 @@ extern "C" {
 
     if (!setting) return;
 
-    f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &setting->objects.array, &setting->objects.used, &setting->objects.size, &f_string_dynamics_delete_callback);
     f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &setting->contents.array, &setting->contents.used, &setting->contents.size, &f_string_dynamics_delete_callback);
+    f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &setting->objectss.array, &setting->objectss.used, &setting->objectss.size, &f_string_dynamicss_delete_callback);
   }
 #endif // _di_iki_write_setting_delete_
 
index 35d4f69ecfb51a62515d44d9fcfe48cf0d356f8d..9c2babc3d3813858b5abb0c59a173e15a40487e0 100644 (file)
@@ -17,19 +17,45 @@ extern "C" {
 #endif
 
 /**
+ * The IKI write callbacks.
+ *
+ * load_objects_content_pipe: Load the Objects and Content from the pipe.
+ *
+ * print_help: Print the main help message.
+ *
+ * process_objects_content: Process an Objects and Content set.
+ */
+#ifndef _di_iki_write_callback_t_
+  typedef struct {
+    void (*load_objects_content_pipe)(void * const main, const f_range_t range, bool * const object_ended);
+
+    void (*print_help)(fl_print_t * const print);
+
+    void (*process_objects_content)(void * const main, const f_string_statics_t objects, const f_string_static_t content);
+  } iki_write_callback_t;
+
+  #define iki_write_callback_t_initialize \
+    { \
+      0, \
+      0, \
+      0, \
+    }
+#endif // _di_iki_write_callback_t_
+
+/**
  * The iki write main program cache.
  *
  * buffer:  A buffer used during processing the file.
  * content: A buffer used to hold a Content during processing.
  * iki:     A buffer used for writing the IKI during processing.
- * object:  A buffer used to hold an Object during processing.
+ * objects: A buffer used to hold Objects during processing.
  */
 #ifndef _di_iki_write_setting_t_
   typedef struct {
     f_string_dynamic_t buffer;
     f_string_dynamic_t content;
     f_string_dynamic_t iki;
-    f_string_dynamic_t object;
+    f_string_dynamics_t objects;
   } iki_write_cache_t;
 
   #define iki_write_cache_t_initialize \
@@ -37,7 +63,7 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
-      f_string_dynamic_t_initialize, \
+      f_string_dynamics_t_initialize, \
     }
 #endif // _di_iki_write_cache_t_
 
@@ -54,8 +80,8 @@ extern "C" {
  *
  * quote: This holds the quote used during processing.
  *
- * objects:  An array of objects passed as values to the "--object" parameter.
- * contents: An array of objects passed as values to the "--content" parameter and must match the length of objects.
+ * contents: An array of content passed as values to the "--content" parameter and must match the length of objects.
+ * objectss: An array of an array of objects passed as values to the "--object" parameter.
  */
 #ifndef _di_iki_write_setting_t_
   typedef struct {
@@ -66,8 +92,8 @@ extern "C" {
 
     f_string_static_t quote;
 
-    f_string_dynamics_t objects;
     f_string_dynamics_t contents;
+    f_string_dynamicss_t objectss;
   } iki_write_setting_t;
 
   #define iki_write_setting_t_initialize \
@@ -77,7 +103,7 @@ extern "C" {
       f_state_t_initialize, \
       f_string_static_t_initialize, \
       f_string_dynamics_t_initialize, \
-      f_string_dynamics_t_initialize, \
+      f_string_dynamicss_t_initialize, \
     }
 #endif // _di_iki_write_setting_t_
 
@@ -91,6 +117,7 @@ extern "C" {
 #ifndef _di_iki_write_main_t_
   typedef struct {
     iki_write_cache_t cache;
+    iki_write_callback_t callback;
     fll_program_data_t program;
     iki_write_setting_t setting;
   } iki_write_main_t;
@@ -98,6 +125,7 @@ extern "C" {
   #define iki_write_main_t_initialize \
     { \
       iki_write_cache_t_initialize, \
+      iki_write_callback_t_initialize, \
       fll_program_data_t_initialize, \
       iki_write_setting_t_initialize, \
     }
index f5c0ea6c02d21bba83a5d87bdc5ca874cf0c8638..b6389bd7fac3a8f87aad5b2d11888feb023a52b3 100644 (file)
@@ -13,7 +13,9 @@ extern "C" {
 
     if (main->setting.flag & iki_write_main_flag_version_copyright_help_d) {
       if (main->setting.flag & iki_write_main_flag_help_d) {
-        iki_write_print_message_help(&main->program.message);
+        if (main->callback.print_help) {
+          main->callback.print_help(&main->program.output);
+        }
       }
       else if (main->setting.flag & iki_write_main_flag_version_d) {
         fll_program_print_version(&main->program.message, iki_write_program_version_s);
@@ -36,8 +38,8 @@ extern "C" {
       pipe.size_read = 1;
 
       main->cache.buffer.used = 0;
-      main->cache.object.used = 0;
       main->cache.content.used = 0;
+      main->cache.objects.used = 0;
 
       range.start = 0;
 
@@ -108,47 +110,9 @@ extern "C" {
         range.stop = range.start - 1;
         range.start = previous;
 
-        if (object_ended) {
-          main->cache.content.used = 0;
-
-          if (main->cache.buffer.used) {
-            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.content);
-
-            if (F_status_is_error(main->setting.state.status)) {
-              iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
-
-              object_ended = F_false;
-
-              break;
-            }
-          }
-
-          iki_write_process(main, main->cache.object, main->cache.content);
-
-          if (F_status_is_error(main->setting.state.status)) {
-            object_ended = F_false;
-
-            break;
-          }
-
-          fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
-          object_ended = F_false;
-        }
-        else {
-          main->cache.object.used = 0;
-
-          main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.buffer, range, &main->cache.object);
-
-          if (F_status_is_error(main->setting.state.status)) {
-            iki_write_print_error(&main->program.error, macro_iki_write_f(f_string_dynamic_partial_append_nulless));
-
-            object_ended = F_false;
-
-            break;
-          }
-
-          object_ended = F_true;
+        if (main->callback.load_objects_content_pipe) {
+          main->callback.load_objects_content_pipe((void *) main, range, &object_ended);
+          if (F_status_is_error(main->setting.state.status)) break;
         }
 
         // Restore the range, positioned after the new line.
@@ -163,7 +127,7 @@ extern "C" {
 
       } while (status != F_okay_eof || main->cache.buffer.used || object_ended);
 
-      if (object_ended) {
+      if (F_status_is_error_not(main->setting.state.status) && object_ended) {
         main->setting.state.status = F_status_set_error(F_parameter);
 
         fll_program_print_error_pipe_object_without_content(&main->program.error);
@@ -171,7 +135,7 @@ extern "C" {
     }
 
     if (F_status_is_error_not(main->setting.state.status) && F_status_set_fine(main->setting.state.status) != F_interrupt) {
-      for (f_number_unsigned_t i = 0; i < main->setting.objects.used; ++i) {
+      for (f_number_unsigned_t i = 0; i < main->setting.objectss.used; ++i) {
 
         if (!((++main->program.signal_check) % iki_write_signal_check_d)) {
           if (fll_program_standard_signal_received(&main->program)) {
@@ -183,7 +147,7 @@ extern "C" {
           main->program.signal_check = 0;
         }
 
-        iki_write_process(main, main->setting.objects.array[i], main->setting.contents.array[i]);
+        main->callback.process_objects_content((void *) main, main->setting.objectss.array[i], main->setting.contents.array[i]);
         if (F_status_is_error(main->setting.state.status)) break;
 
         fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
index 192f65640ee404dc05ba551682da8279821143ad..c46b6ef0419248c703f59676259263cd1f6b0a59 100644 (file)
@@ -64,7 +64,6 @@
 #include <program/iki_write/main/common.h>
 #include <program/iki_write/main/print/error.h>
 #include <program/iki_write/main/print/message.h>
-#include <program/iki_write/main/process.h>
 #include <program/iki_write/main/signal.h>
 #include <program/iki_write/main/thread.h>
 
index fa389dcc035e493d388c0283bbc0c9603891353e..a234f3455e962c3e8839a0fe5d4de25e5734da8f 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
 
     f_file_stream_lock(print->to);
 
-    fl_print_format("%[%QNo main provided, either pipe the main data or use the '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%QNo data provided, either pipe the main data or use the '%]", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_rr_single_s.string, print->to, print->set->notable, f_console_symbol_long_normal_s, iki_write_long_object_s, print->set->notable);
     fl_print_format("%[' and the '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_rr_single_s.string, print->to, print->set->notable, f_console_symbol_long_normal_s, iki_write_long_content_s, print->set->notable);
@@ -50,24 +50,6 @@ extern "C" {
   }
 #endif // _di_iki_write_print_error_main_missing_
 
-#ifndef _di_iki_write_print_error_object_not_valid_
-  f_status_t iki_write_print_error_object_not_valid(fl_print_t * const print, const f_string_static_t object) {
-
-    if (!print) return F_status_set_error(F_output_not);
-    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
-
-    f_file_stream_lock(print->to);
-
-    fl_print_format("%[%QThe object '%]", print->to, print->set->error, print->prefix, print->set->error);
-    fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, object, print->set->notable);
-    fl_print_format("%[' is not a valid IKI Object (IKI Vocabulary).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
-
-    f_file_stream_unlock(print->to);
-
-    return F_okay;
-  }
-#endif // _di_iki_write_print_error_object_not_valid_
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 245f4288a3e80bc928744bb89ca81491455f2a2a..1bb156a482c1eca565e62239c687ceacbd0b3c7a 100644 (file)
@@ -86,26 +86,6 @@ extern "C" {
   extern f_status_t iki_write_print_error_main_missing(fl_print_t * const print);
 #endif // _di_iki_write_print_error_main_missing_
 
-/**
- * Print error message about an Object not being valid.
- *
- * @param print
- *   The output structure to print to.
- *
- *   This does not alter print.custom.setting.state.status.
- * @param object
- *   The a string representing the object that is missing.
- *
- * @return
- *   F_okay on success.
- *   F_output_not on success, but no printing is performed.
- *
- *   F_output_not (with error bit) if setting is NULL.
- */
-#ifndef _di_iki_write_print_error_object_not_valid_
-  extern f_status_t iki_write_print_error_object_not_valid(fl_print_t * const print, const f_string_static_t object);
-#endif // _di_iki_write_print_error_object_not_valid_
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 038afbc9cd9f7d115b8c84ce6e93bec76dcc2c1f..161d546c5e9203611a86c8b4dd7f7efbfbdcb6f0 100644 (file)
@@ -5,11 +5,9 @@ extern "C" {
 #endif
 
 #ifndef _di_iki_write_print_message_help_
-  f_status_t iki_write_print_message_help(fl_print_t * const print) {
+  void iki_write_print_message_help(fl_print_t * const print) {
 
-    if (!print) return F_status_set_error(F_output_not);
-
-    f_file_stream_lock(print->to);
+    if (!print) return;
 
     fll_program_print_help_header(print, iki_write_program_name_long_s, iki_write_program_version_s);
 
@@ -33,27 +31,22 @@ extern "C" {
     fll_program_print_help_option(print, iki_write_short_object_s, iki_write_long_object_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " The Object to write.");
     fll_program_print_help_option(print, iki_write_short_single_s, iki_write_long_single_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Use single quotes (U+0027).");
     fll_program_print_help_option(print, iki_write_short_wrap_s, iki_write_long_wrap_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "   Wrap the vocabulary name.");
+  }
+#endif // _di_iki_write_print_message_help_
 
-    f_print_dynamic_raw(f_string_eol_s, print->to);
+#ifndef _di_iki_write_print_message_help_note_
+  void iki_write_print_message_help_note(fl_print_t * const print) {
 
-    fll_program_print_help_usage(print, iki_write_program_name_s, f_string_empty_s);
+    if (!print) return;
 
     fl_print_format("%r %[Notes:%]%r", print->to, f_string_eol_s, print->set->important, print->set->important, f_string_eol_s);
     fl_print_format("  This program will accept Object and Content strings to generate an IKI string, such as %[object:\"content\"%].%r", print->to, print->set->notable, print->set->notable, f_string_eol_s);
     fl_print_format("  Each Object must have a Content (and each Content must have an Object).%r%r", print->to, f_string_eol_s, f_string_eol_s);
 
     fl_print_format("  The Object is also called the Vocabulary.%r", print->to, f_string_eol_s);
-    fl_print_format("  A complete Object and Content set is also called a Variable.%r%r", print->to, f_string_eol_s, f_string_eol_s);
-
-    fl_print_format("  When piping main to this program, a single form-feed character (\\f) (U+000C) must be used to separate each Object from each Content.%r", print->to, f_string_eol_s);
-    fl_print_format("  Furthermore, each Object must be followed by a Content.%r", print->to, f_string_eol_s);
-
-    f_file_stream_flush(print->to);
-    f_file_stream_unlock(print->to);
-
-    return F_okay;
+    fl_print_format("  A complete Object and Content set is also called a Variable.%r", print->to, f_string_eol_s);
   }
-#endif // _di_iki_write_print_message_help_
+#endif // _di_iki_write_print_message_help_note_
 
 #ifdef __cplusplus
 } // extern "C"
index 277f96e4d467b89f33b74f5d5ce4f57834f2054c..044739c310b881c454c707e5139d2ecea33dae42 100644 (file)
@@ -22,18 +22,30 @@ extern "C" {
  * @param print
  *   The output structure to print to.
  *
- *   This does not alter print.custom.setting.state.status.
- *
- * @return
- *   F_okay on success.
- *   F_output_not on success, but no printing is performed.
+ *   The print.custom is expected to be of type iki_write_main_t.
  *
- *   F_output_not (with error bit) if setting is NULL.
+ *   This does not alter print.custom.setting.state.status.
  */
 #ifndef _di_iki_write_print_message_help_
-  extern f_status_t iki_write_print_message_help(fl_print_t * const print);
+  extern void iki_write_print_message_help(fl_print_t * const print);
 #endif // _di_iki_write_print_message_help_
 
+/**
+ * Print standard parts of the help regarding notes.
+ *
+ * This is expected to be called as part of the help printing and does not perform any locking.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   The print.custom is expected to be of type iki_write_main_t.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ */
+#ifndef _di_iki_write_print_message_help_note_
+  extern void iki_write_print_message_help_note(fl_print_t * const print);
+#endif // _di_iki_write_print_message_help_note_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/level_3/iki_write/c/main/process.c b/level_3/iki_write/c/main/process.c
deleted file mode 100644 (file)
index 3fd6316..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "iki_write.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_iki_write_process_
-  void iki_write_process(iki_write_main_t * const main, const f_string_static_t object, const f_string_static_t content) {
-
-    if (!main) return;
-
-    if (!object.used) {
-      main->setting.state.status = F_status_set_error(F_failure);
-
-      fll_program_print_error_missing_variable_not_zero(&main->program.error, iki_write_object_s);
-
-      return;
-    }
-
-    main->cache.iki.used = 0;
-
-    f_iki_write(object, content, main->setting.quote, &main->cache.iki, &main->setting.state);
-
-    if (F_status_is_error(main->setting.state.status)) {
-      if (F_status_set_fine(main->setting.state.status) == F_syntax) {
-        iki_write_print_error_object_not_valid(&main->program.error, object);
-      }
-      else {
-        iki_write_print_error(&main->program.error, macro_iki_write_f(f_iki_write));
-      }
-
-      return;
-    }
-
-    f_print_dynamic(main->cache.iki, main->program.output.to);
-
-    main->setting.state.status = F_okay;
-  }
-#endif // _di_iki_write_process_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/iki_write/c/main/process.h b/level_3/iki_write/c/main/process.h
deleted file mode 100644 (file)
index 59d5b50..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: IKI Write
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- *
- * Provides the process functionality.
- *
- * This is auto-included and should not need to be explicitly included.
- */
-#ifndef _iki_write_write_process_h
-#define _iki_write_write_process_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Process a given object and content, printing it.
- *
- * @param main
- *   The program and settings data.
- *
- *   This alters main.setting.state.status:
- *     F_okay on success.
- *
- *     Errors (with error bit) from: f_iki_write().
- *
- *     F_failure (with error bit) for any other failure.
- * @param object
- *   The object to validate and print.
- * @param content
- *   The content to escape and print.
- *
- * @see iki_write_print_error_object_not_valid()
- * @see f_iki_write()
- */
-#ifndef _di_iki_write_process_
-  extern void iki_write_process(iki_write_main_t * const main, const f_string_static_t object, const f_string_static_t content);
-#endif // _di_iki_write_process_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _iki_write_write_process_h
index 4f46ac88b225cede68ca0923919c8091e554a7ec..a8fe20859cc8e8700b706db83fa9f5461b57c208 100644 (file)
@@ -8,14 +8,18 @@ settings:
   environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
 
 main:
-  build
+  build settings
+  build settings.eki_write
+  build settings.iki_write
 
 install:
   shell ./install.sh parameter:'work' parameter:'verbosity' parameter:'color'
+  shell ./install.sh parameter:'work' parameter:'verbosity' parameter:'color' -s data/build/settings.eki_write
+  shell ./install.sh parameter:'work' parameter:'verbosity' parameter:'color' -s data/build/settings.iki_write
 
 help:
   print
-  print context:'title'Fakefile Options for IKI Write Program.context:'reset'
+  print context:'title'Fakefile Options for IKI Write Programs.context:'reset'
 
   print
   print The following operations are available\:
index 5f3acd771d0d9195e1dbe8706036c4aa1205ab02..22f17778b460636dd5c9432334df652eabbb1e0b 100644 (file)
@@ -1,5 +1,7 @@
 # fss-0001
 #
+# Builds the main library of the project with all parts except "main" program related.
+#
 # Modes:
 #   - android:           Compile on an android system (using Termux; may need modification depending on the android system).
 #   - clang:             Use CLang rather than the default, which is generally GCC.
@@ -38,11 +40,9 @@ build_libraries-individual_thread -lf_thread
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 
-build_sources_library main/iki_write.c main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/process.c main/signal.c main/thread.c
-
-build_sources_program main/main.c
+build_sources_library main/iki_write.c main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/signal.c main/thread.c
 
-build_sources_headers main/iki_write.h main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/process.h main/signal.h main/thread.h
+build_sources_headers main/iki_write.h main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/signal.h main/thread.h
 
 build_sources_documentation man
 
diff --git a/level_3/iki_write/data/build/settings.eki_write b/level_3/iki_write/data/build/settings.eki_write
new file mode 100644 (file)
index 0000000..917dda7
--- /dev/null
@@ -0,0 +1,71 @@
+# fss-0001
+#
+# Builds the "iki_write" program.
+# This must be called after the "setting".
+#
+
+build_name eki_write
+
+version_major 0
+version_minor 7
+version_micro 0
+version_file micro
+version_target minor
+
+modes android clang coverage fanalyzer gcc gcc_13 individual individual_thread level monolithic test thread threadless
+modes_default monolithic thread gcc
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+build_libraries -lc -liki_write
+build_libraries-individual -lfll_error -lfll_iki -lfll_print -lfll_program -lfl_iki -lfl_print -lf_color -lf_console -lf_conversion -lf_file -lf_iki -lf_memory -lf_pipe -lf_print -lf_rip -lf_signal -lf_string -lf_type_array -lf_utf
+build_libraries-individual_thread -lf_thread
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+
+build_sources_program eki/common.c eki/eki_write.c eki/main.c eki/print.c eki/process.c
+
+build_sources_headers eki/common.h eki/eki_write.h eki/print.h eki/process.h
+
+build_sources_documentation man
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers program/iki_write
+
+has_path_standard yes
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+#defines -D_di_libcap_
+defines -D_libcap_legacy_only_
+defines-android -D_di_f_thread_attribute_affinity_get_ -D_di_f_thread_attribute_affinity_set_ -D_di_f_thread_attribute_concurrency_get_ -D_di_f_thread_attribute_concurrency_set_ -D_di_f_thread_attribute_default_get_ -D_di_f_thread_attribute_default_set_ -D_di_f_thread_cancel_ -D_di_f_thread_cancel_state_set_ -D_di_f_thread_cancel_test_ -D_di_f_thread_join_try_ -D_di_f_thread_join_timed_ -D_pthread_mutex_prioceiling_unsupported_ -D_di_f_thread_semaphore_file_close_ -D_di_f_thread_semaphore_file_open_ -D_di_f_thread_semaphore_file_delete_ -D_di_f_thread_cancel_type_set_
+defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
+defines-threadless -D_di_thread_support_
+
+flags -O2 -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses -Wno-missing-braces
+flags -fstack-clash-protection -fno-delete-null-pointer-checks
+flags -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
+flags-android -Wno-implicit-function-declaration -Wl,-z,norelro
+flags-clang -Wno-logical-op-parentheses
+flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+flags-fanalyzer -fanalyzer
+flags-gcc_13 -fstrict-flex-arrays=3
+flags-test -O0 -fstack-protector-strong -Wall
+flags-thread -pthread
+
+flags_library -fPIC
+flags_object -fPIC
+flags_program -fPIE
+flags_program-android -fPIE -Wl,-z,relro
diff --git a/level_3/iki_write/data/build/settings.iki_write b/level_3/iki_write/data/build/settings.iki_write
new file mode 100644 (file)
index 0000000..cc9da19
--- /dev/null
@@ -0,0 +1,71 @@
+# fss-0001
+#
+# Builds the "iki_write" program.
+# This must be called after the "setting".
+#
+
+build_name iki_write
+
+version_major 0
+version_minor 7
+version_micro 0
+version_file micro
+version_target minor
+
+modes android clang coverage fanalyzer gcc gcc_13 individual individual_thread level monolithic test thread threadless
+modes_default monolithic thread gcc
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+build_libraries -lc -liki_write
+build_libraries-individual -lfll_error -lfll_iki -lfll_print -lfll_program -lfl_iki -lfl_print -lf_color -lf_console -lf_conversion -lf_file -lf_iki -lf_memory -lf_pipe -lf_print -lf_rip -lf_signal -lf_string -lf_type_array -lf_utf
+build_libraries-individual_thread -lf_thread
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+
+build_sources_program iki/common.c iki/iki_write.c iki/main.c iki/print.c iki/process.c
+
+build_sources_headers iki/common.h iki/iki_write.h iki/print.h iki/process.h
+
+build_sources_documentation man
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers program/iki_write
+
+has_path_standard yes
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+#defines -D_di_libcap_
+defines -D_libcap_legacy_only_
+defines-android -D_di_f_thread_attribute_affinity_get_ -D_di_f_thread_attribute_affinity_set_ -D_di_f_thread_attribute_concurrency_get_ -D_di_f_thread_attribute_concurrency_set_ -D_di_f_thread_attribute_default_get_ -D_di_f_thread_attribute_default_set_ -D_di_f_thread_cancel_ -D_di_f_thread_cancel_state_set_ -D_di_f_thread_cancel_test_ -D_di_f_thread_join_try_ -D_di_f_thread_join_timed_ -D_pthread_mutex_prioceiling_unsupported_ -D_di_f_thread_semaphore_file_close_ -D_di_f_thread_semaphore_file_open_ -D_di_f_thread_semaphore_file_delete_ -D_di_f_thread_cancel_type_set_
+defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
+defines-threadless -D_di_thread_support_
+
+flags -O2 -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses -Wno-missing-braces
+flags -fstack-clash-protection -fno-delete-null-pointer-checks
+flags -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
+flags-android -Wno-implicit-function-declaration -Wl,-z,norelro
+flags-clang -Wno-logical-op-parentheses
+flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+flags-fanalyzer -fanalyzer
+flags-gcc_13 -fstrict-flex-arrays=3
+flags-test -O0 -fstack-protector-strong -Wall
+flags-thread -pthread
+
+flags_library -fPIC
+flags_object -fPIC
+flags_program -fPIE
+flags_program-android -fPIE -Wl,-z,relro