]> Kevux Git Server - fll/commitdiff
Update: Control program to latest design practices, migrating from 0.6.x to 0.7.x...
authorKevin Day <kevin@kevux.org>
Fri, 4 Aug 2023 04:54:38 +0000 (23:54 -0500)
committerKevin Day <kevin@kevux.org>
Fri, 4 Aug 2023 04:54:38 +0000 (23:54 -0500)
This gets the control program to compile under the latest design practices.

I did not to an in depth review as this program does not currently do anything.
Once the controller program is updated I will eventually come back to this.

49 files changed:
level_3/control/c/common.c [deleted file]
level_3/control/c/common.h [deleted file]
level_3/control/c/control.c [deleted file]
level_3/control/c/main.c [deleted file]
level_3/control/c/main/action.c [new file with mode: 0644]
level_3/control/c/main/action.h [new file with mode: 0644]
level_3/control/c/main/common.c [new file with mode: 0644]
level_3/control/c/main/common.h [new file with mode: 0644]
level_3/control/c/main/common/define.c [new file with mode: 0644]
level_3/control/c/main/common/define.h [new file with mode: 0644]
level_3/control/c/main/common/enumeration.c [new file with mode: 0644]
level_3/control/c/main/common/enumeration.h [new file with mode: 0644]
level_3/control/c/main/common/print.c [new file with mode: 0644]
level_3/control/c/main/common/print.h [new file with mode: 0644]
level_3/control/c/main/common/string.c [moved from level_3/control/c/private-common.c with 70% similarity]
level_3/control/c/main/common/string.h [moved from level_3/control/c/private-common.h with 63% similarity]
level_3/control/c/main/common/type.c [new file with mode: 0644]
level_3/control/c/main/common/type.h [new file with mode: 0644]
level_3/control/c/main/control.c [new file with mode: 0644]
level_3/control/c/main/control.h [moved from level_3/control/c/control.h with 57% similarity]
level_3/control/c/main/main.c [new file with mode: 0644]
level_3/control/c/main/main.h [moved from level_3/control/c/main.h with 100% similarity]
level_3/control/c/main/packet.c [new file with mode: 0644]
level_3/control/c/main/packet.h [new file with mode: 0644]
level_3/control/c/main/payload.c [new file with mode: 0644]
level_3/control/c/main/payload.h [new file with mode: 0644]
level_3/control/c/main/print/data.c [new file with mode: 0644]
level_3/control/c/main/print/data.h [new file with mode: 0644]
level_3/control/c/main/print/debug.c [new file with mode: 0644]
level_3/control/c/main/print/debug.h [new file with mode: 0644]
level_3/control/c/main/print/error.c [new file with mode: 0644]
level_3/control/c/main/print/error.h [new file with mode: 0644]
level_3/control/c/main/print/message.c [new file with mode: 0644]
level_3/control/c/main/print/message.h [new file with mode: 0644]
level_3/control/c/main/print/warning.c [new file with mode: 0644]
level_3/control/c/main/print/warning.h [new file with mode: 0644]
level_3/control/c/main/process.c [new file with mode: 0644]
level_3/control/c/main/process.h [new file with mode: 0644]
level_3/control/c/main/signal.c [new file with mode: 0644]
level_3/control/c/main/signal.h [new file with mode: 0644]
level_3/control/c/main/thread.c [new file with mode: 0644]
level_3/control/c/main/thread.h [new file with mode: 0644]
level_3/control/c/print.c [deleted file]
level_3/control/c/print.h [deleted file]
level_3/control/c/private-control.c [deleted file]
level_3/control/c/private-control.h [deleted file]
level_3/control/c/private-print.c [deleted file]
level_3/control/c/private-print.h [deleted file]
level_3/control/data/build/settings

diff --git a/level_3/control/c/common.c b/level_3/control/c/common.c
deleted file mode 100644 (file)
index a08cbf2..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-#include "control.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_control_program_version_s_
-  const f_string_static_t control_program_version_s = macro_f_string_static_t_initialize_1(CONTROL_program_version_s, 0, CONTROL_program_version_s_length);
-#endif // _di_control_program_version_s_
-
-#ifndef _di_control_program_name_s_
-  const f_string_static_t control_program_name_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_s, 0, CONTROL_program_name_s_length);
-  const f_string_static_t control_program_name_long_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_long_s, 0, CONTROL_program_name_long_s_length);
-#endif // _di_control_program_name_s_
-
-#ifndef _di_control_parameter_d_
-  const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize_1(CONTROL_short_name_s, 0, CONTROL_short_name_s_length);
-  const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize_1(CONTROL_short_return_s, 0, CONTROL_short_return_s_length);
-  const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize_1(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length);
-  const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize_1(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length);
-
-  const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize_1(CONTROL_long_name_s, 0, CONTROL_long_name_s_length);
-  const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize_1(CONTROL_long_return_s, 0, CONTROL_long_return_s_length);
-  const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize_1(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length);
-  const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize_1(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length);
-#endif // _di_control_parameter_d_
-
-#ifndef _di_control_action_type_identify_
-  uint8_t control_action_type_identify(const f_string_static_t action) {
-
-    if (f_compare_dynamic(action, control_freeze_s) == F_equal_to) {
-      return control_action_type_freeze_e;
-    }
-
-    if (f_compare_dynamic(action, control_kexec_s) == F_equal_to) {
-      return control_action_type_kexec_e;
-    }
-
-    if (f_compare_dynamic(action, control_kill_s) == F_equal_to) {
-      return control_action_type_kill_e;
-    }
-
-    if (f_compare_dynamic(action, control_pause_s) == F_equal_to) {
-      return control_action_type_pause_e;
-    }
-
-    if (f_compare_dynamic(action, control_reboot_s) == F_equal_to) {
-      return control_action_type_reboot_e;
-    }
-
-    if (f_compare_dynamic(action, control_reload_s) == F_equal_to) {
-      return control_action_type_reload_e;
-    }
-
-    if (f_compare_dynamic(action, control_rerun_s) == F_equal_to) {
-      return control_action_type_rerun_e;
-    }
-
-    if (f_compare_dynamic(action, control_restart_s) == F_equal_to) {
-      return control_action_type_restart_e;
-    }
-
-    if (f_compare_dynamic(action, control_resume_s) == F_equal_to) {
-      return control_action_type_resume_e;
-    }
-
-    if (f_compare_dynamic(action, control_shutdown_s) == F_equal_to) {
-      return control_action_type_shutdown_e;
-    }
-
-    if (f_compare_dynamic(action, control_start_s) == F_equal_to) {
-      return control_action_type_start_e;
-    }
-
-    if (f_compare_dynamic(action, control_stop_s) == F_equal_to) {
-      return control_action_type_stop_e;
-    }
-
-    if (f_compare_dynamic(action, control_thaw_s) == F_equal_to) {
-      return control_action_type_thaw_e;
-    }
-
-    return 0;
-  }
-#endif // _di_control_action_type_identify_
-
-#ifndef _di_control_action_type_name_
-  f_string_static_t control_action_type_name(const uint8_t type) {
-
-    switch (type) {
-      case control_action_type_freeze_e:
-        return control_freeze_s;
-
-      case control_action_type_kexec_e:
-        return control_kexec_s;
-
-      case control_action_type_kill_e:
-        return control_kill_s;
-
-      case control_action_type_pause_e:
-        return control_pause_s;
-
-      case control_action_type_reboot_e:
-        return control_reboot_s;
-
-      case control_action_type_reload_e:
-        return control_reload_s;
-
-      case control_action_type_rerun_e:
-        return control_rerun_s;
-
-      case control_action_type_restart_e:
-        return control_restart_s;
-
-      case control_action_type_resume_e:
-        return control_resume_s;
-
-      case control_action_type_shutdown_e:
-        return control_shutdown_s;
-
-      case control_action_type_start_e:
-        return control_start_s;
-
-      case control_action_type_stop_e:
-        return control_stop_s;
-
-      case control_action_type_thaw_e:
-        return control_thaw_s;
-    }
-
-    return f_string_empty_s;
-  }
-#endif // _di_control_action_type_name_
-
-#ifndef _di_control_payload_type_identify_
-  uint8_t control_payload_type_identify(const f_string_static_t payload) {
-
-    if (f_compare_dynamic(payload, control_controller_s) == F_equal_to) {
-      return control_payload_type_controller_e;
-    }
-
-    if (f_compare_dynamic(payload, control_error_s) == F_equal_to) {
-      return control_payload_type_error_e;
-    }
-
-    if (f_compare_dynamic(payload, control_init_s) == F_equal_to) {
-      return control_payload_type_init_e;
-    }
-
-    return 0;
-  }
-#endif // _di_control_payload_type_identify_
-
-#ifndef _di_control_payload_type_name_
-  f_string_static_t control_payload_type_name(const uint8_t type) {
-
-    switch (type) {
-      case control_payload_type_controller_e:
-        return control_controller_s;
-
-      case control_payload_type_error_e:
-        return control_error_s;
-
-      case control_payload_type_init_e:
-        return control_init_s;
-    }
-
-    return f_string_empty_s;
-  }
-#endif // _di_control_payload_type_name_
-
-#ifndef _di_control_setting_delete_
-  f_status_t control_setting_delete(control_setting_t * const setting) {
-
-    if (!setting) return F_status_set_error(F_parameter);
-
-    return F_none;
-  }
-#endif // _di_control_setting_delete_
-
-#ifndef _di_control_setting_load_
-  void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting) {
-
-    if (!main) return;
-
-    setting->state.step_small = control_allocation_console_d;
-
-    f_console_parameter_process(arguments, &main->parameters, &setting->state, 0);
-
-    setting->state.step_small = control_write_allocation_small_d;
-
-    // Identify and process first/last parameters.
-    if (main->parameters.array[control_parameter_line_first_no_e].result & f_console_result_found_e) {
-      setting->flag -= setting->flag & control_main_flag_print_first_e;
-    }
-    else {
-      setting->flag |= control_main_flag_print_first_e;
-    }
-
-    if (main->parameters.array[control_parameter_line_last_no_e].result & f_console_result_found_e) {
-      setting->flag -= setting->flag & control_main_flag_print_last_e;
-    }
-    else {
-      setting->flag |= control_main_flag_print_last_e;
-    }
-
-    if (F_status_is_error(setting->state.status)) {
-      fll_error_print(main->error, F_status_set_fine(setting->state.status), "f_console_parameter_process", fll_error_file_flag_fallback_e);
-
-      if (main->error.verbosity > f_console_verbosity_quiet_e) {
-        fll_print_dynamic_raw(f_string_eol_s, main->error);
-      }
-
-      return;
-    }
-
-    {
-      f_number_unsigned_t choice = 0;
-      f_uint16s_t choices = f_uint16s_t_initialize;
-
-      // Identify and prioritize "color context" parameters.
-      {
-        uint16_t choices_array[3] = { control_parameter_no_color_e, control_parameter_light_e, control_parameter_dark_e };
-        choices.array = choices_array;
-        choices.used = 3;
-
-        static const uint8_t modes[3] = { f_color_mode_not_e, f_color_mode_light_e, f_color_mode_dark_e };
-
-        setting->state.status = fll_program_parameter_process_context(choices, modes, F_true, &main->program);
-
-        if (F_status_is_error(setting->state.status)) {
-          fll_error_print(main->error, F_status_set_fine(setting->state.status), "fll_program_parameter_process_context", fll_error_file_flag_fallback_e);
-
-          if (main->error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->error);
-          }
-
-          return;
-        }
-      }
-
-      // Identify and prioritize "verbosity" parameters.
-      {
-        uint16_t choices_array[5] = { control_parameter_verbosity_quiet_e, control_parameter_verbosity_error_e, control_parameter_verbosity_verbose_e, control_parameter_verbosity_debug_e, control_parameter_verbosity_normal_e };
-        choices.array = choices_array;
-        choices.used = 5;
-
-        static const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e };
-
-        setting->state.status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program);
-
-        if (F_status_is_error(setting->state.status)) {
-          fll_error_print(main->error, F_status_set_fine(setting->state.status), "fll_program_parameter_process_verbosity", fll_error_file_flag_fallback_e);
-
-          if (main->error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->error);
-          }
-
-          return;
-        }
-      }
-    }
-
-    main->output.to.id = F_type_descriptor_output_d;
-    main->output.to.stream = F_type_output_d;
-    main->output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d;
-
-    if (main->parameters.array[control_parameter_help_e].result & f_console_result_found_e) {
-      setting->flag |= control_main_flag_help_e;
-
-      return;
-    }
-
-    if (main->parameters.array[control_parameter_version_e].result & f_console_result_found_e) {
-      setting->flag |= control_main_flag_version_e;
-
-      return;
-    }
-
-    if (main->parameters.array[control_parameter_copyright_e].result & f_console_result_found_e) {
-      setting->flag |= control_main_flag_copyright_e;
-
-      return;
-    }
-
-    f_string_static_t * const args = main->parameters.arguments.array;
-
-    if (main->parameters.array[control_parameter_strip_invalid_e].result & f_console_result_found_e) {
-      setting->flag |= control_main_flag_strip_invalid_e;
-    }
-  }
-#endif // _di_control_setting_load_
-
-#ifndef _di_control_setting_unload_
-  f_status_t control_setting_unload(control_main_t * const main) {
-
-    if (!main) return F_status_set_error(F_parameter);
-
-    control_setting_delete(&control_main_t->setting);
-
-    return F_none;
-  }
-#endif // _di_control_setting_unload_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/control/c/common.h b/level_3/control/c/common.h
deleted file mode 100644 (file)
index d3f1cd0..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Control
- * 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 _control_common_h
-#define _control_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The program version.
- */
-#ifndef _di_control_program_version_s_
-  #define CONTROL_program_version_major_s F_string_ascii_0_s
-  #define CONTROL_program_version_minor_s F_string_ascii_7_s
-  #define CONTROL_program_version_micro_s F_string_ascii_0_s
-
-  #define CONTROL_program_version_major_s_length F_string_ascii_0_s_length
-  #define CONTROL_program_version_minor_s_length F_string_ascii_7_s_length
-  #define CONTROL_program_version_micro_s_length F_string_ascii_0_s_length
-
-  #if !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length))
-    #define CONTROL_program_version_nano_prefix_s
-    #define CONTROL_program_version_nano_prefix_s_length 0
-  #endif // !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length))
-
-  #if !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length))
-    #define CONTROL_program_version_nano_s
-    #define CONTROL_program_version_nano_s_length 0
-  #endif // !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length))
-
-  #define CONTROL_program_version_s CONTROL_program_version_major_s F_string_ascii_period_s CONTROL_program_version_minor_s F_string_ascii_period_s CONTROL_program_version_micro_s CONTROL_program_version_nano_prefix_s CONTROL_program_version_nano_s
-
-  #define CONTROL_program_version_s_length CONTROL_program_version_major_s_length + F_string_ascii_period_s_length + CONTROL_program_version_minor_s_length + F_string_ascii_period_s_length + CONTROL_program_version_micro_s_length + CONTROL_program_version_nano_prefix_s_length + CONTROL_program_version_nano_s_length
-
-  extern const f_string_static_t control_program_version_s;
-#endif // _di_control_program_version_s_
-
-/**
- * The program name.
- */
-#ifndef _di_control_program_name_s_
-  #define CONTROL_program_name_s      "control"
-  #define CONTROL_program_name_long_s "Control Program"
-
-  #define CONTROL_program_name_s_length      7
-  #define CONTROL_program_name_long_s_length 15
-
-  extern const f_string_static_t control_program_name_s;
-  extern const f_string_static_t control_program_name_long_s;
-#endif // _di_control_program_name_s_
-
-/**
- * The program defines.
- *
- * control_*_d:
- *   - allocation_console: An allocation step used for small buffers specifically for console parameter.
- *   - allocation_large:   An allocation step used for buffers that are anticipated to have large buffers.
- *   - allocation_small:   An allocation step used for buffers that are anticipated to have small buffers.
- *   - signal_check:       Number of iterations before performing signal check in non-threaded signal handling.
- */
-#ifndef _di_control_d_
-  #define control_allocation_console_d 4
-  #define control_allocation_large_d   256
-  #define control_allocation_small_d   16
-  #define control_signal_check_d       20000
-#endif // _di_control_d_
-
-/**
- * The main program parameters.
- */
-#ifndef _di_control_parameter_d_
-  #define CONTROL_short_name_s     "n"
-  #define CONTROL_short_return_s   "R"
-  #define CONTROL_short_settings_s "s"
-  #define CONTROL_short_socket_s   "k"
-
-  #define CONTROL_long_name_s     "name"
-  #define CONTROL_long_return_s   "return"
-  #define CONTROL_long_settings_s "settings"
-  #define CONTROL_long_socket_s   "socket"
-
-  #define CONTROL_short_name_s_length     1
-  #define CONTROL_short_return_s_length   1
-  #define CONTROL_short_settings_s_length 1
-  #define CONTROL_short_socket_s_length   1
-
-  #define CONTROL_long_name_s_length     4
-  #define CONTROL_long_return_s_length   6
-  #define CONTROL_long_settings_s_length 8
-  #define CONTROL_long_socket_s_length   6
-
-  extern const f_string_static_t control_short_name_s;
-  extern const f_string_static_t control_short_return_s;
-  extern const f_string_static_t control_short_settings_s;
-  extern const f_string_static_t control_short_socket_s;
-
-  extern const f_string_static_t control_long_name_s;
-  extern const f_string_static_t control_long_return_s;
-  extern const f_string_static_t control_long_settings_s;
-  extern const f_string_static_t control_long_socket_s;
-
-  enum {
-    control_parameter_help_e = 0,
-    control_parameter_copyright_e,
-    control_parameter_light_e,
-    control_parameter_dark_e,
-    control_parameter_no_color_e,
-    control_parameter_verbosity_quiet_e,
-    control_parameter_verbosity_error_e,
-    control_parameter_verbosity_normal_e,
-    control_parameter_verbosity_verbose_e,
-    control_parameter_verbosity_debug_e,
-    control_parameter_version_e,
-    control_parameter_line_first_no_e,
-    control_parameter_line_last_no_e,
-
-    control_parameter_name_e,
-    control_parameter_return_e,
-    control_parameter_settings_e,
-    control_parameter_socket_e,
-  }; // enum
-
-  #define control_console_parameter_t_initialize \
-    { \
-      macro_fll_program_console_parameter_standard_initialize, \
-      \
-      macro_f_console_parameter_t_initialize_3(control_short_name_s,     control_long_name_s,     1, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(control_short_return_s,   control_long_return_s,   1, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(control_short_settings_s, control_long_settings_s, 1, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(control_short_socket_s,   control_long_socket_s,   1, f_console_flag_normal_e), \
-    }
-
-  #define control_parameter_total_d 17
-#endif // _di_control_parameter_d_
-
-/**
- * Codes representing supported actions.
- *
- * freeze:   Perform the freeze controller operation.
- * kexec:    Perform the kexec controller operation (only for init mode).
- * kill:     Perform the kill controller operation.
- * pause:    Perform the pause controller operation.
- * reboot:   Perform the reboot controller operation (only for init mode).
- * reload:   Perform the reload controller operation.
- * rerun:    Perform the rerun controller operation.
- * restart:  Perform the restart controller operation.
- * resume:   Perform the resume controller operation.
- * shutdown: Perform the shutdown controller operation (only for init mode).
- * start:    Perform the start controller operation.
- * stop:     Perform the stop controller operation.
- * thaw:     Perform the thaw controller operation.
- */
-#ifndef _di_control_action_type_e_
-  enum {
-    control_action_type_freeze_e = 1,
-    control_action_type_kexec_e,
-    control_action_type_kill_e,
-    control_action_type_pause_e,
-    control_action_type_reboot_e,
-    control_action_type_reload_e,
-    control_action_type_rerun_e,
-    control_action_type_restart_e,
-    control_action_type_resume_e,
-    control_action_type_shutdown_e,
-    control_action_type_start_e,
-    control_action_type_stop_e,
-    control_action_type_thaw_e,
-  }; // enum
-#endif // _di_control_action_type_e_
-
-/**
- * Supported payload types.
- *
- * controller: The payload is a controller payload.
- * error:      The payload is an error payload.
- * init:       The payload is an init payload (only available when operating in "init" mode).
- */
-#ifndef _di_control_payload_type_e_
-  enum {
-    control_payload_type_controller_e = 1,
-    control_payload_type_error_e,
-    control_payload_type_init_e,
-  }; // enum
-#endif // _di_control_payload_type_e_
-
-/**
- * Flags passed to the main function or program.
- *
- * control_main_flag_*_e:
- *   - none:          No flags set.
- *   - copyright:     Print copyright.
- *   - file_from:     Using a specified source file.
- *   - file_to:       Using a specified destination file.
- *   - header:        Enable printing of headers.
- *   - help:          Print help.
- *   - print_first:   When set, print new line to message output on program begin after loading settings.
- *   - print_last:    When set, print new line to message output on program end.
- *   - separate:      Enable printing of separators.
- *   - strip_invalid: Using strip invalid character mode.
- *   - verify:        Using verify mode.
- *   - version:       Print version.
- */
-#ifndef _di_control_main_flag_e_
-  enum {
-    control_main_flag_none_e          = 0x0,
-    control_main_flag_copyright_e     = 0x1,
-    control_main_flag_file_from_e     = 0x2,
-    control_main_flag_file_to_e       = 0x4,
-    control_main_flag_header_e        = 0x8,
-    control_main_flag_help_e          = 0x10,
-    control_main_flag_print_first_e   = 0x20,
-    control_main_flag_print_last_e    = 0x40,
-    control_main_flag_separate_e      = 0x80,
-    control_main_flag_strip_invalid_e = 0x100,
-    control_main_flag_verify_e        = 0x200,
-    control_main_flag_version_e       = 0x400,
-  }; // enum
-#endif // _di_control_main_flag_e_
-
-/**
- * The control main program settings.
- *
- * This is passed to the program-specific main entry point to designate program settings.
- * These program settings are often processed from the program arguments (often called the command line arguments).
- *
- * flag: Flags passed to the main function.
- *
- * state: The state information.
- */
-#ifndef _di_control_setting_t_
-  typedef struct {
-    uint16_t flag;
-
-    f_state_t state;
-  } control_setting_t;
-
-  #define control_setting_t_initialize \
-    { \
-      control_main_flag_none_e, \
-      f_state_t_initialize, \
-    }
-#endif // _di_control_setting_t_
-
-/**
- * Identify the action code the given name represents.
- *
- * @param action
- *   The string representing an action.
- *
- * @return
- *   The action type code on success.
- *   0 if name is unknown.
- */
-#ifndef _di_control_action_type_identify_
-  extern uint8_t control_action_type_identify(const f_string_static_t action);
-#endif // _di_control_action_type_identify_
-
-/**
- * Get a string representing the action type.
- *
- * @param type
- *   The action type id.
- *
- * @return
- *   The string with used > 0 on success.
- *   The string with used == 0 if no match was found.
- */
-#ifndef _di_control_action_type_name_
-  extern f_string_static_t control_action_type_name(const uint8_t type);
-#endif // _di_control_action_type_name_
-
-/**
- * Identify the payload code the given name represents.
- *
- * @param payload
- *   The string representing a payload.
- *
- * @return
- *   The payload type code on success.
- *   0 if name is unknown.
- */
-#ifndef _di_control_payload_type_identify_
-  extern uint8_t control_payload_type_identify(const f_string_static_t payload);
-#endif // _di_control_payload_type_identify_
-
-/**
- * Get a string representing the payload type.
- *
- * @param type
- *   The payload type id.
- *
- * @return
- *   The string with used > 0 on success.
- *   The string with used == 0 if no match was found.
- */
-#ifndef _di_control_payload_type_name_
-  extern f_string_static_t control_payload_type_name(const uint8_t type);
-#endif // _di_control_payload_type_name_
-
-/**
- * Delete the program main setting data.
- *
- * @param setting
- *   The program main setting data.
- *
- *   This does not alter setting.state.status.
- *
- * @return
- *   F_none on success.
- *
- *   F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_control_setting_delete_
-  extern f_status_t control_setting_delete(control_setting_t * const setting);
-#endif // _di_control_setting_delete_
-
-/**
- * Perform the standard program setting load process.
- *
- * 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 main program data.
- * @param setting
- *   The main program settings.
- *
- *   This alters setting.state.status:
- *     F_none on success.
- *
- *     Errors (with error bit) from: f_console_parameter_process().
- *     Errors (with error bit) from: fll_program_parameter_process_context().
- *
- * @see f_console_parameter_process()
- * @see fll_program_parameter_process_context()
- */
-#ifndef _di_control_setting_load_
-  extern void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting);
-#endif // _di_control_setting_load_
-
-/**
- * Perform the standard program setting unload process.
- *
- * @param main
- *   The main program and setting data.
- *   All buffers are deallocated.
- *
- *   This does not alter main.setting.state.status.
- *
- * @return
- *   F_none on success.
- *
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   Errors (with error bit) from: control_setting_delete().
- *
- * @see control_setting_delete()
- */
-#ifndef _di_control_setting_unload_
-  extern f_status_t control_setting_unload(control_main_t * const main);
-#endif // _di_control_setting_unload_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _control_common_h
diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c
deleted file mode 100644 (file)
index 3774ccb..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "control.h"
-#include "private-common.h"
-#include "private-control.h"
-#include "private-print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_control_main_
-  f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting) {
-
-    f_status_t status = F_none;
-
-    setting->state.step_small = control_allocation_console_d;
-
-    status = f_console_parameter_process(arguments, &main->parameters, &setting->state, 0);
-
-    setting->state.step_small = control_allocation_small_d;
-
-    if (F_status_is_error(status)) return;
-
-    {
-      f_number_unsigned_t choice = 0;
-      f_uint16s_t choices = f_uint16s_t_initialize;
-
-      // Identify and prioritize "color context" parameters.
-      {
-        uint16_t choices_array[3] = { control_parameter_no_color_e, control_parameter_light_e, control_parameter_dark_e };
-        choices.array = choices_array;
-        choices.used = 3;
-
-        static const uint8_t modes[3] = { f_color_mode_not_e, f_color_mode_light_e, f_color_mode_dark_e };
-
-        status = fll_program_parameter_process_context(choices, modes, F_true, &main->program);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_context", fll_error_file_flag_fallback_e);
-
-          if (main->error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->error);
-          }
-
-          return;
-        }
-      }
-
-      // Identify and prioritize "verbosity" parameters.
-      {
-        uint16_t choices_array[5] = { control_parameter_verbosity_quiet_e, control_parameter_verbosity_error_e, control_parameter_verbosity_verbose_e, control_parameter_verbosity_debug_e, control_parameter_verbosity_normal_e };
-        choices.array = choices_array;
-        choices.used = 5;
-
-        const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e };
-
-        status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_verbosity", fll_error_file_flag_fallback_e);
-
-          if (main->error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->error);
-          }
-
-          return;
-        }
-      }
-    }
-
-    if (main->parameters.array[control_parameter_help_e].result & f_console_result_found_e) {
-      control_print_help(main);
-
-      return F_none;
-    }
-
-    if (main->parameters.array[control_parameter_version_e].result & f_console_result_found_e) {
-      fll_program_print_version(&main->message, control_program_version_s);
-
-      return F_none;
-    }
-
-    if (main->parameters.array[control_parameter_copyright_e].result & f_console_result_found_e) {
-      fll_program_print_copyright(&main->message);
-
-      return F_none;
-    }
-
-    status = F_none;
-
-    {
-      uint8_t ids[] = {
-        control_parameter_name_e,
-        control_parameter_settings_e,
-        control_parameter_socket_e
-      };
-
-      f_string_static_t names[] = {
-        control_long_name_s,
-        control_long_settings_s,
-        control_long_socket_s
-      };
-
-      f_number_unsigned_t index = f_number_unsigned_t_initialize;
-
-      for (uint8_t i = 0; i < 3; ++i) {
-
-        if (main->parameters.array[ids[i]].result & f_console_result_found_e) {
-          control_print_error_parameter_value_not(main, names[i]);
-
-          status = F_status_set_error(F_parameter);
-        }
-        else if (main->parameters.array[ids[i]].result & f_console_result_value_e) {
-          index = main->parameters.array[ids[i]].values.array[main->parameters.array[ids[i]].values.used - 1];
-
-          if (!main->parameters.arguments.array[index].used) {
-            control_print_error_parameter_value_empty(main, names[i]);
-
-            status = F_status_set_error(F_parameter);
-          }
-        }
-      } // for
-    }
-
-    if (F_status_is_error_not(status)) {
-      if (main->pipe & fll_program_data_pipe_input_e) {
-        control_print_error_pipe_supported_not(main);
-
-        status = F_status_set_error(F_support_not);
-      }
-      else if (main->parameters.remaining.used) {
-        control_data_t data = control_data_t_initialize;
-        data.argv = main->parameters.arguments.array;
-
-        data.action = control_action_type_identify(data.argv[main->parameters.remaining.array[0]]);
-
-        if (data.action) {
-          status = control_action_verify(main, &data);
-        }
-        else {
-          control_print_error_parameter_action_not(main, data.argv[main->parameters.remaining.array[0]]);
-
-          status = F_status_set_error(F_parameter);
-        }
-
-        if (F_status_is_error_not(status)) {
-          struct sockaddr_un socket_address;
-
-          memset(&socket_address, 0, sizeof(struct sockaddr_un));
-
-          data.socket.address = (struct sockaddr *) &socket_address;
-          data.socket.domain = f_socket_protocol_family_local_e;
-          data.socket.type = f_socket_type_stream_d;
-          data.socket.length = sizeof(struct sockaddr_un);
-
-          status = control_settings_load(main, &data);
-
-          if (F_status_is_error_not(status)) {
-            status = control_packet_build(main, &data);
-
-            if (F_status_is_error(status)) {
-              if (F_status_set_fine(status) == F_too_large) {
-                control_print_error_request_packet_too_large(main);
-              }
-              else {
-                fll_error_print(main->error, F_status_set_fine(status), "control_packet_build", fll_error_file_flag_fallback_e);
-              }
-            }
-          }
-
-          if (F_status_is_error_not(status)) {
-            status = control_packet_send(main, &data);
-
-            if (F_status_is_error(status)) {
-              fll_error_print(main->error, F_status_set_fine(status), "control_packet_send", fll_error_file_flag_fallback_e);
-            }
-          }
-
-          if (F_status_is_error_not(status)) {
-            control_payload_header_t header = control_payload_header_t_initialize;
-
-            status = control_packet_receive(main, &data, &header);
-
-            if (F_status_is_error(status)) {
-              if (F_status_set_fine(status) == F_too_large) {
-                control_print_error_response_packet_valid_not(main);
-              }
-              else {
-                fll_error_print(main->error, F_status_set_fine(status), "control_packet_receive", fll_error_file_flag_fallback_e);
-              }
-            }
-            else {
-              status = control_packet_process(main, &data, &header);
-
-              // Print the error message only if the error message is not already printed.
-              if (F_status_is_error(status)) {
-                if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(status) != header.status || (header.status != F_failure && header.status != F_busy))) {
-                  fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", fll_error_file_flag_fallback_e);
-                }
-              }
-            }
-          }
-
-          if (data.socket.id != -1) {
-            f_socket_disconnect(&data.socket, f_socket_close_fast_e);
-          }
-        }
-
-        control_data_delete(&data);
-      }
-      else {
-        control_print_error_parameter_actions_none(main);
-
-        status = F_status_set_error(F_data_not);
-      }
-    }
-
-    // Ensure a newline is always put at the end of the program execution, unless in quiet mode.
-    if (main->output.verbosity != f_console_verbosity_quiet_e) {
-      if (F_status_is_error(status)) {
-        f_file_stream_flush(main->output.to);
-        f_file_stream_flush(main->error.to);
-
-        fll_print_dynamic_raw(f_string_eol_s, main->output.to);
-      }
-    }
-
-    return status;
-  }
-#endif // _di_control_main_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/control/c/main.c b/level_3/control/c/main.c
deleted file mode 100644 (file)
index 5f2c556..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "control.h"
-
-int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
-
-  control_main_t data = control_main_t_initialize;
-
-  data.program.debug.flag |= control_print_flag_debug_e | control_print_flag_out_e;
-  data.program.error.flag |= control_print_flag_error_e | control_print_flag_out_e;
-  data.program.output.flag |= control_print_flag_out_e;
-  data.program.message.flag |= control_print_flag_message_e | control_print_flag_out_e;
-  data.program.warning.flag |= control_print_flag_warning_e | control_print_flag_out_e;
-  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;
-
-  f_console_parameter_t parameters[] = control_console_parameter_t_initialize;
-  data.program.parameters.array = parameters;
-  data.program.parameters.used = control_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);
-
-  {
-    const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
-
-    control_setting_load(arguments, &data);
-  }
-
-  control_main(&data);
-
-  control_setting_unload(&data);
-
-  fll_program_data_delete(&data.program);
-
-  fll_program_standard_set_down(&data.program);
-
-  return F_status_is_error(data.setting.state.status) ? 1 : 0;
-}
diff --git a/level_3/control/c/main/action.c b/level_3/control/c/main/action.c
new file mode 100644 (file)
index 0000000..8328380
--- /dev/null
@@ -0,0 +1,233 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_action_type_identify_
+  const uint8_t control_action_type_identify(const f_string_static_t action) {
+
+    if (f_compare_dynamic(action, control_freeze_s) == F_equal_to) return control_action_type_freeze_e;
+    if (f_compare_dynamic(action, control_kexec_s) == F_equal_to) return control_action_type_kexec_e;
+    if (f_compare_dynamic(action, control_kill_s) == F_equal_to) return control_action_type_kill_e;
+    if (f_compare_dynamic(action, control_pause_s) == F_equal_to) return control_action_type_pause_e;
+    if (f_compare_dynamic(action, control_reboot_s) == F_equal_to) return control_action_type_reboot_e;
+    if (f_compare_dynamic(action, control_reload_s) == F_equal_to) return control_action_type_reload_e;
+    if (f_compare_dynamic(action, control_rerun_s) == F_equal_to) return control_action_type_rerun_e;
+    if (f_compare_dynamic(action, control_restart_s) == F_equal_to) return control_action_type_restart_e;
+    if (f_compare_dynamic(action, control_resume_s) == F_equal_to) return control_action_type_resume_e;
+    if (f_compare_dynamic(action, control_shutdown_s) == F_equal_to) return control_action_type_shutdown_e;
+    if (f_compare_dynamic(action, control_start_s) == F_equal_to) return control_action_type_start_e;
+    if (f_compare_dynamic(action, control_stop_s) == F_equal_to) return control_action_type_stop_e;
+    if (f_compare_dynamic(action, control_thaw_s) == F_equal_to) return control_action_type_thaw_e;
+
+    return 0;
+  }
+#endif // _di_control_action_type_identify_
+
+#ifndef _di_control_action_type_name_
+  const f_string_static_t control_action_type_name(const uint8_t type) {
+
+    switch (type) {
+      case control_action_type_freeze_e:
+        return control_freeze_s;
+
+      case control_action_type_kexec_e:
+        return control_kexec_s;
+
+      case control_action_type_kill_e:
+        return control_kill_s;
+
+      case control_action_type_pause_e:
+        return control_pause_s;
+
+      case control_action_type_reboot_e:
+        return control_reboot_s;
+
+      case control_action_type_reload_e:
+        return control_reload_s;
+
+      case control_action_type_rerun_e:
+        return control_rerun_s;
+
+      case control_action_type_restart_e:
+        return control_restart_s;
+
+      case control_action_type_resume_e:
+        return control_resume_s;
+
+      case control_action_type_shutdown_e:
+        return control_shutdown_s;
+
+      case control_action_type_start_e:
+        return control_start_s;
+
+      case control_action_type_stop_e:
+        return control_stop_s;
+
+      case control_action_type_thaw_e:
+        return control_thaw_s;
+    }
+
+    return f_string_empty_s;
+  }
+#endif // _di_control_action_type_name_
+
+#ifndef _di_control_action_verify_
+  void control_action_verify(control_main_t * const main) {
+
+    if (!main) return;
+
+    switch (main->setting.action) {
+      case control_action_type_freeze_e:
+      case control_action_type_kill_e:
+      case control_action_type_pause_e:
+      case control_action_type_reload_e:
+      case control_action_type_rerun_e:
+      case control_action_type_restart_e:
+      case control_action_type_resume_e:
+      case control_action_type_start_e:
+      case control_action_type_stop_e:
+      case control_action_type_thaw_e:
+        if (main->setting.actions.used < 3) {
+          control_print_error_parameter_action_rule_not(&main->program.error, main->setting.actions.array[0]);
+
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          return;
+        }
+
+        if (main->setting.actions.used > 3) {
+          if (f_compare_dynamic(control_at_s, main->setting.actions.array[3]) == F_equal_to) {
+            if (main->setting.actions.used < 5) {
+              control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_at_s);
+
+              main->setting.state.status = F_status_set_error(F_parameter);
+
+              return;
+            }
+
+            if (main->setting.actions.used > 5) {
+              control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_at_s);
+
+              main->setting.state.status = F_status_set_error(F_parameter);
+
+              return;
+            }
+          }
+          else if (f_compare_dynamic(control_in_s, main->setting.actions.array[3]) == F_equal_to) {
+            if (main->setting.actions.used < 6) {
+              control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_in_s);
+
+              main->setting.state.status = F_status_set_error(F_parameter);
+
+              return;
+            }
+          }
+          else if (f_compare_dynamic(control_now_s, main->setting.actions.array[3]) == F_equal_to) {
+            if (main->setting.actions.used > 4) {
+              control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_now_s);
+
+              main->setting.state.status = F_status_set_error(F_parameter);
+
+              return;
+            }
+          }
+          else {
+            control_print_error_parameter_action_rule_with_unknown(&main->program.error, main->setting.actions.array[0], main->setting.actions.array[2]);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+
+        if (!main->setting.actions.array[1].used) {
+          if (main->setting.actions.used == 3) {
+            control_print_error_parameter_action_rule_empty(&main->program.error, main->setting.actions.array[0]);
+          }
+          else {
+            control_print_error_parameter_action_rule_directory_empty(&main->program.error, main->setting.actions.array[0]);
+          }
+
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          return;
+        }
+
+        if (main->setting.actions.used == 3) {
+          if (!main->setting.actions.array[2].used) {
+            control_print_error_parameter_action_rule_basename_empty(&main->program.error, main->setting.actions.array[0]);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+
+        main->setting.state.status = F_none;
+
+        return;
+
+      case control_action_type_kexec_e:
+      case control_action_type_reboot_e:
+      case control_action_type_shutdown_e:
+        if (main->setting.actions.used < 2) {
+          control_print_error_parameter_action_rule_too_few(&main->program.error, main->setting.actions.array[0]);
+
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          return;
+        }
+
+        if (f_compare_dynamic(control_at_s, main->setting.actions.array[1]) == F_equal_to) {
+          if (main->setting.actions.used < 3) {
+            control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_at_s);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+
+          if (main->setting.actions.used > 3) {
+            control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_at_s);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+        else if (f_compare_dynamic(control_in_s, main->setting.actions.array[1]) == F_equal_to) {
+          if (main->setting.actions.used < 4) {
+            control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_in_s);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+        else if (f_compare_dynamic(control_now_s, main->setting.actions.array[1]) == F_equal_to) {
+          if (main->setting.actions.used > 2) {
+            control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_now_s);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+          }
+        }
+        else {
+          control_print_error_parameter_action_rule_with_unknown(&main->program.error, main->setting.actions.array[0], main->setting.actions.array[1]);
+
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            return;
+        }
+    }
+
+    main->setting.state.status = F_none;
+  }
+#endif // _di_control_action_verify_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/action.h b/level_3/control/c/main/action.h
new file mode 100644 (file)
index 0000000..71cf354
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the action functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_action_h
+#define _control_action_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Identify the action code the given name represents.
+ *
+ * @param action
+ *   The string representing an action.
+ *
+ * @return
+ *   The action type code on success.
+ *   0 if name is unknown.
+ */
+#ifndef _di_control_action_type_identify_
+  extern const uint8_t control_action_type_identify(const f_string_static_t action);
+#endif // _di_control_action_type_identify_
+
+/**
+ * Get a string representing the action type.
+ *
+ * @param type
+ *   The action type id.
+ *
+ * @return
+ *   The string with used > 0 on success.
+ *   The string with used == 0 if no match was found.
+ */
+#ifndef _di_control_action_type_name_
+  extern const f_string_static_t control_action_type_name(const uint8_t type);
+#endif // _di_control_action_type_name_
+
+/**
+ * Verify that the additional parameters are reasonably correct for the identified action.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *
+ *     F_parameter (with error bit) on parameter validation/verification failure.
+ */
+#ifndef _di_control_action_verify_
+  extern void control_action_verify(control_main_t * const main);
+#endif // _di_control_action_verify_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_action_h
diff --git a/level_3/control/c/main/common.c b/level_3/control/c/main/common.c
new file mode 100644 (file)
index 0000000..10f1e9e
--- /dev/null
@@ -0,0 +1,492 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_setting_load_
+  void control_setting_load(const f_console_arguments_t arguments, control_main_t * const main) {
+
+    if (!main) return;
+
+    main->setting.state.step_small = control_allocation_console_d;
+
+    f_console_parameter_process(arguments, &main->program.parameters, &main->setting.state, 0);
+
+    main->setting.state.step_small = control_allocation_small_d;
+
+    // Identify and process first/last parameters.
+    if (main->program.parameters.array[f_console_standard_parameter_line_first_no_e].result & f_console_result_found_e) {
+      main->setting.flag -= main->setting.flag & control_main_flag_print_first_e;
+    }
+    else {
+      main->setting.flag |= control_main_flag_print_first_e;
+    }
+
+    if (main->program.parameters.array[f_console_standard_parameter_line_last_no_e].result & f_console_result_found_e) {
+      main->setting.flag -= main->setting.flag & control_main_flag_print_last_e;
+    }
+    else {
+      main->setting.flag |= control_main_flag_print_last_e;
+    }
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error(&main->program.error, macro_control_f(f_console_parameter_process));
+
+      return;
+    }
+
+    main->setting.state.status = fll_program_parameter_process_context_standard(F_true, &main->program);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error(&main->program.error, macro_control_f(fll_program_parameter_process_context_standard));
+
+      return;
+    }
+
+    main->setting.state.status = fll_program_parameter_process_verbosity_standard(F_true, &main->program);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error(&main->program.error, macro_control_f(fll_program_parameter_process_verbosity_standard));
+
+      return;
+    }
+
+    if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) {
+      main->setting.flag |= control_main_flag_help_e;
+
+      return;
+    }
+
+    if (main->program.parameters.array[f_console_standard_parameter_version_e].result & f_console_result_found_e) {
+      main->setting.flag |= control_main_flag_version_e;
+
+      return;
+    }
+
+    if (main->program.parameters.array[f_console_standard_parameter_copyright_e].result & f_console_result_found_e) {
+      main->setting.flag |= control_main_flag_copyright_e;
+
+      return;
+    }
+
+    if (main->program.parameters.array[control_parameter_return_e].result & f_console_result_found_e) {
+      main->setting.flag |= control_main_flag_return_e;
+
+      return;
+    }
+
+    f_number_unsigned_t index = 0;
+
+    if (main->program.pipe & fll_program_data_pipe_input_e) {
+      main->setting.flag |= control_main_flag_pipe_e;
+    }
+    else {
+      main->setting.flag -= main->setting.flag & control_main_flag_pipe_e;
+    }
+
+    // The settings path is statically allocated.
+    if (main->program.parameters.array[control_parameter_settings_e].result & f_console_result_value_e) {
+      index = main->program.parameters.array[control_parameter_settings_e].values.array[main->program.parameters.array[control_parameter_settings_e].values.used - 1];
+
+      main->setting.path_settings.string = main->program.parameters.arguments.array[index].string;
+      main->setting.path_settings.used = main->program.parameters.arguments.array[index].used;
+      main->setting.path_settings.size = 0;
+    }
+    else {
+      main->setting.path_settings.string = control_path_settings_s.string;
+      main->setting.path_settings.used = control_path_settings_s.used;
+      main->setting.path_settings.size = 0;
+    }
+
+    {
+      f_file_t file = f_file_t_initialize;
+
+      main->setting.state.status = f_file_stream_open(main->setting.path_settings, f_file_open_mode_read_s, &file);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error_file(&main->program.error, macro_control_f(f_file_stream_open), main->setting.path_settings, f_file_operation_open_s, fll_error_file_type_file_e);
+
+        return;
+      }
+
+      main->setting.state.status = f_file_stream_read(file, &main->cache.large);
+
+      f_file_stream_flush(file);
+      f_file_stream_close(&file);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error_file(&main->program.error, macro_control_f(f_file_stream_read), main->setting.path_settings, f_file_operation_read_s, fll_error_file_type_file_e);
+
+        return;
+      }
+    }
+
+    if (main->cache.large.used) {
+      main->setting.range.start = 0;
+      main->setting.range.stop = main->cache.large.used - 1;
+    }
+    else {
+      main->setting.range.start = 1;
+      main->setting.range.stop = 0;
+    }
+
+    fll_fss_extended_read(main->cache.large, &main->setting.range, &main->cache.objects, &main->cache.contents, 0, 0, &main->cache.delimits, 0, &main->setting.state);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error_file(&main->program.error, macro_control_f(fll_fss_extended_read), main->setting.path_settings, f_file_operation_process_s, fll_error_file_type_file_e);
+
+      return;
+    }
+
+    f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &main->setting.state);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error_file(&main->program.error, macro_control_f(f_fss_apply_delimit), main->setting.path_settings, f_file_operation_process_s, fll_error_file_type_file_e);
+
+      return;
+    }
+
+    uint8_t i = 0;
+    uint8_t parameter_hass[] = { 0, 0, 0, 0 };
+    f_number_unsigned_t parameter_ats[] = { 0, 0, 0, 0 };
+
+    {
+      const f_string_static_t parameter_names[] = {
+        control_name_socket_s,
+        control_path_socket_s,
+        control_path_socket_prefix_s,
+        control_path_socket_suffix_s,
+      };
+
+      f_number_unsigned_t j = 0;
+      uint8_t k = 0;
+
+      for (; j < main->cache.objects.used; ++j) {
+
+        for (k = 0; k < 4; ++k) {
+
+          if (!parameter_names[k].used) continue;
+
+          main->setting.range.start = 0;
+          main->setting.range.stop = parameter_names[k].used - 1;
+
+          if (f_compare_dynamic_partial(parameter_names[k], main->cache.large, main->setting.range, main->cache.objects.array[j]) == F_equal_to) {
+            parameter_hass[k] = F_true;
+            parameter_ats[k] = j;
+
+            break;
+          }
+        } // for
+      } // for
+    }
+
+    // The settings path is statically allocated, except when read from the settings file.
+    if (main->program.parameters.array[control_parameter_socket_e].result & f_console_result_value_e) {
+      index = main->program.parameters.array[control_parameter_settings_e].values.array[main->program.parameters.array[control_parameter_settings_e].values.used - 1];
+
+      main->setting.path_socket.string = main->program.parameters.arguments.array[index].string;
+      main->setting.path_socket.used = main->program.parameters.arguments.array[index].used;
+      main->setting.path_socket.size = 0;
+    }
+    else if (parameter_hass[1]) {
+      main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.large, main->cache.objects.array[parameter_ats[1]], &main->setting.path_socket);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error_file(&main->program.error, macro_control_f(f_string_dynamic_partial_append_nulless), main->setting.path_socket, f_file_operation_process_s, fll_error_file_type_file_e);
+
+        return;
+      }
+    }
+    else {
+      main->setting.path_socket.string = controller_path_socket_s.string;
+      main->setting.path_socket.used = controller_path_socket_s.used;
+      main->setting.path_socket.size = 0;
+    }
+
+    main->setting.state.status = f_file_exists(main->setting.path_socket, F_true);
+
+    if (F_status_is_error(main->setting.state.status) || main->setting.state.status == F_false) {
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      if (F_status_is_error(main->setting.state.status)) {
+        control_print_error_file(&main->program.error, macro_control_f(f_file_exists), main->setting.path_socket, f_file_operation_find_s, fll_error_file_type_directory_e);
+
+        if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.error.to);
+        }
+      }
+
+      main->setting.state.status = F_status_set_error(F_socket_not);
+
+      control_print_error_socket_file_missing(&main->program.error, main->setting.path_socket);
+
+      return;
+    }
+
+    // Construct the file name when the socket path is a directory.
+    if (f_file_is(main->setting.path_socket, F_file_type_directory_d, F_true) == F_true) {
+      main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &main->setting.path_socket);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error(&main->program.error, macro_control_f(f_string_dynamic_append_assure));
+
+        return;
+      }
+
+      {
+        const uint8_t append_ids[] = {
+          0,
+          control_parameter_name_e,
+          0,
+        };
+
+        const uint8_t append_hass[] = {
+          parameter_hass[2],
+          parameter_hass[0],
+          parameter_hass[3],
+        };
+
+        const f_string_static_t append_defaults[] = {
+          controller_path_socket_prefix_s,
+          controller_name_socket_s,
+          controller_path_socket_suffix_s,
+        };
+
+        for (i = 0; i < 3; ++i) {
+
+          if (append_ids[i] && main->program.parameters.array[append_ids[i]].result & f_console_result_value_e) {
+            index = main->program.parameters.array[append_ids[i]].values.array[main->program.parameters.array[append_ids[i]].values.used - 1];
+
+            main->setting.state.status = f_string_dynamic_append(main->program.parameters.arguments.array[index], &main->setting.path_socket);
+          }
+          else if (append_hass[i]) {
+            main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.large, main->cache.objects.array[append_hass[i]], &main->setting.path_socket);
+          }
+          else {
+            main->setting.state.status = f_string_dynamic_append_nulless(append_defaults[i], &main->setting.path_socket);
+          }
+
+          if (F_status_is_error(main->setting.state.status)) {
+            if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+              fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+            }
+
+            control_print_error(
+              &main->program.error,
+              ((append_ids[i] && main->program.parameters.array[append_ids[i]].result & f_console_result_value_e) || !append_hass[i])
+                ? macro_control_f(f_string_dynamic_append)
+                : macro_control_f(f_string_dynamic_partial_append_nulless)
+            );
+
+            return;
+          }
+        } // for
+
+        main->setting.state.status = f_file_exists(main->setting.path_socket, F_true);
+
+        if (F_status_is_error(main->setting.state.status) || main->setting.state.status == F_false) {
+          if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+            fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+          }
+
+          if (F_status_is_error(main->setting.state.status)) {
+            control_print_error_file(&main->program.error, macro_control_f(f_file_exists), main->setting.path_socket, f_file_operation_find_s, fll_error_file_type_directory_e);
+
+            if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
+              fll_print_dynamic_raw(f_string_eol_s, main->program.error.to);
+            }
+          }
+
+          main->setting.state.status = F_status_set_error(F_socket_not);
+
+          control_print_error_socket_file_missing(&main->program.error, main->setting.path_socket);
+
+          return;
+        }
+      }
+    }
+
+    if (f_file_is(main->setting.path_socket, F_file_type_socket_d, F_true) == F_false) {
+      main->setting.state.status = F_status_set_error(F_socket_not);
+
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error_socket_file_not(&main->program.error, main->setting.path_socket);
+
+      return;
+    }
+
+    main->setting.state.status = f_socket_create(&main->setting.socket);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      control_print_error(&main->program.error, macro_control_f(f_socket_create));
+
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error_socket_file_failed(&main->program.error, main->setting.path_socket);
+
+      return;
+    }
+
+    main->setting.state.status = f_socket_connect(main->setting.socket);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      control_print_error(&main->program.error, macro_control_f(f_socket_connect));
+
+      if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      control_print_error_socket_file_failed(&main->program.error, main->setting.path_socket);
+
+      return;
+    }
+
+    f_string_ranges_resize(0, &main->cache.objects);
+    f_string_rangess_resize(0, &main->cache.contents);
+    f_number_unsigneds_resize(0, &main->cache.delimits);
+
+    {
+      const uint8_t ids[] = {
+        control_parameter_name_e,
+        control_parameter_settings_e,
+        control_parameter_socket_e
+      };
+
+      const f_string_static_t names[] = {
+        control_long_name_s,
+        control_long_settings_s,
+        control_long_socket_s
+      };
+
+      f_status_t error_printed_not = F_false;
+
+      for (i = 0; i < 3; ++i) {
+
+        if (main->program.parameters.array[ids[i]].result & f_console_result_found_e) {
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          if (error_printed_not) {
+            error_printed_not = F_true;
+
+            if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+              fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+            }
+          }
+
+          control_print_error_parameter_value_not(&main->program.error, names[i]);
+        }
+        else if (main->program.parameters.array[ids[i]].result & f_console_result_value_e) {
+          index = main->program.parameters.array[ids[i]].values.array[main->program.parameters.array[ids[i]].values.used - 1];
+
+          if (!main->program.parameters.arguments.array[index].used) {
+            main->setting.state.status = F_status_set_error(F_parameter);
+
+            if (error_printed_not) {
+              error_printed_not = F_true;
+
+              if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+                fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+              }
+            }
+
+            control_print_error_parameter_value_empty(&main->program.error, names[i]);
+          }
+        }
+      } // for
+    }
+
+    main->cache.large.used = 0;
+
+    if (main->cache.large.size > control_default_buffer_limit_soft_large_d) {
+      main->setting.state.status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &main->cache.large);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error(&main->program.error, macro_control_f(f_string_dynamic_resize));
+
+        return;
+      }
+    }
+
+    if (main->program.parameters.remaining.used) {
+      main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.remaining.used, &main->setting.actions);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+          fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+        }
+
+        control_print_error(&main->program.error, macro_control_f(f_string_dynamics_increase_by));
+
+        return;
+      }
+
+      index = 0;
+
+      for (f_number_unsigned_t number = 0; index < main->program.parameters.remaining.used; ++index) {
+
+        if (control_signal_check(main)) return;
+
+        number = main->program.parameters.remaining.array[index];
+
+        // Statically allocate the inner strings.
+        main->setting.actions.array[main->setting.actions.used].string = main->program.parameters.arguments.array[number].string;
+        main->setting.actions.array[main->setting.actions.used].used = main->program.parameters.arguments.array[number].used;
+        main->setting.actions.array[main->setting.actions.used++].size = 0;
+      } // for
+    }
+
+    main->setting.state.status = F_none;
+  }
+#endif // _di_control_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/common.h b/level_3/control/c/main/common.h
new file mode 100644 (file)
index 0000000..4abdc52
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * 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 _control_common_h
+#define _control_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * 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 main program data and settings.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_control_setting_load_
+  extern void control_setting_load(const f_console_arguments_t arguments, control_main_t * const main);
+#endif // _di_control_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_common_h
diff --git a/level_3/control/c/main/common/define.c b/level_3/control/c/main/common/define.c
new file mode 100644 (file)
index 0000000..39790a2
--- /dev/null
@@ -0,0 +1,9 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/common/define.h b/level_3/control/c/main/common/define.h
new file mode 100644 (file)
index 0000000..eeebe70
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common define types.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_common_define_h
+#define _control_common_define_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The program allocation defines.
+ *
+ * control_allocation_*_d:
+ *   - console: An allocation step used for small buffers specifically for console parameter.
+ *   - large:   An allocation step used for buffers that are anticipated to have large buffers.
+ *   - pipe:    A buffer size used for processing piped data.
+ *   - small:   An allocation step used for buffers that are anticipated to have small buffers.
+ */
+#ifndef _di_control_allocation_d_
+  #define control_allocation_console_d 4
+  #define control_allocation_large_d   256
+  #define control_allocation_pipe_d    16384
+  #define control_allocation_small_d   16
+#endif // _di_control_allocation_d_
+
+/**
+ * General defines used throughout the program.
+ *
+ * control_default_*_d:
+ *   - buffer_limit_soft_large: The preferred maximum size of buffers intended for large data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit).
+ *   - buffer_limit_soft_small: The preferred maximum size of buffers intended for small data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit).
+ */
+#ifndef _di_control_default_d_
+  #define control_default_buffer_limit_soft_large_d 2048
+  #define control_default_buffer_limit_soft_small_d 64
+#endif // _di_control_default_d_
+
+/**
+ * The program signal defines.
+ *
+ * control_signal_*_d:
+ *   - check:          Number of iterations before performing signal check in non-threaded signal handling.
+ *   - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe).
+ *   - check_tiny:     The tiny check.
+ *   - check_short:    The short signal check.
+ */
+#ifndef _di_control_signal_d_
+  #define control_signal_check_d          500000
+  #define control_signal_check_failsafe_d 20000
+  #define control_signal_check_tiny_d     4
+  #define control_signal_check_short_d    16
+#endif // _di_control_signal_d_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_common_define_h
diff --git a/level_3/control/c/main/common/enumeration.c b/level_3/control/c/main/common/enumeration.c
new file mode 100644 (file)
index 0000000..39790a2
--- /dev/null
@@ -0,0 +1,9 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/common/enumeration.h b/level_3/control/c/main/common/enumeration.h
new file mode 100644 (file)
index 0000000..90d0999
--- /dev/null
@@ -0,0 +1,161 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common enumeration types.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_common_enumeration_h
+#define _control_common_enumeration_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Codes representing supported actions.
+ *
+ * freeze:   Perform the freeze controller operation.
+ * kexec:    Perform the kexec controller operation (only for init mode).
+ * kill:     Perform the kill controller operation.
+ * pause:    Perform the pause controller operation.
+ * reboot:   Perform the reboot controller operation (only for init mode).
+ * reload:   Perform the reload controller operation.
+ * rerun:    Perform the rerun controller operation.
+ * restart:  Perform the restart controller operation.
+ * resume:   Perform the resume controller operation.
+ * shutdown: Perform the shutdown controller operation (only for init mode).
+ * start:    Perform the start controller operation.
+ * stop:     Perform the stop controller operation.
+ * thaw:     Perform the thaw controller operation.
+ */
+#ifndef _di_control_action_type_e_
+  enum {
+    control_action_type_freeze_e = 1,
+    control_action_type_kexec_e,
+    control_action_type_kill_e,
+    control_action_type_pause_e,
+    control_action_type_reboot_e,
+    control_action_type_reload_e,
+    control_action_type_rerun_e,
+    control_action_type_restart_e,
+    control_action_type_resume_e,
+    control_action_type_shutdown_e,
+    control_action_type_start_e,
+    control_action_type_stop_e,
+    control_action_type_thaw_e,
+  }; // enum
+#endif // _di_control_action_type_e_
+
+/**
+ * Supported payload types.
+ *
+ * controller: The payload is a controller payload.
+ * error:      The payload is an error payload.
+ * init:       The payload is an init payload (only available when operating in "init" mode).
+ */
+#ifndef _di_control_payload_type_e_
+  enum {
+    control_payload_type_controller_e = 1,
+    control_payload_type_error_e,
+    control_payload_type_init_e,
+  }; // enum
+#endif // _di_control_payload_type_e_
+
+/**
+ * A codes repesent different flags associated with a packet.
+ *
+ * control_packet_flag_*:
+ *   - binary:     Designate that the packet is in binary mode (when not set then packet is in string mode).
+ *   - endian_big: Designate that the packet is in big endian order (when not set then packet is in little endian order).
+ */
+#ifndef _di_control_packet_flag_e_
+  #define control_packet_flag_binary_d     0x80
+  #define control_packet_flag_endian_big_d 0x40
+#endif // _di_control_packet_flag_e_
+
+/**
+ * Flags passed to the main function or program.
+ *
+ * control_main_flag_*_e:
+ *   - none:          No flags set.
+ *   - copyright:     Print copyright.
+ *   - header:        Enable printing of headers.
+ *   - help:          Print help.
+ *   - pipe:          Use the input pipe.
+ *   - print_first:   When set, print new line to message output on program begin after loading settings.
+ *   - print_last:    When set, print new line to message output on program end.
+ *   - return:        The parameter is specified.
+ *   - version:       Print version.
+ */
+#ifndef _di_control_main_flag_e_
+  enum {
+    control_main_flag_none_e        = 0x0,
+    control_main_flag_copyright_e   = 0x1,
+    control_main_flag_help_e        = 0x2,
+    control_main_flag_pipe_e        = 0x4,
+    control_main_flag_print_first_e = 0x8,
+    control_main_flag_print_last_e  = 0x10,
+    control_main_flag_return_e      = 0x20,
+    control_main_flag_version_e     = 0x40,
+  }; // enum
+#endif // _di_control_main_flag_e_
+
+/**
+ * The main program parameters.
+ */
+#ifndef _di_control_parameter_d_
+  enum {
+    control_parameter_name_e = f_console_standard_parameter_last_e,
+    control_parameter_return_e,
+    control_parameter_settings_e,
+    control_parameter_socket_e,
+  }; // enum
+
+  #define control_console_parameter_t_initialize \
+    { \
+      macro_fll_program_console_parameter_standard_initialize, \
+      \
+      macro_f_console_parameter_t_initialize_3(control_short_name_s,     control_long_name_s,     1, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(control_short_return_s,   control_long_return_s,   1, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(control_short_settings_s, control_long_settings_s, 1, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(control_short_socket_s,   control_long_socket_s,   1, f_console_flag_normal_e), \
+    }
+
+  #define control_parameter_total_d 17
+#endif // _di_control_parameter_d_
+
+/**
+ * Flags for fine-tuned print control.
+ *
+ * control_print_flag_*_e:
+ *   - none:    No flags set.
+ *   - debug:   Stream is for debug printing.
+ *   - error:   Stream is for error printing.
+ *   - in:      Stream is a source file.
+ *   - message: Stream is for message printing.
+ *   - out:     Stream is a destination file.
+ *   - warning: Stream is for warning printing.
+ */
+#ifndef _di_control_print_flag_e_
+  enum {
+    control_print_flag_none_e    = 0x0,
+    control_print_flag_debug_e   = 0x1,
+    control_print_flag_error_e   = 0x2,
+    control_print_flag_file_e    = 0x4,
+    control_print_flag_in_e      = 0x8,
+    control_print_flag_out_e     = 0x10,
+    control_print_flag_message_e = 0x20,
+    control_print_flag_warning_e = 0x40,
+  }; // enum
+#endif // _di_control_print_flag_e_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_common_enumeration_h
diff --git a/level_3/control/c/main/common/print.c b/level_3/control/c/main/common/print.c
new file mode 100644 (file)
index 0000000..99c5491
--- /dev/null
@@ -0,0 +1,34 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_f_a_
+  const f_string_t control_f_a[] = {
+    "control_packet_build",
+    "control_packet_process",
+    "control_packet_receive",
+    "control_packet_send",
+    "f_console_parameter_process",
+    "f_file_exists",
+    "f_file_stream_open",
+    "f_file_stream_read",
+    "f_fss_apply_delimit",
+    "f_socket_connect",
+    "f_socket_create",
+    "f_string_dynamic_append",
+    "f_string_dynamic_append_assure",
+    "f_string_dynamic_partial_append_nulless",
+    "f_string_dynamic_resize",
+    "f_string_dynamics_increase_by",
+    "f_thread_create",
+    "fll_fss_extended_read",
+    "fll_program_parameter_process_context_standard",
+    "fll_program_parameter_process_verbosity_standard",
+  };
+#endif // _di_control_f_a_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/common/print.h b/level_3/control/c/main/common/print.h
new file mode 100644 (file)
index 0000000..5826af1
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common print functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_common_print_h
+#define _control_common_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A special array of strings intended for representing funciton names.
+ *
+ * These are primarily used for printing errors with the function names.
+ *
+ * The macro macro_control_f() is used to reference the array index by the enum name.
+ *
+ * macro_control_f():
+ *   - name: The name of the function.
+ */
+#ifndef _di_control_f_a_
+  extern const f_string_t control_f_a[];
+
+  #define macro_control_f(name) control_f_a[control_f_##name##_e]
+#endif // _di_control_f_a_
+
+/**
+ * An enum representing specific indexes within the above array.
+ *
+ * This is a convenience enum used to make code slightly more readable.
+ */
+#ifndef _di_control_f_e_
+  enum {
+    control_f_control_packet_build_e,
+    control_f_control_packet_process_e,
+    control_f_control_packet_receive_e,
+    control_f_control_packet_send_e,
+    control_f_f_console_parameter_process_e,
+    control_f_f_file_exists_e,
+    control_f_f_file_stream_open_e,
+    control_f_f_file_stream_read_e,
+    control_f_f_fss_apply_delimit_e,
+    control_f_f_socket_connect_e,
+    control_f_f_socket_create_e,
+    control_f_f_string_dynamic_append_e,
+    control_f_f_string_dynamic_append_assure_e,
+    control_f_f_string_dynamic_partial_append_nulless_e,
+    control_f_f_string_dynamic_resize_e,
+    control_f_f_string_dynamics_increase_by_e,
+    control_f_f_thread_create_e,
+    control_f_fll_fss_extended_read_e,
+    control_f_fll_program_parameter_process_context_standard_e,
+    control_f_fll_program_parameter_process_verbosity_standard_e,
+  }; // enum
+#endif // _di_control_f_e_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_common_print_h
similarity index 70%
rename from level_3/control/c/private-common.c
rename to level_3/control/c/main/common/string.c
index 5c5e28010af6e7c769f5796b3c4c33eda2955cee..a9ab36bceaf25a7111597eab5a9ca73054444dd3 100644 (file)
@@ -1,17 +1,29 @@
-#include "control.h"
-#include "private-common.h"
-#include "private-print.h"
+#include "../control.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef _di_controller_strings_
-  const f_string_static_t controller_name_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_name_socket_s, 0, CONTROLLER_name_socket_s_length);
-  const f_string_static_t controller_path_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_s, 0, CONTROLLER_path_socket_s_length);
-  const f_string_static_t controller_path_socket_prefix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_prefix_s, 0, CONTROLLER_path_socket_prefix_s_length);
-  const f_string_static_t controller_path_socket_suffix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_suffix_s, 0, CONTROLLER_path_socket_suffix_s_length);
-#endif // _di_controller_strings_
+#ifndef _di_control_program_version_s_
+  const f_string_static_t control_program_version_s = macro_f_string_static_t_initialize_1(CONTROL_program_version_s, 0, CONTROL_program_version_s_length);
+#endif // _di_control_program_version_s_
+
+#ifndef _di_control_program_name_s_
+  const f_string_static_t control_program_name_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_s, 0, CONTROL_program_name_s_length);
+  const f_string_static_t control_program_name_long_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_long_s, 0, CONTROL_program_name_long_s_length);
+#endif // _di_control_program_name_s_
+
+#ifndef _di_control_parameter_s_
+  const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize_1(CONTROL_short_name_s, 0, CONTROL_short_name_s_length);
+  const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize_1(CONTROL_short_return_s, 0, CONTROL_short_return_s_length);
+  const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize_1(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length);
+  const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize_1(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length);
+
+  const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize_1(CONTROL_long_name_s, 0, CONTROL_long_name_s_length);
+  const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize_1(CONTROL_long_return_s, 0, CONTROL_long_return_s_length);
+  const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize_1(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length);
+  const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize_1(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length);
+#endif // _di_control_parameter_s_
 
 #ifndef _di_control_strings_s_
   const f_string_static_t control_path_settings_s = macro_f_string_static_t_initialize_1(CONTROL_path_settings_s, 0, CONTROL_path_settings_s_length);
@@ -47,22 +59,12 @@ extern "C" {
   const f_string_static_t control_thaw_s = macro_f_string_static_t_initialize_1(CONTROL_thaw_s, 0, CONTROL_thaw_s_length);
 #endif // _di_control_strings_s_
 
-#ifndef _di_control_data_delete_
-  void control_data_delete(control_data_t * const data) {
-
-    f_string_dynamic_resize(0, &data->cache.large);
-    f_string_dynamic_resize(0, &data->cache.small);
-    f_string_dynamic_resize(0, &data->cache.packet);
-
-    f_string_ranges_resize(0, &data->cache.packet_objects);
-    f_string_rangess_resize(0, &data->cache.packet_contents);
-
-    f_string_ranges_resize(0, &data->cache.header_objects);
-    f_string_rangess_resize(0, &data->cache.header_contents);
-
-    f_number_unsigneds_resize(0, &data->cache.delimits);
-  }
-#endif // _di_control_data_delete_
+#ifndef _di_controller_strings_s_
+  const f_string_static_t controller_name_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_name_socket_s, 0, CONTROLLER_name_socket_s_length);
+  const f_string_static_t controller_path_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_s, 0, CONTROLLER_path_socket_s_length);
+  const f_string_static_t controller_path_socket_prefix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_prefix_s, 0, CONTROLLER_path_socket_prefix_s_length);
+  const f_string_static_t controller_path_socket_suffix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_suffix_s, 0, CONTROLLER_path_socket_suffix_s_length);
+#endif // _di_controller_strings_s_
 
 #ifdef __cplusplus
 } // extern "C"
similarity index 63%
rename from level_3/control/c/private-common.h
rename to level_3/control/c/main/common/string.h
index 89505dd2717935db83d711aef44cfa4ef49a4d49..d5c611678f37215d5d89f19eaf3b5404376b038d 100644 (file)
  * Project: Control
  * API Version: 0.7
  * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common string structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
  */
-#ifndef _PRIVATE_common_h
-#define _PRIVATE_common_h
+#ifndef _control_common_string_h
+#define _control_common_string_h
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * General defines used throughout the program.
- *
- * control_default_*:
- *   - buffer_limit_soft_large: The preferred maximum size of buffers intended for large data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit).
- *   - buffer_limit_soft_small: The preferred maximum size of buffers intended for small data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit).
- *
- * control_signal_*:
- *   - check: The interval in which callbacks checking signal should actually perform the signal check (significantly improves perfomance).
- *
- * control_allocation_*:
- *   - large: Default allocation buffer size for buffers expected to work with large data sets.
- *   - small: Default allocation buffer size for buffers expected to work with small data sets.
- */
-#ifndef _di_control_defines_s_
-  #define control_default_buffer_limit_soft_large_d 2048
-  #define control_default_buffer_limit_soft_small_d 64
-
-  #define control_signal_check_d 20000
-
-  #define control_allocation_large_d 256
-  #define control_allocation_small_d 16
-#endif // _di_control_defines_s_
-
-/**
- * A codes repesent different flags associated with a packet.
- *
- * control_packet_flag_*:
- *   - binary:     Designate that the packet is in binary mode (when not set then packet is in string mode).
- *   - endian_big: Designate that the packet is in big endian order (when not set then packet is in little endian order).
- */
-#ifndef _di_control_packet_flag_
-  #define control_packet_flag_binary_d     0x80
-  #define control_packet_flag_endian_big_d 0x40
-#endif // _di_control_packet_flag_
-
-/**
- * Controller defines that the control program utilizes.
- *
- * These are intended to exactly match the relevant controller string defines.
+ * The program version.
  */
-#ifndef _di_controller_strings_
+#ifndef _di_control_program_version_s_
+  #define CONTROL_program_version_major_s F_string_ascii_0_s
+  #define CONTROL_program_version_minor_s F_string_ascii_7_s
+  #define CONTROL_program_version_micro_s F_string_ascii_0_s
 
-  // The name_socket is a system-specific path and should match the path compiled into the controller program.
-  #if defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_)
-    #define CONTROLLER_name_socket_s _override_controller_name_socket_
+  #define CONTROL_program_version_major_s_length F_string_ascii_0_s_length
+  #define CONTROL_program_version_minor_s_length F_string_ascii_7_s_length
+  #define CONTROL_program_version_micro_s_length F_string_ascii_0_s_length
 
-    #define CONTROLLER_name_socket_s_length _override_controller_name_socket_length_
-  #else
-    #define CONTROLLER_name_socket_s "default"
+  #if !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length))
+    #define CONTROL_program_version_nano_prefix_s
+    #define CONTROL_program_version_nano_prefix_s_length 0
+  #endif // !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length))
 
-    #define CONTROLLER_name_socket_s_length 7
-  #endif // defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_)
+  #if !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length))
+    #define CONTROL_program_version_nano_s
+    #define CONTROL_program_version_nano_s_length 0
+  #endif // !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length))
 
-  // The path_socket is a system-specific path and should match the path compiled into the controller program.
-  #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
-    #define CONTROLLER_path_socket_s _override_controller_path_socket_
+  #define CONTROL_program_version_s CONTROL_program_version_major_s F_string_ascii_period_s CONTROL_program_version_minor_s F_string_ascii_period_s CONTROL_program_version_micro_s CONTROL_program_version_nano_prefix_s CONTROL_program_version_nano_s
 
-    #define CONTROLLER_path_socket_s_length _override_controller_path_socket_length_
-  #elif defined(_controller_as_init_)
-    #define CONTROLLER_path_socket_s "/var/run/init"
+  #define CONTROL_program_version_s_length CONTROL_program_version_major_s_length + F_string_ascii_period_s_length + CONTROL_program_version_minor_s_length + F_string_ascii_period_s_length + CONTROL_program_version_micro_s_length + CONTROL_program_version_nano_prefix_s_length + CONTROL_program_version_nano_s_length
 
-    #define CONTROLLER_path_socket_s_length 13
-  #else
-    #define CONTROLLER_path_socket_s "/var/run/controller"
+  extern const f_string_static_t control_program_version_s;
+#endif // _di_control_program_version_s_
 
-    #define CONTROLLER_path_socket_s_length 19
-  #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
-
-  // The name_socket_prefix is a system-specific path and should match the path compiled into the controller program.
-  #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_)
-    #define CONTROLLER_path_socket_prefix_s _override_controller_path_socket_prefix_
-
-    #define CONTROLLER_path_socket_prefix_s_length _override_controller_path_socket_prefix_length_
-  #elif defined(_controller_as_init_)
-    #define CONTROLLER_path_socket_prefix_s "init-"
-
-    #define CONTROLLER_path_socket_prefix_s_length 5
-  #else
-    #define CONTROLLER_path_socket_prefix_s ""
-
-    #define CONTROLLER_path_socket_prefix_s_length 0
-  #endif // defined(_override_controller_name_socket_prefix_) && defined(_override_controller_name_socket_prefix_length_)
-
-  // The name_socket_suffix is a system-specific path and should match the path compiled into the controller program.
-  #if defined(_override_controller_path_socket_suffix_) && defined(_override_controller_path_socket_suffix_length_)
-    #define CONTROLLER_path_socket_suffix_s _override_controller_path_socket_suffix_
+/**
+ * The program name.
+ */
+#ifndef _di_control_program_name_s_
+  #define CONTROL_program_name_s      "control"
+  #define CONTROL_program_name_long_s "Control Program"
 
-    #define CONTROLLER_path_socket_suffix_s_length _override_controller_path_socket_suffix_length_
-  #else
-    #define CONTROLLER_path_socket_suffix_s ".socket"
+  #define CONTROL_program_name_s_length      7
+  #define CONTROL_program_name_long_s_length 15
 
-    #define CONTROLLER_path_socket_suffix_s_length 7
-  #endif // defined(_override_controller_name_socket_suffix_) && defined(_override_controller_name_socket_suffix_length_)
+  extern const f_string_static_t control_program_name_s;
+  extern const f_string_static_t control_program_name_long_s;
+#endif // _di_control_program_name_s_
 
-  extern const f_string_static_t controller_name_socket_s;
-  extern const f_string_static_t controller_path_socket_s;
-  extern const f_string_static_t controller_path_socket_prefix_s;
-  extern const f_string_static_t controller_path_socket_suffix_s;
-#endif // _di_controller_strings_
+/**
+ * The main program parameters.
+ */
+#ifndef _di_control_parameter_s_
+  #define CONTROL_short_name_s     "n"
+  #define CONTROL_short_return_s   "R"
+  #define CONTROL_short_settings_s "s"
+  #define CONTROL_short_socket_s   "k"
+
+  #define CONTROL_long_name_s     "name"
+  #define CONTROL_long_return_s   "return"
+  #define CONTROL_long_settings_s "settings"
+  #define CONTROL_long_socket_s   "socket"
+
+  #define CONTROL_short_name_s_length     1
+  #define CONTROL_short_return_s_length   1
+  #define CONTROL_short_settings_s_length 1
+  #define CONTROL_short_socket_s_length   1
+
+  #define CONTROL_long_name_s_length     4
+  #define CONTROL_long_return_s_length   6
+  #define CONTROL_long_settings_s_length 8
+  #define CONTROL_long_socket_s_length   6
+
+  extern const f_string_static_t control_short_name_s;
+  extern const f_string_static_t control_short_return_s;
+  extern const f_string_static_t control_short_settings_s;
+  extern const f_string_static_t control_short_socket_s;
+
+  extern const f_string_static_t control_long_name_s;
+  extern const f_string_static_t control_long_return_s;
+  extern const f_string_static_t control_long_settings_s;
+  extern const f_string_static_t control_long_socket_s;
+#endif // _di_control_parameter_s_
 
 /**
  * All special strings used within this program.
@@ -221,115 +202,72 @@ extern "C" {
 #endif // _di_control_strings_s_
 
 /**
- * The control cache.
- *
- * large:  A buffer for storing large sets of data.
- * small:  A buffer for storing small sets of data.
- * packet: A buffer for storing the send packet or the response payload.
- *
- * packet_objects:  The FSS Objects for a packet.
- * packet_contents: The FSS Contents for a packet.
- *
- * header_objects:  The FSS Objects for a packet payload header.
- * header_contents: The FSS Contents for a packet payload header.
+ * Controller defines that the control program utilizes.
  *
- * delimits: The delimits cache.
+ * These are intended to exactly match the relevant controller string defines.
  */
-#ifndef _di_control_cache_t_
-  typedef struct {
-    f_string_dynamic_t large;
-    f_string_dynamic_t small;
-    f_string_dynamic_t packet;
-
-    f_string_ranges_t packet_objects;
-    f_string_rangess_t packet_contents;
-
-    f_string_ranges_t header_objects;
-    f_string_rangess_t header_contents;
-
-    f_number_unsigneds_t delimits;
-  } control_cache_t;
-
-  #define control_cache_initialize \
-    { \
-      f_string_dynamic_t_initialize, \
-      f_string_dynamic_t_initialize, \
-      f_string_dynamic_t_initialize, \
-      f_string_ranges_t_initialize, \
-      f_string_rangess_t_initialize, \
-      f_string_ranges_t_initialize, \
-      f_string_rangess_t_initialize, \
-      f_number_unsigneds_t_initialize, \
-    }
-#endif // _di_control_cache_t_
+#ifndef _di_controller_strings_s_
 
-/**
- * The control data.
- *
- * action: The action type code.
- * argv:   The argument structure in the progam data parameters for simplifying syntax.
- * cache:  A cache.
- * socket: A socket used to connect to the controller.
- */
-#ifndef _di_control_data_t_
-  typedef struct {
-    uint8_t action;
+  // The name_socket is a system-specific path and should match the path compiled into the controller program.
+  #if defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_)
+    #define CONTROLLER_name_socket_s _override_controller_name_socket_
 
-    control_cache_t cache;
+    #define CONTROLLER_name_socket_s_length _override_controller_name_socket_length_
+  #else
+    #define CONTROLLER_name_socket_s "default"
 
-    f_socket_t socket;
+    #define CONTROLLER_name_socket_s_length 7
+  #endif // defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_)
 
-    f_string_static_t *argv;
-  } control_data_t;
+  // The path_socket is a system-specific path and should match the path compiled into the controller program.
+  #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
+    #define CONTROLLER_path_socket_s _override_controller_path_socket_
 
-  #define control_data_t_initialize \
-    { \
-      0, \
-      f_string_dynamic_t_initialize, \
-      f_socket_t_initialize, \
-      0, \
-    }
-#endif // _di_control_data_t_
+    #define CONTROLLER_path_socket_s_length _override_controller_path_socket_length_
+  #elif defined(_controller_as_init_)
+    #define CONTROLLER_path_socket_s "/var/run/init"
 
-/**
- * The packet payload header data.
- *
- * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet.
- *
- * action: The action type code, for any valid action (see: control_action_types enumeration).
- * type:   The packet type represented by the payload packet.
- * status: The status code represented by the payload packet.
- * length: The length of the payload content within the payload packet.
- */
-#ifndef _di_control_payload_header_t_
-  typedef struct {
-    uint8_t action;
-    uint8_t type;
-    f_status_t status;
-    uint16_t length;
-  } control_payload_header_t;
-
-  #define control_payload_header_t_initialize \
-    { \
-      0, \
-      0, \
-      f_status_t_initialize, \
-      f_number_unsigned_t_initialize, \
-    }
-#endif // _di_control_payload_header_t_
+    #define CONTROLLER_path_socket_s_length 13
+  #else
+    #define CONTROLLER_path_socket_s "/var/run/controller"
 
-/**
- * Deallocate the control data.
- *
- * @param data
- *   The control data.
- */
-#ifndef _di_control_data_delete_
-  extern void control_data_delete(control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_data_delete_
+    #define CONTROLLER_path_socket_s_length 19
+  #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
+
+  // The name_socket_prefix is a system-specific path and should match the path compiled into the controller program.
+  #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_)
+    #define CONTROLLER_path_socket_prefix_s _override_controller_path_socket_prefix_
+
+    #define CONTROLLER_path_socket_prefix_s_length _override_controller_path_socket_prefix_length_
+  #elif defined(_controller_as_init_)
+    #define CONTROLLER_path_socket_prefix_s "init-"
+
+    #define CONTROLLER_path_socket_prefix_s_length 5
+  #else
+    #define CONTROLLER_path_socket_prefix_s ""
+
+    #define CONTROLLER_path_socket_prefix_s_length 0
+  #endif // defined(_override_controller_name_socket_prefix_) && defined(_override_controller_name_socket_prefix_length_)
+
+  // The name_socket_suffix is a system-specific path and should match the path compiled into the controller program.
+  #if defined(_override_controller_path_socket_suffix_) && defined(_override_controller_path_socket_suffix_length_)
+    #define CONTROLLER_path_socket_suffix_s _override_controller_path_socket_suffix_
+
+    #define CONTROLLER_path_socket_suffix_s_length _override_controller_path_socket_suffix_length_
+  #else
+    #define CONTROLLER_path_socket_suffix_s ".socket"
+
+    #define CONTROLLER_path_socket_suffix_s_length 7
+  #endif // defined(_override_controller_name_socket_suffix_) && defined(_override_controller_name_socket_suffix_length_)
+
+  extern const f_string_static_t controller_name_socket_s;
+  extern const f_string_static_t controller_path_socket_s;
+  extern const f_string_static_t controller_path_socket_prefix_s;
+  extern const f_string_static_t controller_path_socket_suffix_s;
+#endif // _di_controller_strings_s_
 
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
-#endif // _PRIVATE_common_h
+#endif // _control_common_string_h
diff --git a/level_3/control/c/main/common/type.c b/level_3/control/c/main/common/type.c
new file mode 100644 (file)
index 0000000..2193092
--- /dev/null
@@ -0,0 +1,49 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_main_delete_
+  void control_main_delete(control_main_t * const main) {
+
+    if (!main) return;
+
+    fll_program_data_delete(&main->program);
+    control_setting_delete(&main->setting);
+
+    f_string_dynamic_resize(0, &main->cache.large);
+    f_string_dynamic_resize(0, &main->cache.small);
+    f_string_dynamic_resize(0, &main->cache.packet);
+
+    f_string_ranges_resize(0, &main->cache.objects);
+    f_string_rangess_resize(0, &main->cache.contents);
+
+    f_string_ranges_resize(0, &main->cache.packet_objects);
+    f_string_rangess_resize(0, &main->cache.packet_contents);
+
+    f_string_ranges_resize(0, &main->cache.header_objects);
+    f_string_rangess_resize(0, &main->cache.header_contents);
+
+    f_number_unsigneds_resize(0, &main->cache.delimits);
+  }
+#endif // _di_control_main_delete_
+
+#ifndef _di_control_setting_delete_
+  f_status_t control_setting_delete(control_setting_t * const setting) {
+
+    if (!setting) return F_status_set_error(F_parameter);
+
+    f_string_dynamic_resize(0, &setting->name_socket);
+    f_string_dynamic_resize(0, &setting->path_settings);
+    f_string_dynamic_resize(0, &setting->path_socket);
+
+    f_string_dynamics_resize(0, &setting->actions);
+
+    return F_none;
+  }
+#endif // _di_control_setting_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/common/type.h b/level_3/control/c/main/common/type.h
new file mode 100644 (file)
index 0000000..63ae8ad
--- /dev/null
@@ -0,0 +1,218 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common type structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_common_type_h
+#define _control_common_type_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The control cache.
+ *
+ * large:  A buffer for storing large sets of data.
+ * small:  A buffer for storing small sets of data.
+ * packet: A buffer for storing the send packet or the response payload.
+ *
+ * objects:  An array of ranges representing objects.
+ * contents: An array of ranges representing contents.
+ * delimits: An array of ranges representing delimits.
+ *
+ * packet_objects:  The FSS Objects for a packet.
+ * packet_contents: The FSS Contents for a packet.
+ *
+ * header_objects:  The FSS Objects for a packet payload header.
+ * header_contents: The FSS Contents for a packet payload header.
+ *
+ * delimits: The delimits cache.
+ */
+#ifndef _di_control_cache_t_
+  typedef struct {
+    f_string_dynamic_t large;
+    f_string_dynamic_t small;
+    f_string_dynamic_t packet;
+
+    f_string_ranges_t objects;
+    f_string_rangess_t contents;
+    f_number_unsigneds_t delimits;
+
+    f_string_ranges_t packet_objects;
+    f_string_rangess_t packet_contents;
+
+    f_string_ranges_t header_objects;
+    f_string_rangess_t header_contents;
+  } control_cache_t;
+
+  #define control_cache_t_initialize \
+    { \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_string_ranges_t_initialize, \
+      f_string_rangess_t_initialize, \
+      f_number_unsigneds_t_initialize, \
+      f_string_ranges_t_initialize, \
+      f_string_rangess_t_initialize, \
+      f_string_ranges_t_initialize, \
+      f_string_rangess_t_initialize, \
+    }
+#endif // _di_control_cache_t_
+
+/**
+ * The packet payload header data.
+ *
+ * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet.
+ *
+ * action: The action type code, for any valid action (see: control_action_types enumeration).
+ * type:   The packet type represented by the payload packet.
+ * status: The status code represented by the payload packet.
+ * length: The length of the payload content within the payload packet.
+ */
+#ifndef _di_control_payload_header_t_
+  typedef struct {
+    uint8_t action;
+    uint8_t type;
+    f_status_t status;
+    uint16_t length;
+  } control_payload_header_t;
+
+  #define control_payload_header_t_initialize \
+    { \
+      0, \
+      0, \
+      f_status_t_initialize, \
+      f_number_unsigned_t_initialize, \
+    }
+#endif // _di_control_payload_header_t_
+
+/**
+ * The control main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * Properties:
+ *   - flag:       Flags passed to the main function.
+ *   - action:     The action type code.
+ *   - size_write: The write size of a packet request or response.
+ *
+ *   - status_signal: A status used eclusively by the threaded signal handler.
+ *   - state:         The state data used when processing the data.
+ *
+ *   - range:  A range for any particular use.
+ *   - socket: A socket used to connect to the controller.
+ *
+ *   - name_socket:   The name of the socket file.
+ *   - path_settings: The path to the settings file.
+ *   - path_socket:   The path to the socket file.
+ *   - actions:       The requested actions.
+ */
+#ifndef _di_control_setting_t_
+  typedef struct {
+    uint16_t flag;
+    uint8_t action;
+    f_number_unsigned_t size_write;
+
+    f_status_t status_signal;
+    f_state_t state;
+
+    f_string_range_t range;
+    f_socket_t socket;
+
+    f_string_dynamic_t name_socket;
+    f_string_dynamic_t path_settings;
+    f_string_dynamic_t path_socket;
+    f_string_dynamics_t actions;
+  } control_setting_t;
+
+  #define control_setting_t_initialize \
+    { \
+      control_main_flag_none_e, \
+      0, \
+      0, \
+      F_none, \
+      f_state_t_initialize, \
+      f_string_range_t_initialize, \
+      f_socket_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamics_t_initialize, \
+    }
+#endif // _di_control_setting_t_
+
+/**
+ * The main program data as a single structure.
+ *
+ * Properties:
+ *   - program: The main program data.
+ *   - setting: The settings data.
+ *   - cache:   The cache data.
+ */
+#ifndef _di_control_main_t_
+  typedef struct {
+    fll_program_data_t program;
+    control_setting_t setting;
+    control_cache_t cache;
+  } control_main_t;
+
+  #define control_main_t_initialize \
+    { \
+      fll_program_data_t_initialize, \
+      control_setting_t_initialize, \
+      control_cache_t_initialize, \
+    }
+#endif // _di_control_main_t_
+
+/**
+ * Deallocate main program data.
+ *
+ * @param setting_make
+ *   The make setting data.
+ *
+ *   This does not alter main.setting.state.status.
+ *
+ * @see f_number_unsigneds_resize()
+ * @see f_string_dynamic_resize()
+ * @see f_string_ranges_resize()
+ * @see f_string_rangess_resize()
+ * @see fll_program_data_delete()
+ */
+#ifndef _di_control_main_delete_
+  extern void control_main_delete(control_main_t * const main);
+#endif // _di_control_main_delete_
+
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *
+ *   This does not alter setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see f_string_dynamic_resize()
+ * @see f_string_dynamics_resize()
+ */
+#ifndef _di_control_setting_delete_
+  extern f_status_t control_setting_delete(control_setting_t * const setting);
+#endif // _di_control_setting_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_common_type_h
diff --git a/level_3/control/c/main/control.c b/level_3/control/c/main/control.c
new file mode 100644 (file)
index 0000000..a84c778
--- /dev/null
@@ -0,0 +1,129 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_main_
+  void control_main(control_main_t * const main) {
+
+    if (!main) return;
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      return;
+    }
+
+    if ((main->setting.flag & control_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+      fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+    }
+
+    main->setting.state.status = F_none;
+
+    if (main->setting.flag & (control_main_flag_help_e | control_main_flag_version_e | control_main_flag_copyright_e)) {
+      if (main->setting.flag & control_main_flag_help_e) {
+        control_print_message_help(&main->program.message);
+      }
+      else if (main->setting.flag & control_main_flag_version_e) {
+        fll_program_print_version(&main->program.message, control_program_version_s);
+      }
+      else if (main->setting.flag & control_main_flag_copyright_e) {
+        fll_program_print_copyright(&main->program.message);
+      }
+
+      if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
+      return;
+    }
+
+    if (main->setting.flag & control_main_flag_pipe_e) {
+      control_print_error_pipe_supported_not(&main->program.error);
+
+      main->setting.state.status = F_status_set_error(F_support_not);
+    }
+    else if (main->setting.actions.used) {
+      main->setting.action = control_action_type_identify(main->setting.actions.array[0]);
+
+      if (main->setting.action) {
+        control_action_verify(main);
+      }
+      else {
+        control_print_error_parameter_action_not(&main->program.error, main->setting.actions.array[0]);
+
+        main->setting.state.status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(main->setting.state.status)) {
+        control_packet_build(main);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if (F_status_set_fine(main->setting.state.status) == F_too_large) {
+            control_print_error_request_packet_too_large(&main->program.error);
+          }
+          else {
+            control_print_error(&main->program.error, macro_control_f(control_packet_build));
+          }
+        }
+
+        if (F_status_is_error_not(main->setting.state.status)) {
+          control_packet_send(main);
+
+          if (F_status_is_error(main->setting.state.status)) {
+            control_print_error(&main->program.error, macro_control_f(control_packet_send));
+          }
+        }
+
+        if (F_status_is_error_not(main->setting.state.status)) {
+          control_payload_header_t header = control_payload_header_t_initialize;
+
+          control_packet_receive(main, &header);
+
+          if (F_status_is_error(main->setting.state.status)) {
+            if (F_status_set_fine(main->setting.state.status) == F_too_large) {
+              control_print_error_response_packet_valid_not(&main->program.error);
+            }
+            else {
+              control_print_error(&main->program.error, macro_control_f(control_packet_receive));
+            }
+          }
+          else {
+            control_packet_process(main, &header);
+
+            // Print the error message only if the error message is not already printed.
+            if (F_status_is_error(main->setting.state.status)) {
+              if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(main->setting.state.status) != header.status || (header.status != F_failure && header.status != F_busy))) {
+                control_print_error(&main->program.error, macro_control_f(control_packet_process));
+              }
+            }
+          }
+        }
+      }
+
+      if (main->setting.socket.id != -1) {
+        f_socket_disconnect(&main->setting.socket, f_socket_close_fast_e);
+      }
+    }
+    else {
+      control_print_error_parameter_actions_none(&main->program.error);
+
+      main->setting.state.status = F_status_set_error(F_data_not);
+    }
+
+    if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) {
+      fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+    }
+
+    if (F_status_is_error(main->setting.state.status)) return;
+
+    main->setting.state.status = F_none;
+  }
+#endif // _di_control_main_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
similarity index 57%
rename from level_3/control/c/control.h
rename to level_3/control/c/main/control.h
index ec77cc73074c90b0141e1a4f285d64b4bf45c4ce..dd17517c1bbc684cdea9b428f8c31995e112cdf8 100644 (file)
@@ -4,11 +4,6 @@
  * Project: Control
  * API Version: 0.7
  * Licenses: lgpl-2.1-or-later
- *
- * This is the Control program.
- *
- * This program utilizes the Featureless Linux Library.
- * This program is used to communicate with the "controller" program that exists as a system init (an alternative to sysvinit, initng, etc..).
  */
 #ifndef _control_h
 #define _control_h
@@ -35,6 +30,7 @@
 #include <fll/level_0/rip.h>
 #include <fll/level_0/signal.h>
 #include <fll/level_0/socket.h>
+#include <fll/level_0/thread.h>
 #include <fll/level_0/status_string.h>
 
 // FLL-1 includes.
 #include <fll/level_2/program.h>
 
 // Control includes.
-#include <program/control/common.h>
-#include <program/control/print.h>
+#include <program/control/main/common/define.h>
+#include <program/control/main/common/enumeration.h>
+#include <program/control/main/common/print.h>
+#include <program/control/main/common/string.h>
+#include <program/control/main/common/type.h>
+#include <program/control/main/common.h>
+#include <program/control/main/print/data.h>
+#include <program/control/main/print/debug.h>
+#include <program/control/main/print/error.h>
+#include <program/control/main/print/message.h>
+#include <program/control/main/print/warning.h>
+#include <program/control/main/action.h>
+#include <program/control/main/packet.h>
+#include <program/control/main/payload.h>
+#include <program/control/main/signal.h>
+#include <program/control/main/thread.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -71,19 +81,18 @@ extern "C" {
  *   - F_signal_termination
  *
  * @param main
- *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
- *
- * @return
- *   F_none on success.
+ *   The main program data and settings.
  *
- *   F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_interrupt (with error bit) on (exit) signal received.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_control_main_
-  extern f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting);
+  extern void control_main(control_main_t * const main);
 #endif // _di_control_main_
 
 #ifdef __cplusplus
diff --git a/level_3/control/c/main/main.c b/level_3/control/c/main/main.c
new file mode 100644 (file)
index 0000000..bfde226
--- /dev/null
@@ -0,0 +1,77 @@
+#include "control.h"
+
+int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
+
+  control_main_t data = control_main_t_initialize;
+
+  data.program.debug.flag |= control_print_flag_debug_e | control_print_flag_out_e;
+  data.program.error.flag |= control_print_flag_error_e | control_print_flag_out_e;
+  data.program.output.flag |= control_print_flag_out_e;
+  data.program.message.flag |= control_print_flag_message_e | control_print_flag_out_e;
+  data.program.warning.flag |= control_print_flag_warning_e | control_print_flag_out_e;
+  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;
+
+  f_console_parameter_t parameters[] = control_console_parameter_t_initialize;
+
+  data.program.parameters.array = parameters;
+  data.program.parameters.used = control_parameter_total_d;
+  data.program.environment = envp;
+
+  data.setting.socket.domain = f_socket_protocol_family_local_e;
+  data.setting.socket.type = f_socket_type_stream_e;
+  data.setting.socket.length = sizeof(struct sockaddr_un);
+
+  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);
+
+      control_setting_load(arguments, &data);
+    }
+
+    control_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, &control_thread_signal, (void *) &data);
+
+      if (F_status_is_error(data.setting.state.status)) {
+        control_print_error(&data.program.error, macro_control_f(f_thread_create));
+      }
+      else {
+        {
+          const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+
+          control_setting_load(arguments, &data);
+        }
+
+        if (!control_signal_check(&data)) {
+          control_main(&data);
+        }
+
+        f_thread_cancel(id_signal);
+        f_thread_join(id_signal, 0);
+      }
+    }
+  #endif // _di_thread_support_
+
+  control_main_delete(&data);
+
+  fll_program_standard_set_down(&data.program);
+
+  return (F_status_is_error(data.setting.state.status) || data.setting.state.status == F_false) ? 1 : 0;
+}
diff --git a/level_3/control/c/main/packet.c b/level_3/control/c/main/packet.c
new file mode 100644 (file)
index 0000000..56c11d5
--- /dev/null
@@ -0,0 +1,561 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_packet_build_
+  void control_packet_build(control_main_t * const main) {
+
+    if (!main) return;
+
+    main->cache.packet.used = 0;
+    main->cache.large.used = 0;
+    main->cache.small.used = 0;
+
+    f_number_unsigned_t i = 0;
+
+    {
+      f_number_unsigned_t length = 5 + f_fss_header_s.used + f_fss_payload_s.used;
+      length += control_action_s.used + control_length_s.used + control_type_s.used;
+      length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2;
+      length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3;
+      length += main->setting.actions.array[0].used + f_string_ascii_0_s.used;
+
+      // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length.
+      for (i = 1; i < main->setting.actions.used; ++i) {
+        length += f_fss_payload_header_next_s.used + main->setting.actions.array[i].used;
+      } // for
+
+      if (main->setting.action == control_action_type_kexec_e || main->setting.action == control_action_type_reboot_e || main->setting.action == control_action_type_shutdown_e) {
+        length += control_init_s.used;
+      }
+      else {
+        length += control_controller_s.used;
+      }
+
+      if (length > 0xffffffffu) {
+        main->setting.state.status = F_status_set_error(F_too_large);
+
+        return;
+      }
+
+      main->setting.state.status = f_string_dynamic_resize(length, &main->cache.packet);
+      if (F_status_is_error(main->setting.state.status)) return;
+    }
+
+    f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0);
+
+    f_string_static_t contents_array[main->setting.actions.used];
+    f_string_statics_t contents = macro_f_string_statics_t_initialize_1(contents_array, 0, main->setting.actions.used);
+
+    // The Packet Control Block.
+    {
+      f_char_t block_control = (f_char_t) control_packet_flag_binary_d;
+
+      #ifdef _is_F_endian_big
+        block_control |= (f_char_t) control_packet_flag_endian_big_d;
+      #endif // _is_F_endian_big
+
+      main->setting.state.status = f_string_append(&block_control, 1, &main->cache.packet);
+      if (F_status_is_error(main->setting.state.status)) return;
+    }
+
+    // Reserve the Packet Size Block to be calculated later.
+    main->cache.packet.used = 5;
+
+    // Payload Header: type.
+    if (main->setting.action == control_action_type_kexec_e || main->setting.action == control_action_type_reboot_e || main->setting.action == control_action_type_shutdown_e) {
+      contents_array[0] = control_init_s;
+    }
+    else {
+      contents_array[0] = control_controller_s;
+    }
+
+    contents.used = 1;
+
+    fll_fss_extended_write(control_type_s, contents, 0, &main->cache.large, &state);
+
+    // Payload Header: action.
+    if (F_status_is_error_not(state.status)) {
+      for (contents.used = 0; contents.used < main->setting.actions.used; ++contents.used) {
+        contents_array[contents.used] = main->setting.actions.array[contents.used];
+      } // for
+
+      fll_fss_extended_write(control_action_s, contents, 0, &main->cache.large, &state);
+    }
+
+    // Payload Header: length.
+    if (F_status_is_error_not(state.status)) {
+      contents_array[0] = f_string_ascii_0_s;
+      contents.used = 1;
+
+      fll_fss_extended_write(control_length_s, contents, 0, &main->cache.large, &state);
+    }
+
+    // Payload Packet: Header.
+    if (F_status_is_error_not(state.status)) {
+      fll_fss_payload_write(f_fss_header_s, main->cache.large, F_false, 0, &main->cache.packet, &state);
+    }
+
+    // Payload Packet: Payload.
+    if (F_status_is_error_not(state.status)) {
+      main->cache.large.used = 0;
+
+      fll_fss_payload_write(f_fss_payload_s, main->cache.large, F_false, 0, &main->cache.packet, &state);
+    }
+
+    if (F_status_is_error(state.status)) {
+      main->setting.state.status = state.status;
+
+      return;
+    }
+
+    // Construct Packet Size Block.
+    #ifdef _is_F_endian_big
+      main->cache.packet.string[1] = main->cache.packet.used & 0xffu;
+      main->cache.packet.string[2] = main->cache.packet.used & 0xff00u;
+      main->cache.packet.string[3] = main->cache.packet.used & 0xff0000u;
+      main->cache.packet.string[4] = main->cache.packet.used & 0xff000000u;
+    #else
+      main->cache.packet.string[1] = main->cache.packet.used & 0xff000000u;
+      main->cache.packet.string[2] = main->cache.packet.used & 0xff0000u;
+      main->cache.packet.string[3] = main->cache.packet.used & 0xff00u;
+      main->cache.packet.string[4] = main->cache.packet.used & 0xffu;
+    #endif // _is_F_endian_big
+
+    main->setting.state.status = F_none;
+  }
+#endif // _di_control_packet_build_
+
+#ifndef _di_control_packet_header_flag_
+  uint8_t control_packet_header_flag(const uint8_t buffer[]) {
+    return (uint8_t) (((buffer[0] & 0x8u) ? control_packet_flag_binary_d : 0) | ((buffer[0] & 0x4u) ? control_packet_flag_endian_big_d : 0));
+  }
+#endif // _di_control_packet_header_flag_
+
+#ifndef _di_control_packet_header_length_
+  uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) {
+
+    #ifdef _is_F_endian_big
+      if (is_big) return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
+    #else
+      if (!is_big) return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
+    #endif // _is_F_endian_big
+
+    return (buffer[4] << 24u) | (buffer[3] << 16u) | (buffer[2] << 8u) | buffer[1];
+  }
+#endif // _di_control_packet_header_length_
+
+#ifndef _di_control_packet_receive_
+  void control_packet_receive(control_main_t * const main, control_payload_header_t * const header) {
+
+    if (!main || !header) return;
+
+    main->cache.large.used = 0;
+    main->cache.small.used = 0;
+    main->cache.packet.used = 0;
+    main->cache.packet_objects.used = 0;
+    main->cache.packet_contents.used = 0;
+    main->cache.header_objects.used = 0;
+    main->cache.header_contents.used = 0;
+    main->cache.delimits.used = 0;
+
+    header->action = 0;
+    header->type = 0;
+    header->status = F_none;
+    header->length = 0;
+
+    f_number_unsigned_t i = 0;
+    f_string_range_t range_header = f_string_range_t_initialize;
+    f_string_range_t range_payload = f_string_range_t_initialize;
+
+    {
+      f_number_unsigned_t length = 5;
+      uint8_t head[length];
+
+      memset(head, 0, sizeof(uint8_t) * length);
+
+      main->setting.state.status = f_socket_read(&main->setting.socket, f_socket_flag_peek_e, (void *) head, &length);
+      if (F_status_is_error(main->setting.state.status)) return;
+
+      if (length < 5) {
+        main->setting.state.status = F_status_set_error(F_packet_not);
+
+        return;
+      }
+
+      // Only the first two bits of the 8 Control bits are allowed to be set to 1 for this Packet.
+      if (head[0] & (~(control_packet_flag_binary_d | control_packet_flag_endian_big_d))) {
+        main->setting.state.status = F_status_set_error(F_packet_not);
+
+        return;
+      }
+
+      length = control_packet_header_length(head[0] & control_packet_flag_endian_big_d, head);
+
+      if (length > 0xffffffffu) {
+        main->setting.state.status = F_status_set_error(F_too_large);
+
+        return;
+      }
+
+      main->setting.state.status = f_string_dynamic_increase_by(length, &main->cache.large);
+      if (F_status_is_error(main->setting.state.status)) return;
+
+      main->setting.state.status = f_socket_read(&main->setting.socket, f_socket_flag_wait_all_e, (void *) head, &length);
+      if (F_status_is_error(main->setting.state.status)) return;
+
+      if (length < main->cache.large.used) {
+        main->setting.state.status = F_status_set_error(F_too_small);
+
+        return;
+      }
+
+      if (length > main->cache.large.used) {
+        main->setting.state.status = F_status_set_error(F_too_large);
+
+        return;
+      }
+    }
+
+    {
+      f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0);
+      f_string_range_t range_packet = macro_f_string_range_t_initialize_2(main->cache.large.used);
+
+      fll_fss_basic_list_read(main->cache.large, &range_packet, &main->cache.packet_objects, &main->cache.packet_contents, &main->cache.delimits, 0, 0, &state);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        control_print_debug_packet_message(&main->program.debug, "Failure while reading FSS Basic List in the response packet", 0, 0);
+
+        if (F_status_set_fine(main->setting.state.status) == F_memory_not) return;
+
+        main->setting.state.status = F_status_set_error(F_header);
+
+        return;
+      }
+
+      f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &state);
+
+      if (F_status_is_error(state.status)) {
+        main->setting.state.status = state.status;
+
+        control_print_debug_packet_message(&main->program.debug, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0);
+
+        main->setting.state.status = F_status_set_error(F_header);
+
+        return;
+      }
+
+      main->cache.delimits.used = 0;
+
+      {
+        f_string_ranges_t *content_header = 0;
+        f_string_ranges_t *content_payload = 0;
+
+        for (; i < main->cache.packet_objects.used; ++i) {
+
+          if (f_compare_dynamic_partial_string(f_fss_header_s.string, main->cache.large, f_fss_header_s.used, main->cache.packet_objects.array[i]) == F_equal_to) {
+
+            // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs.
+            if (content_header) {
+              control_print_debug_packet_message(&main->program.debug, "Multiple %[" F_fss_header_s "%] found in response packet", 0, 0);
+
+              main->setting.state.status = F_status_set_error(F_payload_not);
+
+              return;
+            }
+
+            content_header = &main->cache.packet_contents.array[i];
+          }
+          else if (f_compare_dynamic_partial_string(f_fss_payload_s.string, main->cache.large, f_fss_payload_s.used, main->cache.packet_objects.array[i]) == F_equal_to) {
+
+            // Only a single "payload" is supported by the FSS-000E (Payload) standard.
+            if (content_payload) {
+              control_print_debug_packet_message(&main->program.debug, "Multiple %[" F_fss_payload_s "%] found in response packet", 0, 0);
+
+              main->setting.state.status = F_status_set_error(F_payload_not);
+
+              return;
+            }
+
+            if (i + 1 < main->cache.packet_contents.used) {
+              control_print_debug_packet_message(&main->program.debug, "Invalid FSS Payload format, the %[" F_fss_payload_s "%] is required to be the last FSS Basic List Object", 0, 0);
+
+              main->setting.state.status = F_status_set_error(F_payload_not);
+
+              return;
+            }
+
+            content_payload = &main->cache.packet_contents.array[i];
+          }
+        } // for
+
+        if (!content_header) {
+          control_print_debug_packet_message(&main->program.debug, "Did not find a %[" F_fss_header_s "%] in the response packet", 0, 0);
+
+          main->setting.state.status = F_status_set_error(F_payload_not);
+
+          return;
+        }
+
+        if (!content_payload) {
+          control_print_debug_packet_message(&main->program.debug, "Did not find a %[" F_fss_payload_s "%] in the response packet", 0, 0);
+
+          main->setting.state.status = F_status_set_error(F_payload_not);
+
+          return;
+        }
+
+        range_header = content_header->array[0];
+        range_payload = content_payload->array[0];
+      }
+
+      {
+        // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type.
+        uint8_t found = 0;
+        f_number_unsigned_t number = 0;
+        f_string_range_t range = range_header;
+
+        fll_fss_extended_read(main->cache.large, &range, &main->cache.header_objects, &main->cache.header_contents, 0, 0, &main->cache.delimits, 0, &state);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          control_print_debug_packet_message(&main->program.debug, "Failure while reading FSS Extended in the response packet", 0, 0);
+
+          if (F_status_set_fine(main->setting.state.status) == F_memory_not) return;
+
+          main->setting.state.status = F_status_set_error(F_header_not);
+
+          return;
+        }
+
+        f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &state);
+
+        if (F_status_is_error(state.status)) {
+          main->setting.state.status = state.status;
+
+          control_print_debug_packet_message(&main->program.debug, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0);
+
+          main->setting.state.status = F_status_set_error(F_header_not);
+
+          return;
+        }
+
+        if (!main->cache.header_contents.used) {
+          control_print_debug_packet_message(&main->program.debug, "Did not find any Content within the %[" F_fss_header_s "%]", 0, 0);
+
+          main->setting.state.status = F_status_set_error(F_header_not);
+
+          return;
+        }
+
+        for (i = 0; i < main->cache.header_objects.used; ++i) {
+
+          if (f_compare_dynamic_partial_string(control_action_s.string, main->cache.large, control_action_s.used, main->cache.header_objects.array[i]) == F_equal_to) {
+            if (!(found & 0x1)) {
+              const f_number_unsigned_t action_length = (main->cache.header_contents.array[i].array[0].stop - main->cache.header_contents.array[i].array[0].start) + 1;
+              char action_string[action_length + 1];
+              const f_string_static_t action = macro_f_string_static_t_initialize_1(action_string, 0, action_length);
+
+              memcpy(action_string, main->cache.large.string + main->cache.header_contents.array[i].array[0].start, action_length);
+              action_string[action_length] = 0;
+
+              found |= 0x1;
+
+              control_print_debug_packet_header_object_and_content(&main->program.debug, control_action_s, main->cache.large, main->cache.header_contents.array[i].array[0]);
+
+              header->action = control_action_type_identify(action);
+
+              if (!header->action) {
+                control_print_debug_packet_message(&main->program.debug, "Failed to identify %[" CONTROL_action_s "%] from: ", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                main->setting.state.status = F_status_set_error(F_header_not);
+
+                return;
+              }
+            }
+            else {
+              control_print_warning_packet_header_duplicate_object(&main->program.warning, control_action_s);
+            }
+          }
+          else if (f_compare_dynamic_partial_string(control_length_s.string, main->cache.large, control_length_s.used, main->cache.header_objects.array[i]) == F_equal_to) {
+            if (!(found & 0x2)) {
+              found |= 0x2;
+              number = 0;
+
+              control_print_debug_packet_header_object_and_content(&main->program.debug, control_length_s, main->cache.large, main->cache.header_contents.array[i].array[0]);
+
+              main->setting.state.status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, main->cache.large, main->cache.header_contents.array[i].array[0], &number);
+
+              if (F_status_is_error(main->setting.state.status)) {
+                control_print_debug_packet_message(&main->program.debug, "Failed to process number for %[" CONTROL_length_s "%] in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                main->setting.state.status = F_status_set_error(F_header_not);
+
+                return;
+              }
+
+              if (number > F_type_size_max_32_unsigned_d) {
+                control_print_debug_packet_message(&main->program.debug, "Processed number for %[" CONTROL_length_s "%] exceeds allowed size in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                main->setting.state.status = F_status_set_error(F_header_not);
+
+                return;
+              }
+
+              header->length = (uint16_t) number;
+            }
+            else {
+              control_print_warning_packet_header_duplicate_object(&main->program.warning, control_length_s);
+            }
+          }
+          else if (f_compare_dynamic_partial_string(control_status_s.string, main->cache.large, control_status_s.used, main->cache.header_objects.array[i]) == F_equal_to) {
+            if (!(found & 0x4)) {
+              found |= 0x4;
+              number = 0;
+
+              control_print_debug_packet_header_object_and_content(&main->program.debug, control_status_s, main->cache.large, main->cache.header_contents.array[i].array[0]);
+
+              // Attempt to get packet status as a number.
+              main->setting.state.status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, main->cache.large, main->cache.header_contents.array[i].array[0], &number);
+
+              if (F_status_set_fine(main->setting.state.status) == F_number) {
+
+                // Not a number, so attempt get by packet status string name.
+                const f_number_unsigned_t name_length = (main->cache.header_contents.array[i].array[0].stop - main->cache.header_contents.array[i].array[0].start) + 1;
+                char name_string[name_length + 1];
+                const f_string_static_t name = macro_f_string_static_t_initialize_1(name_string, 0, name_length);
+
+                memcpy(name_string, main->cache.large.string + main->cache.header_contents.array[i].array[0].start, name_length);
+                name_string[name_length] = 0;
+
+                main->setting.state.status = fl_status_string_from(name, &header->status);
+
+                if (F_status_is_error(main->setting.state.status)) {
+                  control_print_debug_packet_message(&main->program.debug, "Failed to process %[" CONTROL_status_s "%] in the response packet, Content is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                  main->setting.state.status = F_status_set_error(F_header_not);
+
+                  return;
+                }
+              }
+              else if (F_status_is_error(main->setting.state.status)) {
+                control_print_debug_packet_message(&main->program.debug, "Failed to process number for %[" CONTROL_status_s "%] in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                if (F_status_set_fine(main->setting.state.status) == F_memory_not) return;
+
+                main->setting.state.status = F_status_set_error(F_header_not);
+
+                return;
+              }
+              else {
+                if (number > F_status_size_max_with_bits_d) {
+                  control_print_debug_packet_message(&main->program.debug, "Processed number for %[" CONTROL_status_s "%] exceeds allowed size in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                  main->setting.state.status = F_status_set_error(F_header_not);
+
+                  return;
+                }
+              }
+            }
+            else {
+              control_print_warning_packet_header_duplicate_object(&main->program.warning, control_length_s);
+            }
+          }
+          else if (f_compare_dynamic_partial_string(control_type_s.string, main->cache.large, control_type_s.used, main->cache.header_objects.array[i]) == F_equal_to) {
+            if (!(found & 0x8)) {
+              found |= 0x8;
+
+              control_print_debug_packet_header_object_and_content(&main->program.debug, control_type_s, main->cache.large, main->cache.header_contents.array[i].array[0]);
+
+              if (f_compare_dynamic_partial_string(control_controller_s.string, main->cache.large, control_controller_s.used, main->cache.header_contents.array[i].array[0]) == F_equal_to) {
+                header->type = control_payload_type_controller_e;
+              }
+              else if (f_compare_dynamic_partial_string(control_error_s.string, main->cache.large, control_error_s.used, main->cache.header_contents.array[i].array[0]) == F_equal_to) {
+                header->type = control_payload_type_error_e;
+              }
+              else {
+                control_print_debug_packet_message(&main->program.debug, "Unknown %[" CONTROL_type_s "%] in response packet, Content is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]);
+
+                main->setting.state.status = F_status_set_error(F_header_not);
+
+                return;
+              }
+            }
+            else {
+              control_print_warning_packet_header_duplicate_object(&main->program.warning, control_type_s);
+            }
+          }
+        }
+      }
+    }
+
+    main->setting.state.status = F_none;
+  }
+#endif // _di_control_packet_receive_
+
+#ifndef _di_control_packet_process_
+  void control_packet_process(control_main_t * const main, control_payload_header_t * const header) {
+
+    if (!main || !header) return;
+
+    f_string_static_t string_status = f_string_static_t_initialize;
+
+    {
+      main->setting.state.status = f_status_string_to(header->status, &string_status);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        control_print_warning_packet_process_string_to_failed(&main->program.warning, header->status, main->setting.state.status);
+
+        return;
+      }
+    }
+
+    if (main->setting.flag & control_main_flag_return_e) {
+      fll_print_format("response %q %q %q%r", main->program.output.to, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s);
+    }
+    else if (header->type == control_payload_type_error_e) {
+      control_print_error_packet_response(&main->program.error, *header, string_status);
+    }
+    else if (header->status == F_failure) {
+      control_print_error_packet_response_failure(&main->program.error, *header, string_status);
+    }
+    else if (header->status == F_busy) {
+      control_print_warning_packet_response_busy(&main->program.warning, *header, string_status);
+    }
+    else if (header->status == F_done || header->status == F_success) {
+      control_print_message_packet_response(&main->program.output, *header, string_status);
+    }
+    else {
+
+      // Set type to 0 to inform the caller to handle this error.
+      header->type = 0;
+
+      main->setting.state.status = F_status_set_error(F_known_not);
+
+      return;
+    }
+
+    if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) {
+      main->setting.state.status = F_status_set_error(header->status);
+    }
+    else {
+      main->setting.state.status = header->status;
+    }
+  }
+#endif // _di_control_packet_process_
+
+#ifndef _di_control_packet_send_
+  void control_packet_send(control_main_t * const main) {
+
+    if (!main) return;
+
+    main->setting.size_write = main->cache.packet.used;
+
+    main->setting.state.status = f_socket_write(&main->setting.socket, 0, (void *) &main->cache.packet, 0);
+  }
+#endif // _di_control_packet_send_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/packet.h b/level_3/control/c/main/packet.h
new file mode 100644 (file)
index 0000000..e2e04ba
--- /dev/null
@@ -0,0 +1,155 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the packet functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_packet_h
+#define _control_packet_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Build the payload, storing it in the large cache.
+ *
+ * @param main
+ *   The main program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_too_large (with error bit) If the message is too large for the packet format to transmit.
+ *
+ *   Errors (with error bit) from: f_string_append().
+ *   Errors (with error bit) from: f_string_dynamic_append().
+ *   Errors (with error bit) from: f_string_dynamic_resize().
+ *   Errors (with error bit) from: fll_fss_extended_write().
+ *   Errors (with error bit) from: fll_fss_payload_write().
+ *
+ * @see f_string_append()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_resize()
+ */
+#ifndef _di_control_packet_build_
+  extern void control_packet_build(control_main_t * const main);
+#endif // _di_control_packet_build_
+
+/**
+ * Given the header buffer, get the flag bits.
+ *
+ * @param buffer
+ *   The buffer to read the length of and get the
+ *
+ * @return
+ *   The 8-bit number representing the flags.
+ */
+#ifndef _di_control_packet_header_flag_
+  extern uint8_t control_packet_header_flag(const uint8_t buffer[]);
+#endif // _di_control_packet_header_flag_
+
+/**
+ * Given the header buffer, get the length bits.
+ *
+ * The endianness is automatically detected and swapped by this function to guarantee host order bytes.
+ *
+ * @param is_big
+ *   If TRUE, then the length in the buffer is in big endian format.
+ *   If FALSE, then the length in the buffer is in little endian format.
+ * @param buffer
+ *   The buffer to read the length of and get the
+ *
+ * @return
+ *   The 32-bit number representing the length.
+ */
+#ifndef _di_control_packet_header_length_
+  extern uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]);
+#endif // _di_control_packet_header_length_
+
+/**
+ * Receive the response from the remote socket, storing it in the large cache.
+ *
+ * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *
+ *     F_header_not (with error bit) If there is a problem processing the packet header.
+ *     F_memory_not (with error bit) On out of memory issues (this is passed through from called functions).
+ *     F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure.
+ *     F_payload_not (with error bit) If there is a problem processing the packet payload.
+ *     F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size.
+ *     F_too_small (with error bit) If the received packet actual size is smaller than the specified size.
+ *
+ *     Errors (with error bit) from: f_socket_read().
+ *     Errors (with error bit) from: f_string_dynamic_increase_by().
+ *     Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect().
+ *     Errors (with error bit) from: fll_fss_extended_read().
+ *     Errors (with error bit) from: fll_fss_basic_list_read().
+ * @param header
+ *   The control payload packet header data.
+ *
+ * @see f_socket_read()
+ * @see f_string_dynamic_increase_by()
+ * @see fl_conversion_dynamic_partial_to_unsigned_detect()
+ * @see f_fss_apply_delimit()
+ * @see fl_status_string_from()
+ * @see fll_fss_extended_read()
+ * @see fll_fss_basic_list_read()
+ */
+#ifndef _di_control_packet_receive_
+  extern void control_packet_receive(control_main_t * const main, control_payload_header_t * const header);
+#endif // _di_control_packet_receive_
+
+/**
+ * Process the received and loaded packet.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_done on success but action has no success or failure states.
+ *     F_success on success.
+ *
+ *     F_busy (with error bit)
+ *     F_failure (with error bit) on success but controller returned failure for action.
+ *     F_known_not (with error bit) if the Payload type is unknown.
+ *     Any error (with error bit) on failure where the error is defined by the controller service.
+ * @param header
+ *   The control payload packet header data.
+ */
+#ifndef _di_control_packet_process_
+  extern void control_packet_process(control_main_t * const main, control_payload_header_t * const header);
+#endif // _di_control_packet_process_
+
+/**
+ * Send the payload to the remote socket, getting the payload from the large cache.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_socket_write().
+ *
+ * @see f_socket_write()
+ */
+#ifndef _di_control_packet_send_
+  extern void control_packet_send(control_main_t * const main);
+#endif // _di_control_packet_send_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_packet_h
diff --git a/level_3/control/c/main/payload.c b/level_3/control/c/main/payload.c
new file mode 100644 (file)
index 0000000..aa20e06
--- /dev/null
@@ -0,0 +1,38 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_payload_type_identify_
+  const uint8_t control_payload_type_identify(const f_string_static_t payload) {
+
+    if (f_compare_dynamic(payload, control_controller_s) == F_equal_to) return control_payload_type_controller_e;
+    if (f_compare_dynamic(payload, control_error_s) == F_equal_to) return control_payload_type_error_e;
+    if (f_compare_dynamic(payload, control_init_s) == F_equal_to) return control_payload_type_init_e;
+
+    return 0;
+  }
+#endif // _di_control_payload_type_identify_
+
+#ifndef _di_control_payload_type_name_
+  const f_string_static_t control_payload_type_name(const uint8_t type) {
+
+    switch (type) {
+      case control_payload_type_controller_e:
+        return control_controller_s;
+
+      case control_payload_type_error_e:
+        return control_error_s;
+
+      case control_payload_type_init_e:
+        return control_init_s;
+    }
+
+    return f_string_empty_s;
+  }
+#endif // _di_control_payload_type_name_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/payload.h b/level_3/control/c/main/payload.h
new file mode 100644 (file)
index 0000000..12142a0
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the payload functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_payload_h
+#define _control_payload_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Identify the payload code the given name represents.
+ *
+ * @param payload
+ *   The string representing a payload.
+ *
+ * @return
+ *   The payload type code on success.
+ *   0 if name is unknown.
+ */
+#ifndef _di_control_payload_type_identify_
+  extern const uint8_t control_payload_type_identify(const f_string_static_t payload);
+#endif // _di_control_payload_type_identify_
+
+/**
+ * Get a string representing the payload type.
+ *
+ * @param type
+ *   The payload type id.
+ *
+ * @return
+ *   The string with used > 0 on success.
+ *   The string with used == 0 if no match was found.
+ */
+#ifndef _di_control_payload_type_name_
+  extern const f_string_static_t control_payload_type_name(const uint8_t type);
+#endif // _di_control_payload_type_name_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_payload_h
diff --git a/level_3/control/c/main/print/data.c b/level_3/control/c/main/print/data.c
new file mode 100644 (file)
index 0000000..39790a2
--- /dev/null
@@ -0,0 +1,9 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/print/data.h b/level_3/control/c/main/print/data.h
new file mode 100644 (file)
index 0000000..e075bff
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print data functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_print_data_h
+#define _control_print_data_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_print_data_h
diff --git a/level_3/control/c/main/print/debug.c b/level_3/control/c/main/print/debug.c
new file mode 100644 (file)
index 0000000..d22d59e
--- /dev/null
@@ -0,0 +1,59 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_print_debug_packet_header_object_and_content_
+  f_status_t control_print_debug_packet_header_object_and_content(fl_print_t * const print, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_debug_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("Packet header Object '%[%Q%]", print->to, print->set->notable, object, print->set->notable);
+    fl_print_format("' has value '%[%/Q%]'.%r", print->to, print->set->notable, content, content_range, print->set->notable, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_debug_packet_header_object_and_content_
+
+#ifndef _di_control_print_debug_packet_message_
+  f_status_t control_print_debug_packet_message(fl_print_t * const print, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_debug_e) return F_output_not;
+
+    control_main_t * const main = (control_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%s", print->to, message);
+
+    if (buffer) {
+      if (range) {
+        fl_print_format("'%[%/Q%]'", print->to, print->set->notable, *buffer, *range, print->set->notable);
+      }
+      else {
+        fl_print_format("'%[%/Q%]'", print->to, print->set->notable, *buffer, print->set->notable);
+      }
+    }
+
+    if (main->setting.state.status) {
+      fl_print_format(", with status code %[%ui%]'", print->to, print->set->notable, main->setting.state.status, print->set->notable);
+    }
+
+    fl_print_format(".%r", print->to, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_debug_packet_message_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/print/debug.h b/level_3/control/c/main/print/debug.h
new file mode 100644 (file)
index 0000000..a27e4b4
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_print_debug_h
+#define _control_print_debug_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print a message displaying the object and content for some packet header.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param object
+ *   The object string.
+ * @param content
+ *   The content string.
+ * @param content_range
+ *   The range representing the content where the content is found within the content string.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_debug_packet_header_object_and_content_
+  extern f_status_t control_print_debug_packet_header_object_and_content(fl_print_t * const print, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range);
+#endif // _di_control_print_debug_packet_header_object_and_content_
+
+/**
+ * Print a debug message regarding some packet.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param message
+ *   The message to print.
+ *
+ *   A single "%[" followed by a single "%]" is supported in the message and is replaced with "notable" context.
+ * @param buffer
+ *   (optional) An additonal message to print (this is syntax highlighted).
+ *   Set to NULL to not use.
+ * @param range
+ *   (optional) The range within the buffer to print rather than printing the entire buffer.
+ *   Set to NULL to not use.
+ *   This is ignored when buffer is NULL.
+ * @param status
+ *   (optional) A status code that triggered the failure (this is syntax highlighted).
+ *   Set to NULL to not use.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_debug_packet_message_
+  extern f_status_t control_print_debug_packet_message(fl_print_t * const print, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range);
+#endif // _di_control_print_debug_packet_message_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_print_debug_h
diff --git a/level_3/control/c/main/print/error.c b/level_3/control/c/main/print/error.c
new file mode 100644 (file)
index 0000000..f074e17
--- /dev/null
@@ -0,0 +1,419 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_print_error_
+  f_status_t control_print_error(fl_print_t * const print, const f_string_t function) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    fll_error_print(print, F_status_set_fine(((control_main_t *) print->custom)->setting.state.status), function, fll_error_file_flag_fallback_e);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_
+
+#ifndef _di_control_print_error_file_
+  f_status_t control_print_error_file(fl_print_t * const print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    control_main_t * const main = (control_main_t *) print->custom;
+
+    fll_error_file_print(print, F_status_set_fine(main->setting.state.status), function, fll_error_file_flag_fallback_e, name, operation, type);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_file_
+
+#ifndef _di_control_print_error_packet_response_
+  f_status_t control_print_error_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    control_main_t * const main = (control_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QReceived error response for " CONTROL_action_s " '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable);
+    fl_print_format("%[' with status '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, string_status, print->set->notable);
+    fl_print_format("%[' (%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%ui%]", print->to, print->set->notable, header.status, print->set->notable);
+
+    if (header.length) {
+      fl_print_format("%[): %/Q%]%r", print->to, print->set->error, print->set->error, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+    }
+    else {
+      fl_print_format("%[).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+    }
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_packet_response_
+
+#ifndef _di_control_print_error_packet_response_failure_
+  f_status_t control_print_error_packet_response_failure(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    control_main_t * const main = (control_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe action '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable);
+    fl_print_format("%[' failed with status '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, string_status, print->set->notable);
+    fl_print_format("%[' (%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%ui%]", print->to, print->set->notable, header.status, print->set->notable);
+
+    if (header.length) {
+      fl_print_format("%[): %/Q%]%r", print->to, print->set->error, print->set->error, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+    }
+    else {
+      fl_print_format("%[).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+    }
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_packet_response_failure_
+
+#ifndef _di_control_print_error_parameter_actions_none_
+  f_status_t control_print_error_parameter_actions_none(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("%[%QNo actions provided.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_actions_none_
+
+#ifndef _di_control_print_error_parameter_action_not_
+  f_status_t control_print_error_parameter_action_not(fl_print_t * const print, const f_string_static_t action) {
+
+    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 parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' is not a known controller action.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_not_
+
+#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
+  f_status_t control_print_error_parameter_action_rule_basename_empty(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' a rule base name cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_basename_empty_
+
+#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
+  f_status_t control_print_error_parameter_action_rule_directory_empty(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_directory_empty_
+
+#ifndef _di_control_print_error_parameter_action_rule_empty_
+  f_status_t control_print_error_parameter_action_rule_empty(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' a rule name cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_empty_
+
+#ifndef _di_control_print_error_parameter_action_rule_not_
+  f_status_t control_print_error_parameter_action_rule_not(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_not_
+
+#ifndef _di_control_print_error_parameter_action_rule_too_few_
+  f_status_t control_print_error_parameter_action_rule_too_few(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' has too few arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_few_
+
+#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
+  f_status_t control_print_error_parameter_action_rule_too_few_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' when used with '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable);
+    fl_print_format("%[' has too few arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_few_with_
+
+#ifndef _di_control_print_error_parameter_action_rule_too_many_
+  f_status_t control_print_error_parameter_action_rule_too_many(fl_print_t * const print, const f_string_static_t action) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' has too many arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_many_
+
+#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
+  f_status_t control_print_error_parameter_action_rule_too_many_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' when used with '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable);
+    fl_print_format("%[' has too many arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_many_with_
+
+#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
+  f_status_t control_print_error_parameter_action_rule_with_unknown(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) {
+
+    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 action parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable);
+    fl_print_format("%[' does not know the argument '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable);
+    fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_action_rule_with_unknown_
+
+#ifndef _di_control_print_error_parameter_value_empty_
+  f_status_t control_print_error_parameter_value_empty(fl_print_t * const print, const f_string_static_t parameter) {
+
+    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 value for the parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, parameter, print->set->notable);
+    fl_print_format("%[' must not be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_value_empty_
+
+#ifndef _di_control_print_error_parameter_value_not_
+  f_status_t control_print_error_parameter_value_not(fl_print_t * const print, const f_string_static_t parameter) {
+
+    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 parameter '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, parameter, print->set->notable);
+    fl_print_format("%[' is specified, but no value is given.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_parameter_value_not_
+
+#ifndef _di_control_print_error_pipe_supported_not_
+  f_status_t control_print_error_pipe_supported_not(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("%[%QPipe input is not supported by this program.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_pipe_supported_not_
+
+#ifndef _di_control_print_error_response_packet_valid_not_
+  f_status_t control_print_error_response_packet_valid_not(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 received response is not a valid or supported packet.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_response_packet_valid_not_
+
+#ifndef _di_control_print_error_request_packet_too_large_
+  f_status_t control_print_error_request_packet_too_large(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 generated packet is too large, cannot send packet.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_request_packet_too_large_
+
+#ifndef _di_control_print_error_socket_file_failed_
+  f_status_t control_print_error_socket_file_failed(fl_print_t * const print, const f_string_static_t path_socket) {
+
+    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("%[%QFailed to connect to the socket file '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable);
+    fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_socket_file_failed_
+
+#ifndef _di_control_print_error_socket_file_missing_
+  f_status_t control_print_error_socket_file_missing(fl_print_t * const print, const f_string_static_t path_socket) {
+
+    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 controller socket file '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable);
+    fl_print_format("%[' could not be found and is required.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_socket_file_missing_
+
+#ifndef _di_control_print_error_socket_file_not_
+  f_status_t control_print_error_socket_file_not(fl_print_t * const print, const f_string_static_t path_socket) {
+
+    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 controller socket file '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable);
+    fl_print_format("%[' is not a socket file.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_error_socket_file_not_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/print/error.h b/level_3/control/c/main/print/error.h
new file mode 100644 (file)
index 0000000..08ace68
--- /dev/null
@@ -0,0 +1,492 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print error functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_print_error_h
+#define _control_print_error_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print generic error message regarding a function failing in some way.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_print()
+ */
+#ifndef _di_control_print_error_
+  extern f_status_t control_print_error(fl_print_t * const print, const f_string_t function);
+#endif // _di_control_print_error_
+
+/**
+ * Print file related error or warning messages.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param function
+ *   The name of the function where the error happened.
+ *   Set to 0 to disable.
+ * @param name
+ *   The name of the file or directory.
+ * @param operation
+ *   The operation that fails, such as 'create' or 'access'.
+ * @param type
+ *   A valid file type code from the fll_error_file_type enum.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_file_print()
+ */
+#ifndef _di_control_print_error_file_
+  extern f_status_t control_print_error_file(fl_print_t * const print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type);
+#endif // _di_control_print_error_file_
+
+/**
+ * Print an error from the packet response.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param header
+ *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_packet_response_
+  extern f_status_t control_print_error_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t status);
+#endif // _di_control_print_error_packet_response_
+
+/**
+ * Print a error about a packet response failure.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param header
+ *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_packet_response_failure_
+  extern f_status_t control_print_error_packet_response_failure(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status);
+#endif // _di_control_print_error_packet_response_failure_
+/**
+ * Print an error message about no actions being provided.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_actions_none_
+  extern f_status_t control_print_error_parameter_actions_none(fl_print_t * const print);
+#endif // _di_control_print_error_parameter_actions_none_
+
+/**
+ * Print an error message about the given parameter not matching the known set of controller actions.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_not_
+  extern f_status_t control_print_error_parameter_action_not(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_not_
+
+/**
+ * Print an error message about the given parameter being a rule action having an empty rule basename.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
+  extern f_status_t control_print_error_parameter_action_rule_basename_empty(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_basename_empty_
+
+/**
+ * Print an error message about the given parameter being a rule action having an empty rule directory path.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
+  extern f_status_t control_print_error_parameter_action_rule_directory_empty(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_directory_empty_
+
+/**
+ * Print an error message about the given parameter being a rule action having an empty rule name.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_empty_
+  extern f_status_t control_print_error_parameter_action_rule_empty(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_empty_
+
+/**
+ * Print an error message about the given parameter being a rule action but no rule name is specified.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_not_
+  extern f_status_t control_print_error_parameter_action_rule_not(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_not_
+
+/**
+ * Print an error message about the given parameter being a rule action having too few arguments passed.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_few_
+  extern f_status_t control_print_error_parameter_action_rule_too_few(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_too_few_
+
+/**
+ * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with".
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
+  extern f_status_t control_print_error_parameter_action_rule_too_few_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with);
+#endif // _di_control_print_error_parameter_action_rule_too_few_with_
+
+/**
+ * Print an error message about the given parameter being a rule action having too many arguments passed.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_many_
+  extern f_status_t control_print_error_parameter_action_rule_too_many(fl_print_t * const print, const f_string_static_t action);
+#endif // _di_control_print_error_parameter_action_rule_too_many_
+
+/**
+ * Print an error message about the given parameter being a rule action having too many arguments passed for a given "with".
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
+  extern f_status_t control_print_error_parameter_action_rule_too_many_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with);
+#endif // _di_control_print_error_parameter_action_rule_too_many_with_
+/**
+ * Print an error message about the given parameter being unknown for the use with the given action.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
+  extern f_status_t control_print_error_parameter_action_rule_with_unknown(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with);
+#endif // _di_control_print_error_parameter_action_rule_with_unknown_
+
+/**
+ * Print an error message about the parameter's associated value being an empty string.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param parameter
+ *   The parameter name.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_value_empty_
+  extern f_status_t control_print_error_parameter_value_empty(fl_print_t * const print, const f_string_static_t parameter);
+#endif // _di_control_print_error_parameter_value_empty_
+
+/**
+ * Print an error message about the parameter missings its associated value.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param parameter
+ *   The parameter name.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_parameter_value_not_
+  extern f_status_t control_print_error_parameter_value_not(fl_print_t * const print, const f_string_static_t parameter);
+#endif // _di_control_print_error_parameter_value_not_
+
+/**
+ * Print an error message about a pipe input being unsupported.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_pipe_supported_not_
+  extern f_status_t control_print_error_pipe_supported_not(fl_print_t * const print);
+#endif // _di_control_print_error_pipe_supported_not_
+
+/**
+ * Print an error message about the response packet format either being invalid or not supported.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_response_packet_valid_not_
+  extern f_status_t control_print_error_response_packet_valid_not(fl_print_t * const print);
+#endif // _di_control_print_error_response_packet_valid_not_
+
+/**
+ * Print an error message about the request packet being too large.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_request_packet_too_large_
+  extern f_status_t control_print_error_request_packet_too_large(fl_print_t * const print);
+#endif // _di_control_print_error_request_packet_too_large_
+
+/**
+ * Print an error message about failure to connect to the socket file.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param path_socket
+ *   The socket file path.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_socket_file_failed_
+  extern f_status_t control_print_error_socket_file_failed(fl_print_t * const print, const f_string_static_t path_socket);
+#endif // _di_control_print_error_socket_file_failed_
+
+/**
+ * Print an error message about the socket file not being found.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param path_socket
+ *   The socket file path.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_socket_file_missing_
+  extern f_status_t control_print_error_socket_file_missing(fl_print_t * const print, const f_string_static_t path_socket);
+#endif // _di_control_print_error_socket_file_missing_
+
+/**
+ * Print an error message about the socket file not actually being a socket file.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param path_socket
+ *   The socket file path.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_error_socket_file_not_
+  extern f_status_t control_print_error_socket_file_not(fl_print_t * const print, const f_string_static_t path_socket);
+#endif // _di_control_print_error_socket_file_not_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_print_error_h
diff --git a/level_3/control/c/main/print/message.c b/level_3/control/c/main/print/message.c
new file mode 100644 (file)
index 0000000..2cd0d9a
--- /dev/null
@@ -0,0 +1,82 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_print_message_help_
+  f_status_t control_print_message_help(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
+    f_file_stream_lock(print->to);
+
+    fll_program_print_help_header(print, control_program_name_long_s, control_program_version_s);
+
+    fll_program_print_help_option_standard(print);
+
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    fll_program_print_help_option(print, control_short_name_s, control_long_name_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "    Specify the name of the controller socket file.");
+    fll_program_print_help_option(print, control_short_return_s, control_long_return_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "  Print a message about the response packet.");
+    fll_program_print_help_option(print, control_short_settings_s, control_long_settings_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Specify a directory path or a full path to the control settings file.");
+    fll_program_print_help_option(print, control_short_socket_s, control_long_socket_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "  Specify a directory path or a full path to the controller socket file.");
+
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    fll_program_print_help_usage(print, control_program_name_s, control_action_s);
+
+    fl_print_format("%r  When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", print->to, f_string_eol_s, print->set->notable, f_console_symbol_long_normal_s, control_long_socket_s, print->set->notable);
+    fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, control_long_name_s, print->set->notable, f_string_eol_s, f_string_eol_s);
+
+    fl_print_format("  A rule action allows for either the full rule path, such as '%[boot/root%]'", print->to, print->set->notable, print->set->notable);
+    fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", print->to, print->set->notable, print->set->notable);
+    fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", print->to, print->set->notable, print->set->notable, f_string_eol_s, f_string_eol_s);
+
+    fl_print_format("  The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", print->to, print->set->notable, f_console_symbol_long_normal_s, control_long_return_s, print->set->notable, f_string_eol_s);
+    fl_print_format("  Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", print->to, print->set->notable, f_console_symbol_long_inverse_s, f_console_standard_long_quiet_s, print->set->notable, f_string_eol_s);
+    fl_print_format("  No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", print->to, f_string_eol_s);
+
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_message_help_
+
+#ifndef _di_control_print_message_packet_response_
+  f_status_t control_print_message_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_normal_e) return F_output_not;
+
+    control_main_t * const main = (control_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("The action '", print->to);
+    fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable);
+
+    if (header.status == F_done) {
+      fl_print_format("' is performed", print->to);
+    }
+    else {
+      fl_print_format("' is successfully performed", print->to);
+    }
+
+    if (header.length) {
+      fl_print_format(": %/Q%r", print->to, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+    }
+    else {
+      fl_print_format(".%r", print->to, f_string_eol_s);
+    }
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_message_packet_response_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/print/message.h b/level_3/control/c/main/print/message.h
new file mode 100644 (file)
index 0000000..9cbf157
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_print_message_h
+#define _control_print_message_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print help.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see f_file_stream_flush()
+ * @see f_file_stream_lock()
+ * @see f_file_stream_unlock()
+ * @see f_print_dynamic_raw()
+ * @see fl_print_format()
+ *
+ * @see fll_program_print_help_header()
+ * @see fll_program_print_help_option()
+ * @see fll_program_print_help_option_standard()
+ * @see fll_program_print_help_usage()
+ */
+#ifndef _di_control_print_message_help_
+  extern f_status_t control_print_message_help(fl_print_t * const print);
+#endif // _di_control_print_message_help_
+
+/**
+ * Print a message about a packet response.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param header
+ *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_message_packet_response_
+  extern f_status_t control_print_message_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status);
+#endif // _di_control_print_message_packet_response_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_print_message_h
diff --git a/level_3/control/c/main/print/warning.c b/level_3/control/c/main/print/warning.c
new file mode 100644 (file)
index 0000000..75eb4d7
--- /dev/null
@@ -0,0 +1,65 @@
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_control_print_warning_packet_header_duplicate_object_
+  f_status_t control_print_warning_packet_header_duplicate_object(fl_print_t * const print, const f_string_static_t response_header) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe received response header '%]", print->to, print->set->warning, print->prefix, print->set->warning);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, response_header, print->set->notable);
+    fl_print_format("%[' is repeated.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_warning_packet_header_duplicate_object_
+
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+  f_status_t control_print_warning_packet_process_string_to_failed(fl_print_t * const print, const f_status_t status_of, const f_status_t status_error) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QFailed while calling f_status_string_to() for status%] ", print->to, print->set->warning, print->set->warning, print->set->warning);
+    fl_print_format("%[%ui%]", print->to, print->set->notable, status_of, print->set->notable);
+    fl_print_format("%[, failing with status code%] ", print->to, print->set->warning, status_error, print->set->warning);
+    fl_print_format("%[%ui%]", print->to, print->set->notable, status_error, print->set->notable);
+    fl_print_format("%[.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_warning_packet_process_string_to_failed_
+
+#ifndef _di_control_print_warning_packet_response_busy_
+  f_status_t control_print_warning_packet_response_busy(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) {
+
+    if (!print) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe action '%]", print->to, print->set->warning, print->prefix, print->set->warning);
+    fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable);
+    fl_print_format("%[' could not be performed because the service is busy.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_control_print_warning_packet_response_busy_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/print/warning.h b/level_3/control/c/main/print/warning.h
new file mode 100644 (file)
index 0000000..847632d
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_print_warning_h
+#define _control_print_warning_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print a warning message about a response header being repeated (when debugging).
+ *
+ * This program currently does not support multiple headers for any given valid header Object.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param response_header
+ *   The repeated response header.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_warning_packet_header_duplicate_object_
+  extern f_status_t control_print_warning_packet_header_duplicate_object(fl_print_t * const print, const f_string_static_t response_header);
+#endif // _di_control_print_warning_packet_header_duplicate_object_
+
+/**
+ * Print a warning message about a failure when calling f_status_string_to().
+ *
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param status_of
+ *   The status code to be translating to a string.
+ * @param status_error
+ *   The status code representing the failure status returned by f_status_string_to().
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see f_status_string_to()
+ */
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+  extern f_status_t control_print_warning_packet_process_string_to_failed(fl_print_t * const print, const f_status_t status_of, const f_status_t status_error);
+#endif // _di_control_print_warning_packet_process_string_to_failed_
+
+/**
+ * Print a warning about a packet response returning as busy.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param header
+ *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ */
+#ifndef _di_control_print_warning_packet_response_busy_
+  extern f_status_t control_print_warning_packet_response_busy(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status);
+#endif // _di_control_print_warning_packet_response_busy_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_print_warning_h
diff --git a/level_3/control/c/main/process.c b/level_3/control/c/main/process.c
new file mode 100644 (file)
index 0000000..0c95daf
--- /dev/null
@@ -0,0 +1,9 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/process.h b/level_3/control/c/main/process.h
new file mode 100644 (file)
index 0000000..0eda87d
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * 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 _control_process_h
+#define _control_process_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_process_h
diff --git a/level_3/control/c/main/signal.c b/level_3/control/c/main/signal.c
new file mode 100644 (file)
index 0000000..2354590
--- /dev/null
@@ -0,0 +1,111 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_control_signal_check_) && defined(_di_thread_support_)
+  f_status_t control_signal_check(control_main_t * const main) {
+
+    if (!main || main->program.signal.id == -1) return F_false;
+
+    if (!((++main->program.signal_check) % control_signal_check_d)) {
+      if (fll_program_standard_signal_received(&main->program)) {
+        fll_program_print_signal_received(&main->program.warning, main->program.signal_received);
+
+        main->setting.state.status = F_status_set_error(F_interrupt);
+
+        return F_true;
+      }
+
+      main->program.signal_check = 0;
+    }
+
+    return F_false;
+  }
+#endif // !defined(_di_control_signal_check_) && defined(_di_thread_support_)
+
+#if !defined(_di_control_signal_check_) && !defined(_di_thread_support_)
+  f_status_t control_signal_check(control_main_t * const main) {
+
+    if (!main || main->program.signal.id == -1) return F_false;
+
+    if (main->program.signal_received) {
+      fll_program_print_signal_received(&main->program.warning, main->program.signal_received);
+
+      main->setting.state.status = F_status_set_error(F_interrupt);
+
+      return F_true;
+    }
+
+    return F_false;
+  }
+#endif // !defined(_di_control_signal_check_) && !defined(_di_thread_support_)
+
+#if !defined(_di_control_signal_handler_) && !defined(_di_thread_support_)
+  void control_signal_handler(control_main_t * const main) {
+
+    if (!main) return;
+
+    siginfo_t information;
+    f_number_unsigned_t failsafe = 0;
+
+    memset(&information, 0, sizeof(siginfo_t));
+
+    main->program.signal_received = 0;
+
+    f_signal_set_empty(&main->program.signal.set);
+    f_signal_set_add(F_signal_abort, &main->program.signal.set);
+    f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_add(F_signal_hangup, &main->program.signal.set);
+    f_signal_set_add(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_add(F_signal_quit, &main->program.signal.set);
+    f_signal_set_add(F_signal_termination, &main->program.signal.set);
+
+    if (main->program.signal.id == -1) {
+      main->setting.status_signal = f_signal_open(&main->program.signal);
+
+      if (F_status_is_error(main->setting.status_signal)) {
+        main->program.signal_received = F_signal_abort;
+
+        return;
+      }
+    }
+
+    do {
+      memset(&information, 0, sizeof(siginfo_t));
+
+      main->setting.status_signal = f_signal_wait(&main->program.signal.set, &information);
+
+      if (F_status_is_error(main->setting.status_signal) && F_status_set_fine(main->setting.status_signal) != F_interrupt) {
+        if (++failsafe >= control_signal_check_failsafe_d) break;
+      }
+
+      switch (information.si_signo) {
+        case F_signal_abort:
+        case F_signal_broken_pipe:
+        case F_signal_hangup:
+        case F_signal_interrupt:
+        case F_signal_quit:
+        case F_signal_termination:
+          main->program.signal_received = information.si_signo;
+
+          break;
+      }
+
+      failsafe = 0;
+      main->setting.status_signal = F_none;
+
+    } while (!main->program.signal_received);
+
+    f_signal_close(&main->program.signal);
+
+    if (F_status_is_error(main->setting.status_signal)) {
+      main->program.signal_received = F_signal_abort;
+    }
+  }
+#endif // !defined(_di_control_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/signal.h b/level_3/control/c/main/signal.h
new file mode 100644 (file)
index 0000000..981706f
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides signal functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_signal_h
+#define _control_signal_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Check to see if a signal is received.
+ *
+ * If main.signal is non-zero, then this handles the following signals:
+ *   - F_signal_abort
+ *   - F_signal_broken_pipe
+ *   - F_signal_hangup
+ *   - F_signal_interrupt
+ *   - F_signal_quit
+ *   - F_signal_termination
+ *
+ * There is a threaded and a non-threaded version of this.
+ * The non-threaded version checks periodically using control_signal_check_d and updates main->signal_check as needed.
+ * The threaded version checks the flag state which is set by a separate thread that is blocking until signal is received.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   This does not alter main.setting.state.status.
+ *
+ * @return
+ *   F_true on signal received.
+ *   F_false otherwise.
+ *
+ * @see control_signal_handler()
+ *
+ * @see fll_program_standard_signal_received()
+ */
+#ifndef _di_control_signal_check_
+  extern f_status_t control_signal_check(control_main_t * const main);
+#endif // _di_control_signal_check_
+
+/**
+ * Signal handler for signals/interrupts.
+ *
+ * This blocks until an expected signal is recieved.
+ * When an expected signal is received it then sets the
+ *
+ * If main.signal is non-zero, then this handles the following signals:
+ *   - F_signal_abort
+ *   - F_signal_broken_pipe
+ *   - F_signal_hangup
+ *   - F_signal_interrupt
+ *   - F_signal_quit
+ *   - F_signal_termination
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   This alters main.program.signal_received, setting it to a received signal.
+ *
+ *   This alters main.setting.state.status:
+ *     Errors (with error bit) from: f_signal_open()
+ *     Errors (with error bit) from: f_signal_wait()
+ *
+ * @see f_signal_close()
+ * @see f_signal_open()
+ * @see f_signal_wait()
+ */
+#if !defined(_di_control_signal_handler_) && !defined(_di_thread_support_)
+  extern void control_signal_handler(control_main_t * const main);
+#endif // !defined(_di_control_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_signal_h
diff --git a/level_3/control/c/main/thread.c b/level_3/control/c/main/thread.c
new file mode 100644 (file)
index 0000000..b859f7a
--- /dev/null
@@ -0,0 +1,26 @@
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_control_thread_signal_) && !defined(_di_thread_support_)
+  void * control_thread_signal(void * const main) {
+
+    f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+    if (main) {
+      control_signal_handler((control_main_t *) main);
+    }
+
+    return 0;
+  }
+#endif // !defined(_di_control_thread_signal_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/control/c/main/thread.h b/level_3/control/c/main/thread.h
new file mode 100644 (file)
index 0000000..22212e7
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Control
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides thread functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _control_thread_h
+#define _control_thread_h
+
+/**
+ * Thread handler for signals/interrupts.
+ *
+ * If main.signal is non-zero, then this handles the following signals:
+ *   - F_signal_abort
+ *   - F_signal_broken_pipe
+ *   - F_signal_hangup
+ *   - F_signal_interrupt
+ *   - F_signal_quit
+ *   - F_signal_termination
+ *
+ * @param main
+ *   The program and settings data.
+ *
+ *   Must be of type control_main_t.
+ *
+ * @return
+ *   0, always.
+ *
+ * @see f_thread_cancel_state_set()
+ *
+ * @see control_signal_handler()
+ */
+#if !defined(_di_control_thread_signal_) && !defined(_di_thread_support_)
+  extern void * control_thread_signal(void * const main);
+#endif // !defined(_di_control_thread_signal_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _control_thread_h
diff --git a/level_3/control/c/print.c b/level_3/control/c/print.c
deleted file mode 100644 (file)
index 04031ad..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "control.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_control_print_help_
-  f_status_t control_print_help(control_setting_t * const setting, const fl_print_t print) {
-
-    f_file_stream_lock(print.to);
-
-    fll_program_print_help_header(print, control_program_name_long_s, control_program_version_s);
-
-    fll_program_print_help_option_standard(main->output.to, context);
-
-    f_print_dynamic_raw(f_string_eol_s, main->output.to);
-
-    fll_program_print_help_option(print, control_short_name_s, control_long_name_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "    Specify the name of the controller socket file.");
-    fll_program_print_help_option(print, control_short_return_s, control_long_return_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "  Print a message about the response packet.");
-    fll_program_print_help_option(print, control_short_settings_s, control_long_settings_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Specify a directory path or a full path to the control settings file.");
-    fll_program_print_help_option(print, control_short_socket_s, control_long_socket_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "  Specify a directory path or a full path to the controller socket file.");
-
-    f_print_dynamic_raw(f_string_eol_s, print.to);
-    f_print_dynamic_raw(f_string_eol_s, print.to);
-
-    fll_program_print_help_usage(print, control_program_name_s, control_action_s);
-
-    fl_print_format("%r  When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", print.to, f_string_eol_s, print.set->notable, f_console_symbol_long_normal_s, control_long_socket_s, print.set->notable);
-    fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", print.to, print.set->notable, f_console_symbol_long_normal_s, control_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s);
-
-    fl_print_format("  A rule action allows for either the full rule path, such as '%[boot/root%]'", print.to, print.set->notable, print.set->notable);
-    fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", print.to, print.set->notable, print.set->notable);
-    fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", print.to, print.set->notable, print.set->notable, f_string_eol_s, f_string_eol_s);
-
-    fl_print_format("  The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", print.to, print.set->notable, f_console_symbol_long_normal_s, control_long_return_s, print.set->notable, f_string_eol_s);
-    fl_print_format("  Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", print.to, print.set->notable, f_console_symbol_long_inverse_s, f_console_standard_long_quiet_s, print.set->notable, f_string_eol_s);
-    fl_print_format("  No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", print.to, f_string_eol_s);
-
-    f_file_stream_flush(print.to);
-    f_file_stream_unlock(print.to);
-
-    return F_none;
-  }
-#endif // _di_control_print_help_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/control/c/print.h b/level_3/control/c/print.h
deleted file mode 100644 (file)
index e46b5a4..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Control
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _control_print_h
-#define _control_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print help.
- *
- * @param setting
- *   The main program settings.
- *
- *   This does not alter setting.state.status.
- * @param print
- *   The output structure to print to.
- *
- * @return
- *   F_none on success.
- *   F_output_not on success, but no printing is performed.
- */
-#ifndef _di_control_print_help_
-  extern f_status_t control_print_help(control_setting_t * const setting, const fl_print_t print);
-#endif // _di_control_print_help_control
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _control_print_h
diff --git a/level_3/control/c/private-control.c b/level_3/control/c/private-control.c
deleted file mode 100644 (file)
index 43868e3..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-#include "control.h"
-#include "private-common.h"
-#include "private-control.h"
-#include "private-print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_control_action_verify_
-  f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) {
-
-    switch (data->action) {
-      case control_action_type_freeze_e:
-      case control_action_type_kill_e:
-      case control_action_type_pause_e:
-      case control_action_type_reload_e:
-      case control_action_type_rerun_e:
-      case control_action_type_restart_e:
-      case control_action_type_resume_e:
-      case control_action_type_start_e:
-      case control_action_type_stop_e:
-      case control_action_type_thaw_e:
-        if (main->parameters.remaining.used < 3) {
-          control_print_error_parameter_action_rule_not(main, data->argv[main->parameters.remaining.array[0]]);
-
-          return F_status_set_error(F_parameter);
-        }
-
-        if (main->parameters.remaining.used > 3) {
-          if (f_compare_dynamic(control_at_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
-            if (main->parameters.remaining.used < 5) {
-              control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
-
-              return F_status_set_error(F_parameter);
-            }
-
-            if (main->parameters.remaining.used > 5) {
-              control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
-
-              return F_status_set_error(F_parameter);
-            }
-          }
-          else if (f_compare_dynamic(control_in_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
-            if (main->parameters.remaining.used < 6) {
-              control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s);
-
-              return F_status_set_error(F_parameter);
-            }
-          }
-          else if (f_compare_dynamic(control_now_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
-            if (main->parameters.remaining.used > 4) {
-              control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s);
-
-              return F_status_set_error(F_parameter);
-            }
-          }
-          else {
-            control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[2]]);
-
-            return F_status_set_error(F_parameter);
-          }
-        }
-
-        if (!data->argv[main->parameters.remaining.array[1]].used) {
-          if (main->parameters.remaining.used == 3) {
-            control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]);
-          }
-          else {
-            control_print_error_parameter_action_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]);
-          }
-
-          return F_status_set_error(F_parameter);
-        }
-
-        if (main->parameters.remaining.used == 3) {
-          if (!data->argv[main->parameters.remaining.array[2]].used) {
-            control_print_error_parameter_action_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]);
-
-            return F_status_set_error(F_parameter);
-          }
-        }
-
-        return F_none;
-
-      case control_action_type_kexec_e:
-      case control_action_type_reboot_e:
-      case control_action_type_shutdown_e:
-        if (main->parameters.remaining.used < 2) {
-          control_print_error_parameter_action_rule_too_few(main, data->argv[main->parameters.remaining.array[0]]);
-
-          return F_status_set_error(F_parameter);
-        }
-
-        if (f_compare_dynamic(control_at_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
-          if (main->parameters.remaining.used < 3) {
-            control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
-
-            return F_status_set_error(F_parameter);
-          }
-
-          if (main->parameters.remaining.used > 3) {
-            control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
-
-            return F_status_set_error(F_parameter);
-          }
-        }
-        else if (f_compare_dynamic(control_in_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
-          if (main->parameters.remaining.used < 4) {
-            control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s);
-
-            return F_status_set_error(F_parameter);
-          }
-        }
-        else if (f_compare_dynamic(control_now_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
-          if (main->parameters.remaining.used > 2) {
-            control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s);
-
-            return F_status_set_error(F_parameter);
-          }
-        }
-        else {
-          control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[1]]);
-
-          return F_status_set_error(F_parameter);
-        }
-    }
-
-    return F_none;
-  }
-#endif // _di_control_action_verify_
-
-#ifndef _di_control_packet_build_
-  f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) {
-
-    data->cache.packet.used = 0;
-    data->cache.large.used = 0;
-    data->cache.small.used = 0;
-
-    f_number_unsigned_t i = 0;
-    f_status_t status = F_none;
-
-    {
-      f_number_unsigned_t length = 5 + f_fss_header_s.used + f_fss_payload_s.used;
-      length += control_action_s.used + control_length_s.used + control_type_s.used;
-      length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2;
-      length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3;
-      length += data->argv[main->parameters.remaining.array[0]].used + f_string_ascii_0_s.used;
-
-      // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length.
-      for (i = 1; i < main->parameters.remaining.used; ++i) {
-        length += f_fss_payload_header_next_s.used + data->argv[main->parameters.remaining.array[i]].used;
-      } // for
-
-      if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) {
-        length += control_init_s.used;
-      }
-      else {
-        length += control_controller_s.used;
-      }
-
-      if (length > 0xffffffffu) {
-        return F_status_set_error(F_too_large);
-      }
-
-      status = f_string_dynamic_resize(length, &data->cache.packet);
-      if (F_status_is_error(status)) return status;
-    }
-
-    const f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0);
-
-    f_string_static_t contents_array[main->parameters.remaining.used];
-    f_string_statics_t contents = macro_f_string_statics_t_initialize_1(contents_array, 0, main->parameters.remaining.used);
-
-    // The Packet Control Block.
-    {
-      f_char_t block_control = (f_char_t) control_packet_flag_binary_d;
-
-      #ifdef _is_F_endian_big
-        block_control |= (f_char_t) control_packet_flag_endian_big_d;
-      #endif // _is_F_endian_big
-
-      status = f_string_append(&block_control, 1, &data->cache.packet);
-      if (F_status_is_error(status)) return status;
-    }
-
-    // Reserve the Packet Size Block to be calculated later.
-    data->cache.packet.used = 5;
-
-    // Payload Header: type.
-    if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) {
-      contents_array[0] = control_init_s;
-    }
-    else {
-      contents_array[0] = control_controller_s;
-    }
-
-    contents.used = 1;
-
-    status = fll_fss_extended_write(control_type_s, contents, 0, state, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    // Payload Header: action.
-    for (contents.used = 0; contents.used < main->parameters.remaining.used; ++contents.used) {
-      contents_array[contents.used] = data->argv[main->parameters.remaining.array[contents.used]];
-    } // for
-
-    status = fll_fss_extended_write(control_action_s, contents, 0, state, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    // Payload Header: length.
-    contents_array[0] = f_string_ascii_0_s;
-    contents.used = 1;
-
-    status = fll_fss_extended_write(control_length_s, contents, 0, state, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    // Payload Packet: Header.
-    status = fll_fss_payload_write(f_fss_header_s, data->cache.large, F_false, 0, state, &data->cache.packet);
-    if (F_status_is_error(status)) return status;
-
-    // Payload Packet: Payload.
-    data->cache.large.used = 0;
-
-    status = fll_fss_payload_write(f_fss_payload_s, data->cache.large, F_false, 0, state, &data->cache.packet);
-    if (F_status_is_error(status)) return status;
-
-    // Construct Packet Size Block.
-    #ifdef _is_F_endian_big
-      data->cache.packet.string[1] = data->cache.packet.used & 0xffu;
-      data->cache.packet.string[2] = data->cache.packet.used & 0xff00u;
-      data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u;
-      data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u;
-    #else
-      data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u;
-      data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u;
-      data->cache.packet.string[3] = data->cache.packet.used & 0xff00u;
-      data->cache.packet.string[4] = data->cache.packet.used & 0xffu;
-    #endif // _is_F_endian_big
-
-    return F_none;
-  }
-#endif // _di_control_packet_build_
-
-#ifndef _di_control_packet_header_flag_
-  uint8_t control_packet_header_flag(const uint8_t buffer[]) {
-    return (uint8_t) (((buffer[0] & 0x8u) ? control_packet_flag_binary_d : 0) | ((buffer[0] & 0x4u) ? control_packet_flag_endian_big_d : 0));
-  }
-#endif // _di_control_packet_header_flag_
-
-#ifndef _di_control_packet_header_length_
-  uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) {
-
-    #ifdef _is_F_endian_big
-      if (is_big) {
-        return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
-      }
-    #else
-      if (!is_big) {
-        return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
-      }
-    #endif // _is_F_endian_big
-
-    return (buffer[4] << 24u) | (buffer[3] << 16u) | (buffer[2] << 8u) | buffer[1];
-  }
-#endif // _di_control_packet_header_length_
-
-#ifndef _di_control_packet_receive_
-  f_status_t control_packet_receive(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) {
-
-    data->cache.large.used = 0;
-    data->cache.small.used = 0;
-    data->cache.packet.used = 0;
-    data->cache.packet_objects.used = 0;
-    data->cache.packet_contents.used = 0;
-    data->cache.header_objects.used = 0;
-    data->cache.header_contents.used = 0;
-    data->cache.delimits.used = 0;
-
-    header->action = 0;
-    header->type = 0;
-    header->status = F_none;
-    header->length = 0;
-
-    f_status_t status = F_none;
-    f_number_unsigned_t i = 0;
-    f_string_range_t range_header = f_string_range_t_initialize;
-    f_string_range_t range_payload = f_string_range_t_initialize;
-
-    {
-      f_number_unsigned_t length = 5;
-      uint8_t head[length];
-
-      memset(head, 0, sizeof(uint8_t) * length);
-
-      status = f_socket_read(&data->socket, f_socket_flag_peek_e, (void *) head, &length);
-      if (F_status_is_error(status)) return status;
-      if (length < 5) return F_status_set_error(F_packet_not);
-
-      // Only the first two bits of the 8 Control bits are allowed to be set to 1 for this Packet.
-      if (head[0] & (~(control_packet_flag_binary_d | control_packet_flag_endian_big_d))) {
-        return F_status_set_error(F_packet_not);
-      }
-
-      length = control_packet_header_length(head[0] & control_packet_flag_endian_big_d, head);
-
-      if (length > 0xffffffffu) {
-        return F_status_set_error(F_too_large);
-      }
-
-      status = f_string_dynamic_increase_by(length, &data->cache.large);
-      if (F_status_is_error(status)) return status;
-
-      status = f_socket_read(&data->socket, f_socket_flag_wait_all_e, (void *) head, &length);
-      if (F_status_is_error(status)) return status;
-      if (length < data->cache.large.used) return F_status_set_error(F_too_small);
-      if (length > data->cache.large.used) return F_status_set_error(F_too_large);
-    }
-
-    {
-      f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0);
-      f_string_range_t range_packet = macro_f_string_range_t_initialize_2(data->cache.large.used);
-
-      status = fll_fss_basic_list_read(data->cache.large, state, &range_packet, &data->cache.packet_objects, &data->cache.packet_contents, &data->cache.delimits, 0, 0);
-
-      if (F_status_is_error(status)) {
-        control_print_debug_packet_message(main, "Failure while reading FSS Basic List in the response packet", 0, 0, &status);
-
-        if (F_status_set_fine(status) == F_memory_not) {
-          return status;
-        }
-
-        return F_status_set_error(F_header);
-      }
-
-      status = f_fss_apply_delimit(state, data->cache.delimits, &data->cache.large);
-
-      if (F_status_is_error(status)) {
-        control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status);
-
-        return F_status_set_error(F_header);
-      }
-
-      data->cache.delimits.used = 0;
-
-      {
-        f_string_ranges_t *content_header = 0;
-        f_string_ranges_t *content_payload = 0;
-
-        for (; i < data->cache.packet_objects.used; ++i) {
-
-          if (f_compare_dynamic_partial_string(f_fss_header_s.string, data->cache.large, f_fss_header_s.used, data->cache.packet_objects.array[i]) == F_equal_to) {
-
-            // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs.
-            if (content_header) {
-              control_print_debug_packet_message(main, "Multiple %[" F_fss_header_s "%] found in response packet", 0, 0, 0);
-
-              return F_status_set_error(F_payload_not);
-            }
-
-            content_header = &data->cache.packet_contents.array[i];
-          }
-          else if (f_compare_dynamic_partial_string(f_fss_payload_s.string, data->cache.large, f_fss_payload_s.used, data->cache.packet_objects.array[i]) == F_equal_to) {
-
-            // Only a single "payload" is supported by the FSS-000E (Payload) standard.
-            if (content_payload) {
-              control_print_debug_packet_message(main, "Multiple %[" F_fss_payload_s "%] found in response packet", 0, 0, 0);
-
-              return F_status_set_error(F_payload_not);
-            }
-
-            if (i + 1 < data->cache.packet_contents.used) {
-              control_print_debug_packet_message(main, "Invalid FSS Payload format, the %[" F_fss_payload_s "%] is required to be the last FSS Basic List Object", 0, 0, 0);
-
-              return F_status_set_error(F_payload_not);
-            }
-
-            content_payload = &data->cache.packet_contents.array[i];
-          }
-        } // for
-
-        if (!content_header) {
-          control_print_debug_packet_message(main, "Did not find a %[" F_fss_header_s "%] in the response packet", 0, 0, 0);
-
-          return F_status_set_error(F_payload_not);
-        }
-
-        if (!content_payload) {
-          control_print_debug_packet_message(main, "Did not find a %[" F_fss_payload_s "%] in the response packet", 0, 0, 0);
-
-          return F_status_set_error(F_payload_not);
-        }
-
-        range_header = content_header->array[0];
-        range_payload = content_payload->array[0];
-      }
-
-      {
-        // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type.
-        uint8_t found = 0;
-        f_number_unsigned_t number = 0;
-        f_string_range_t range = range_header;
-
-        status = fll_fss_extended_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, 0, 0, &data->cache.delimits, 0);
-
-        if (F_status_is_error(status)) {
-          control_print_debug_packet_message(main, "Failure while reading FSS Extended in the response packet", 0, 0, &status);
-
-          if (F_status_set_fine(status) == F_memory_not) {
-            return status;
-          }
-
-          return F_status_set_error(F_header_not);
-        }
-
-        status = f_fss_apply_delimit(state, data->cache.delimits, &data->cache.large);
-
-        if (F_status_is_error(status)) {
-          control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status);
-
-          return F_status_set_error(F_header_not);
-        }
-
-        if (!data->cache.header_contents.used) {
-          control_print_debug_packet_message(main, "Did not find any Content within the %[" F_fss_header_s "%]", 0, 0, 0);
-
-          return F_status_set_error(F_header_not);
-        }
-
-        for (i = 0; i < data->cache.header_objects.used; ++i) {
-
-          if (f_compare_dynamic_partial_string(control_action_s.string, data->cache.large, control_action_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
-            if (!(found & 0x1)) {
-              const f_number_unsigned_t action_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1;
-              char action_string[action_length + 1];
-              const f_string_static_t action = macro_f_string_static_t_initialize_1(action_string, 0, action_length);
-
-              memcpy(action_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, action_length);
-              action_string[action_length] = 0;
-
-              found |= 0x1;
-
-              control_print_debug_packet_header_object_and_content(main, control_action_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
-
-              header->action = control_action_type_identify(action);
-
-              if (!header->action) {
-                control_print_debug_packet_message(main, "Failed to identify %[" CONTROL_action_s "%] from: ", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
-
-                return F_status_set_error(F_header_not);
-              }
-            }
-            else {
-              control_print_warning_packet_header_duplicate_object(main, control_action_s);
-            }
-          }
-          else if (f_compare_dynamic_partial_string(control_length_s.string, data->cache.large, control_length_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
-            if (!(found & 0x2)) {
-              found |= 0x2;
-              number = 0;
-
-              control_print_debug_packet_header_object_and_content(main, control_length_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
-
-              status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, data->cache.large, data->cache.header_contents.array[i].array[0], &number);
-
-              if (F_status_is_error(status)) {
-                control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_length_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
-
-                return F_status_set_error(F_header_not);
-              }
-
-              if (number > F_type_size_max_32_unsigned_d) {
-                control_print_debug_packet_message(main, "Processed number for %[" CONTROL_length_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
-
-                return F_status_set_error(F_header_not);
-              }
-
-              header->length = (uint16_t) number;
-            }
-            else {
-              control_print_warning_packet_header_duplicate_object(main, control_length_s);
-            }
-          }
-          else if (f_compare_dynamic_partial_string(control_status_s.string, data->cache.large, control_status_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
-            if (!(found & 0x4)) {
-              found |= 0x4;
-              number = 0;
-
-              control_print_debug_packet_header_object_and_content(main, control_status_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
-
-              // Attempt to get status as a number.
-              status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, data->cache.large, data->cache.header_contents.array[i].array[0], &number);
-
-              if (F_status_set_fine(status) == F_number) {
-
-                // Not a number, so attempt get by status string name.
-                const f_number_unsigned_t name_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1;
-                char name_string[name_length + 1];
-                const f_string_static_t name = macro_f_string_static_t_initialize_1(name_string, 0, name_length);
-
-                memcpy(name_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, name_length);
-                name_string[name_length] = 0;
-
-                status = fl_status_string_from(name, &header->status);
-
-                if (F_status_is_error(status)) {
-                  control_print_debug_packet_message(main, "Failed to process %[" CONTROL_status_s "%] in the response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
-
-                  return F_status_set_error(F_header_not);
-                }
-              }
-              else if (F_status_is_error(status)) {
-                control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_status_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
-
-                if (F_status_set_fine(status) == F_memory_not) {
-                  return status;
-                }
-
-                return F_status_set_error(F_header_not);
-              }
-              else {
-                if (number > F_status_size_max_with_bits_d) {
-                  control_print_debug_packet_message(main, "Processed number for %[" CONTROL_status_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
-
-                  return F_status_set_error(F_header_not);
-                }
-              }
-            }
-            else {
-              control_print_warning_packet_header_duplicate_object(main, control_length_s);
-            }
-          }
-          else if (f_compare_dynamic_partial_string(control_type_s.string, data->cache.large, control_type_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
-            if (!(found & 0x8)) {
-              found |= 0x8;
-
-              control_print_debug_packet_header_object_and_content(main, control_type_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
-
-              if (f_compare_dynamic_partial_string(control_controller_s.string, data->cache.large, control_controller_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) {
-                header->type = control_payload_type_controller_e;
-              }
-              else if (f_compare_dynamic_partial_string(control_error_s.string, data->cache.large, control_error_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) {
-                header->type = control_payload_type_error_e;
-              }
-              else {
-                control_print_debug_packet_message(main, "Unknown %[" CONTROL_type_s "%] in response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
-
-                return F_status_set_error(F_header_not);
-              }
-            }
-            else {
-              control_print_warning_packet_header_duplicate_object(main, control_type_s);
-            }
-          }
-        }
-      }
-    }
-
-    return F_none;
-  }
-#endif // _di_control_packet_receive_
-
-#ifndef _di_control_packet_process_
-  f_status_t control_packet_process(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) {
-
-    f_string_static_t string_status = f_string_static_t_initialize;
-
-    {
-      const f_status_t status = f_status_string_to(header->status, &string_status);
-
-      if (F_status_is_error(status)) {
-        control_print_warning_packet_process_string_to_failed(main, header->status, status);
-      }
-    }
-
-    if (main->parameters.array[control_parameter_return_e].result & f_console_result_found_e) {
-      fll_print_format("%rresponse %q %q %q%r", main->output.to, f_string_eol_s, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s);
-    }
-    else if (header->type == control_payload_type_error_e) {
-      control_print_error_packet_response(main, data, *header, string_status);
-    }
-    else if (header->status == F_failure || header->status == F_busy || header->status == F_done || header->status == F_success) {
-      control_print_controller_packet_response(main, data, *header, string_status);
-    }
-    else {
-
-      // Set type to 0 to inform the caller to handle this error.
-      header->type = 0;
-
-      return F_status_set_error(F_known_not);
-    }
-
-    if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) {
-      return F_status_set_error(header->status);
-    }
-
-    return header->status;
-  }
-#endif // _di_control_packet_process_
-
-#ifndef _di_control_packet_send_
-  f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) {
-
-    data->socket.size_write = data->cache.packet.used;
-
-    return f_socket_write(&data->socket, 0, (void *) &data->cache.packet, 0);
-  }
-#endif // _di_control_packet_send_
-
-#ifndef _di_control_settings_load_
-  f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) {
-
-    f_status_t status = F_none;
-
-    data->cache.small.used = 0;
-
-    if (main->parameters.array[control_parameter_settings_e].result & f_console_result_value_e) {
-      const f_number_unsigned_t index = main->parameters.array[control_parameter_settings_e].values.array[main->parameters.array[control_parameter_settings_e].values.used - 1];
-
-      status = f_string_dynamic_append(data->argv[index], &data->cache.small);
-    }
-    else {
-      status = f_string_dynamic_append(control_path_settings_s, &data->cache.small);
-    }
-
-    if (F_status_is_error(status)) {
-      fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
-
-      return status;
-    }
-
-    {
-      f_file_t file = f_file_t_initialize;
-
-      status = f_file_stream_open(data->cache.small, f_file_open_mode_read_s, &file);
-
-      if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_open_s, fll_error_file_type_file_e);
-
-        return status;
-      }
-
-      status = f_file_stream_read(file, &data->cache.large);
-
-      f_file_stream_flush(file);
-      f_file_stream_close(&file);
-
-      if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_read_s, fll_error_file_type_file_e);
-
-        return status;
-      }
-    }
-
-    f_state_t state = f_state_t_initialize;
-    f_string_range_t range = f_string_range_t_initialize;
-    f_string_ranges_t objects = f_string_ranges_t_initialize;
-    f_string_rangess_t contents = f_string_rangess_t_initialize;
-    f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
-
-    status = fll_fss_extended_read(data->cache.large, state, &range, &objects, &contents, 0, 0, &delimits, 0);
-
-    if (F_status_is_error(status)) {
-      fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_extended_read", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e);
-    }
-    else {
-      status = f_fss_apply_delimit(state, delimits, &data->cache.large);
-
-      if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "f_fss_apply_delimit", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e);
-      }
-    }
-
-    if (F_status_is_error_not(status)) {
-      uint8_t parameter_hass[] = { 0, 0, 0, 0 };
-
-      f_number_unsigned_t parameter_ats[] = { 0, 0, 0, 0 };
-
-      {
-        const f_string_static_t parameter_names[] = {
-          control_name_socket_s,
-          control_path_socket_s,
-          control_path_socket_prefix_s,
-          control_path_socket_suffix_s,
-        };
-
-        f_number_unsigned_t i = 0;
-        uint8_t j = 0;
-        f_string_range_t range = f_string_range_t_initialize;
-
-        for (; i < objects.used; ++i) {
-
-          for (j = 0; j < 4; ++j) {
-
-            range.stop = parameter_names[j].used - 1;
-
-            if (f_compare_dynamic_partial(parameter_names[j], data->cache.large, range, objects.array[i]) == F_equal_to) {
-              parameter_hass[j] = F_true;
-              parameter_ats[j] = i;
-
-              break;
-            }
-          } // for
-        } // for
-      }
-
-      data->cache.small.used = 0;
-
-      if (main->parameters.array[control_parameter_socket_e].result & f_console_result_value_e) {
-        const f_number_unsigned_t index = main->parameters.array[control_parameter_socket_e].values.array[main->parameters.array[control_parameter_socket_e].values.used - 1];
-
-        status = f_string_dynamic_append(data->argv[index], &data->cache.small);
-      }
-      else if (parameter_hass[1]) {
-        status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[parameter_ats[1]], &data->cache.small);
-      }
-      else {
-        status = f_string_dynamic_append(controller_path_socket_s, &data->cache.small);
-      }
-
-      if (F_status_is_error(status)) {
-        if (main->parameters.array[control_parameter_socket_e].result & f_console_result_value_e || !parameter_hass[1]) {
-          fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
-        }
-        else {
-          fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", fll_error_file_flag_fallback_e);
-        }
-      }
-
-      status = f_file_exists(data->cache.small, F_true);
-
-      if (F_status_is_error(status) || status == F_false) {
-        if (F_status_is_error(status)) {
-          fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e);
-
-          if (main->error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->error.to);
-          }
-        }
-
-        control_print_error_socket_file_missing(main, data->cache.small);
-
-        status = F_status_set_error(F_socket_not);
-      }
-
-      // Construct the file name when the socket path is a directory.
-      else if (f_file_is(data->cache.small, F_file_type_directory_d, F_true) == F_true) {
-        status = f_string_dynamic_append_assure(f_path_separator_s, &data->cache.small);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append_assure", fll_error_file_flag_fallback_e);
-        }
-        else {
-          uint8_t append_ids[] = {
-            0,
-            control_parameter_name_e,
-            0,
-          };
-
-          uint8_t append_hass[] = {
-            parameter_hass[2],
-            parameter_hass[0],
-            parameter_hass[3],
-          };
-
-          const f_string_static_t append_defaults[] = {
-            controller_path_socket_prefix_s,
-            controller_name_socket_s,
-            controller_path_socket_suffix_s,
-          };
-
-          for (uint8_t i = 0; i < 3; ++i) {
-
-            if (append_ids[i] && main->parameters.array[append_ids[i]].result & f_console_result_value_e) {
-              const f_number_unsigned_t index = main->parameters.array[append_ids[i]].values.array[main->parameters.array[append_ids[i]].values.used - 1];
-
-              status = f_string_dynamic_append(data->argv[index], &data->cache.small);
-            }
-            else if (append_hass[i]) {
-              status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[append_hass[i]], &data->cache.small);
-            }
-            else {
-              status = f_string_dynamic_append_nulless(append_defaults[i], &data->cache.small);
-            }
-
-            if (F_status_is_error(status)) {
-              if ((append_ids[i] && main->parameters.array[append_ids[i]].result & f_console_result_value_e) || !append_hass[i]) {
-                fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
-              }
-              else {
-                fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", fll_error_file_flag_fallback_e);
-              }
-
-              break;
-            }
-          } // for
-
-          if (F_status_is_error_not(status)) {
-            status = f_file_exists(data->cache.small, F_true);
-
-            if (F_status_is_error(status) || status == F_false) {
-              if (F_status_is_error(status)) {
-                fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e);
-
-                if (main->error.verbosity > f_console_verbosity_quiet_e) {
-                  fll_print_dynamic_raw(f_string_eol_s, main->error.to);
-                }
-              }
-
-              control_print_error_socket_file_missing(main, data->cache.small);
-
-              status = F_status_set_error(F_socket_not);
-            }
-          }
-        }
-      }
-
-      if (F_status_is_error_not(status)) {
-        if (f_file_is(data->cache.small, F_file_type_socket_d, F_true) == F_false) {
-          control_print_error_socket_file_not(main, data->cache.small);
-
-          status = F_status_set_error(F_socket_not);
-        }
-      }
-
-      if (F_status_is_error_not(status)) {
-        status = f_socket_create(&data->socket);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "f_socket_create", fll_error_file_flag_fallback_e);
-
-          control_print_error_socket_file_failed(main, data->cache.small);
-        }
-      }
-
-      if (F_status_is_error_not(status)) {
-        status = f_socket_connect(data->socket);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "f_socket_connect", fll_error_file_flag_fallback_e);
-
-          control_print_error_socket_file_failed(main, data->cache.small);
-        }
-      }
-    }
-
-    f_string_ranges_resize(0, &objects);
-    f_string_rangess_resize(0, &contents);
-    f_number_unsigneds_resize(0, &delimits);
-
-    data->cache.large.used = 0;
-    data->cache.small.used = 0;
-
-    if (F_status_is_error_not(status)) {
-      if (data->cache.large.size > control_default_buffer_limit_soft_large_d) {
-        status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &data->cache.large);
-      }
-
-      if (F_status_is_error_not(status)) {
-        if (data->cache.small.size > control_default_buffer_limit_soft_small_d) {
-          status = f_string_dynamic_resize(control_default_buffer_limit_soft_small_d, &data->cache.small);
-        }
-      }
-    }
-
-    if (F_status_is_error(status)) return status;
-
-    return F_none;
-  }
-#endif // _di_control_settings_load_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/control/c/private-control.h b/level_3/control/c/private-control.h
deleted file mode 100644 (file)
index b663dc9..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Control
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_control_h
-#define _PRIVATE_control_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Verify that the additional parameters are reasonably correct for the identified action.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- *
- * @return
- *   F_none on success.
- *
- *   F_parameter (with error bit) on parameter validation/verification failure.
- */
-#ifndef _di_control_action_verify_
-  extern f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_action_verify_
-
-/**
- * Build the payload, storing it in the large cache.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- *
- * @return
- *   F_none on success.
- *
- *   F_too_large (with error bit) If the message is too large for the packet format to transmit.
- *
- *   Errors (with error bit) from: f_string_append().
- *   Errors (with error bit) from: f_string_dynamic_append().
- *   Errors (with error bit) from: f_string_dynamic_resize().
- *   Errors (with error bit) from: fll_fss_extended_write().
- *   Errors (with error bit) from: fll_fss_payload_write().
- *
- * @see f_string_append()
- * @see f_string_dynamic_append()
- * @see f_string_dynamic_resize()
- */
-#ifndef _di_control_packet_build_
-  extern f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_build_
-
-/**
- * Given the header buffer, get the flag bits.
- *
- * @param buffer
- *   The buffer to read the length of and get the
- *
- * @return
- *   The 8-bit number representing the flags.
- */
-#ifndef _di_control_packet_header_flag_
-  extern uint8_t control_packet_header_flag(const uint8_t buffer[]) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_header_flag_
-
-/**
- * Given the header buffer, get the length bits.
- *
- * The endianness is automatically detected and swapped by this function to guarantee host order bytes.
- *
- * @param is_big
- *   If TRUE, then the length in the buffer is in big endian format.
- *   If FALSE, then the length in the buffer is in little endian format.
- * @param buffer
- *   The buffer to read the length of and get the
- *
- * @return
- *   The 32-bit number representing the length.
- */
-#ifndef _di_control_packet_header_length_
-  extern uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_header_length_
-
-/**
- * Receive the response from the remote socket, storing it in the large cache.
- *
- * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- * @param header
- *   The control payload packet header data.
- *
- * @return
- *   F_none on success.
- *
- *   F_header_not (with error bit) If there is a problem processing the packet header.
- *   F_memory_not (with error bit) On out of memory issues (this is passed through from called functions).
- *   F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure.
- *   F_payload_not (with error bit) If there is a problem processing the packet payload.
- *   F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size.
- *   F_too_small (with error bit) If the received packet actual size is smaller than the specified size.
- *
- *   Errors (with error bit) from: f_socket_read().
- *   Errors (with error bit) from: f_string_dynamic_increase_by().
- *   Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect().
- *   Errors (with error bit) from: fll_fss_extended_read().
- *   Errors (with error bit) from: fll_fss_basic_list_read().
- *
- * @see f_socket_read()
- * @see f_string_dynamic_increase_by()
- * @see fl_conversion_dynamic_partial_to_unsigned_detect()
- * @see f_fss_apply_delimit()
- * @see fl_status_string_from()
- * @see fll_fss_extended_read()
- * @see fll_fss_basic_list_read()
- */
-#ifndef _di_control_packet_receive_
-  extern f_status_t control_packet_receive(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_receive_
-
-/**
- * Process the received and loaded packet.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- * @param header
- *   The control payload packet header data.
- *
- * @return
- *   F_done on success but action has no success or failure states.
- *   F_success on success.
- *
- *   F_busy (with error bit)
- *   F_failure (with error bit) on success but controller returned failure for action.
- *   F_known_not (with error bit) if the Payload type is unknown.
- *   Any error (with error bit) on failure where the error is defined by the controller service.
- */
-#ifndef _di_control_packet_process_
-  extern f_status_t control_packet_process(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_process_
-
-/**
- * Send the payload to the remote socket, getting the payload from the large cache.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- *
- * @return
- *   F_none on success.
- *
- *   Errors (with error bit) from: f_socket_write().
- *
- * @see f_socket_write()
- */
-#ifndef _di_control_packet_send_
-  extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_send_
-
-/**
- * Load and process the control settings file.
- *
- * This identifies and attempts to connect to the socket.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- *
- * @return
- *   F_none on success.
- *
- *   F_interrupt (with error bit) on interrupt signal received.
- *   F_socket_not (with error bit) on socket related error preventing the socket from being created or connected to.
- *
- *   Errors (with error bit) from: f_file_exists().
- *   Errors (with error bit) from: f_file_open().
- *   Errors (with error bit) from: f_file_stream_read().
- *   Errors (with error bit) from: f_socket_connect().
- *   Errors (with error bit) from: f_socket_create().
- *   Errors (with error bit) from: f_string_append().
- *   Errors (with error bit) from: f_string_append_assure().
- *   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: f_string_dynamics_resize().
- *   Errors (with error bit) from: f_fss_apply_delimit().
- *   Errors (with error bit) from: fll_fss_extended_read().
- *
- * @see f_file_exists()
- * @see f_file_open()
- * @see f_file_stream_read()
- * @see f_socket_connect()
- * @see f_socket_create()
- * @see f_string_append()
- * @see f_string_append_assure()
- * @see f_string_dynamic_append_nulless()
- * @see f_string_dynamic_partial_append_nulless()
- * @see f_string_dynamics_resize()
- * @see f_fss_apply_delimit()
- * @see fll_fss_extended_read()
- */
-#ifndef _di_control_settings_load_
-  extern f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_settings_load_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_control_h
diff --git a/level_3/control/c/private-print.c b/level_3/control/c/private-print.c
deleted file mode 100644 (file)
index 474944c..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-#include "control.h"
-#include "private-common.h"
-#include "private-control.h"
-#include "private-print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_control_print_controller_packet_response_
-  void control_print_controller_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
-
-    if (header.status == F_failure) {
-      if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-      f_file_stream_lock(main->error.to);
-
-      fl_print_format("%r%[%QThe action '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-      fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
-      fl_print_format("%[' failed with status '%]", main->error.to, main->context.set.error, main->context.set.error);
-      fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, string_status, main->context.set.notable);
-      fl_print_format("%[' (%]", main->error.to, main->context.set.error, main->context.set.error);
-      fl_print_format("%[%ui%]", main->error.to, main->context.set.notable, header.status, main->context.set.notable);
-
-      if (header.length) {
-        fl_print_format("%[): %/Q%]%r", main->error.to, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
-      }
-      else {
-        fl_print_format("%[).%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-      }
-
-      f_file_stream_unlock(main->error.to);
-
-      return;
-    }
-
-    if (header.status == F_busy) {
-      if (main->warning.verbosity == f_console_verbosity_quiet_e) return;
-
-      f_file_stream_lock(main->warning.to);
-
-      fl_print_format("%r%[%QThe action '%]", main->warning.to, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning);
-      fl_print_format("%[%q%]", main->warning.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
-      fl_print_format("%[' could not be performed because the service is busy.%]%r", main->warning.to, main->context.set.warning, main->context.set.warning, f_string_eol_s);
-
-      f_file_stream_unlock(main->warning.to);
-
-      return;
-    }
-
-    if (main->output.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->output.to);
-
-    fl_print_format("%rThe action '", main->output.to, f_string_eol_s);
-    fl_print_format("%[%q%]", main->output.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
-
-    if (header.status == F_done) {
-      fl_print_format("' is performed", main->output.to);
-    }
-    else {
-      fl_print_format("' is successfully performed", main->output.to);
-    }
-
-    if (header.length) {
-      fl_print_format(": %/Q%r", main->output.to, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
-    }
-    else {
-      fl_print_format(".%r", main->output.to, f_string_eol_s);
-    }
-
-    f_file_stream_unlock(main->output.to);
-  }
-#endif // _di_control_print_controller_packet_response_
-
-#ifndef _di_control_print_debug_packet_header_object_and_content_
-  void control_print_debug_packet_header_object_and_content(const fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) {
-
-    if (main->output.verbosity == f_console_verbosity_debug_e) return;
-
-    f_file_stream_lock(main->output.to);
-
-    fl_print_format("%rPacket header Object '%[%Q%]", main->output.to, f_string_eol_s, main->context.set.notable, object, main->context.set.notable);
-    fl_print_format("' has value '%[%/Q%]'.%r", main->output.to, main->context.set.notable, content, content_range, main->context.set.notable, f_string_eol_s);
-
-    f_file_stream_unlock(main->output.to);
-  }
-#endif // _di_control_print_debug_packet_header_object_and_content_
-
-#ifndef _di_control_print_debug_packet_message_
-  void control_print_debug_packet_message(const fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) {
-
-    if (main->output.verbosity == f_console_verbosity_debug_e) return;
-
-    f_file_stream_lock(main->output.to);
-
-    fl_print_format("%r%s", main->output.to, f_string_eol_s, message, main->context.set.notable, main->context.set.notable);
-
-    if (buffer) {
-      if (range) {
-        fl_print_format("'%[%/Q%]'", main->output.to, main->context.set.notable, *buffer, *range, main->context.set.notable);
-      }
-      else {
-        fl_print_format("'%[%/Q%]'", main->output.to, main->context.set.notable, *buffer, main->context.set.notable);
-      }
-    }
-
-    if (status) {
-      fl_print_format(", with status code %[%ui%]'", main->output.to, main->context.set.notable, *status, main->context.set.notable);
-    }
-
-    fl_print_format(".%r", main->output.to, f_string_eol_s);
-
-    f_file_stream_unlock(main->output.to);
-  }
-#endif // _di_control_print_debug_packet_message_
-
-#ifndef _di_control_print_error_packet_response_
-  void control_print_error_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QReceived error response for " CONTROL_action_s " '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%q%]", main->error.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
-    fl_print_format("%[' with status '%]", main->error.to, main->context.set.error, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, string_status, main->context.set.notable);
-    fl_print_format("%[' (%]", main->error.to, main->context.set.error, main->context.set.error);
-    fl_print_format("%[%ui%]", main->error.to, main->context.set.notable, header.status, main->context.set.notable);
-
-    if (header.length) {
-      fl_print_format("%[): %/Q%]%r", main->error.to, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
-    }
-    else {
-      fl_print_format("%[).%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-    }
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_packet_response_
-
-#ifndef _di_control_print_error_parameter_actions_none_
-  void control_print_error_parameter_actions_none(const fll_program_data_t * const main) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    fll_print_format("%r%[%QNo actions provided.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
-  }
-#endif // _di_control_print_error_parameter_actions_none_
-
-#ifndef _di_control_print_error_parameter_action_not_
-  void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' is not a known controller action.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_not_
-
-#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
-  void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' a rule base name cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_basename_empty_
-
-#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
-  void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_directory_empty_
-
-#ifndef _di_control_print_error_parameter_action_rule_empty_
-  void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' a rule name cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_empty_
-
-#ifndef _di_control_print_error_parameter_action_rule_not_
-  void control_print_error_parameter_action_rule_not(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_not_
-
-#ifndef _di_control_print_error_parameter_action_rule_too_few_
-  void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' has too few arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_too_few_
-
-#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
-  void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' when used with '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable);
-    fl_print_format("%[' has too few arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_too_few_with_
-
-#ifndef _di_control_print_error_parameter_action_rule_too_many_
-  void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' has too many arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_too_many_
-
-#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
-  void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' when used with '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable);
-    fl_print_format("%[' has too many arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_too_many_with_
-
-#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
-  void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable);
-    fl_print_format("%[' does not know the argument '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable);
-    fl_print_format("%['.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_action_rule_with_unknown_
-
-#ifndef _di_control_print_error_parameter_value_empty_
-  void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe value for the parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%r%r%]", main->error.to, main->context.set.notable, f_console_symbol_long_normal_s, parameter, main->context.set.notable);
-    fl_print_format("%[' must not be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_value_empty_
-
-#ifndef _di_control_print_error_parameter_value_not_
-  void control_print_error_parameter_value_not(const fll_program_data_t * const main, const f_string_static_t parameter) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%r%r%]", main->error.to, main->context.set.notable, f_console_symbol_long_normal_s, parameter, main->context.set.notable);
-    fl_print_format("%[' is specified, but no value is given.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_parameter_value_not_
-
-#ifndef _di_control_print_error_pipe_supported_not_
-  void control_print_error_pipe_supported_not(const fll_program_data_t * const main) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    fll_print_format("%r%[%QPipe input is not supported by this program.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
-  }
-#endif // _di_control_print_error_pipe_supported_not_
-
-#ifndef _di_control_print_error_response_packet_valid_not_
-  void control_print_error_response_packet_valid_not(const fll_program_data_t * const main) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    fll_print_format("%r%[%QThe received response is not a valid or supported packet.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
-  }
-#endif // _di_control_print_error_response_packet_valid_not_
-
-#ifndef _di_control_print_error_request_packet_too_large_
-  void control_print_error_request_packet_too_large(const fll_program_data_t * const main) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    fll_print_format("%r%[%QThe generated packet is too large, cannot send packet.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
-  }
-#endif // _di_control_print_error_request_packet_too_large_
-
-#ifndef _di_control_print_error_socket_file_failed_
-  void control_print_error_socket_file_failed(const fll_program_data_t * const main, const f_string_static_t path_socket) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QFailed to connect to the socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable);
-    fl_print_format("%['.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_socket_file_failed_
-
-#ifndef _di_control_print_error_socket_file_missing_
-  void control_print_error_socket_file_missing(const fll_program_data_t * const main, const f_string_static_t path_socket) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe controller socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable);
-    fl_print_format("%[' could not be found and is required.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_socket_file_missing_
-
-#ifndef _di_control_print_error_socket_file_not_
-  void control_print_error_socket_file_not(const fll_program_data_t * const main, const f_string_static_t path_socket) {
-
-    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
-
-    f_file_stream_lock(main->error.to);
-
-    fl_print_format("%r%[%QThe controller socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
-    fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable);
-    fl_print_format("%[' is not a socket file.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-    f_file_stream_unlock(main->error.to);
-  }
-#endif // _di_control_print_error_socket_file_not_
-
-#ifndef _di_control_print_warning_packet_header_duplicate_object_
-  void control_print_warning_packet_header_duplicate_object(const fll_program_data_t * const main, const f_string_static_t response_header) {
-
-    if (main->warning.verbosity == f_console_verbosity_debug_e) return;
-
-    f_file_stream_lock(main->warning.to);
-
-    fl_print_format("%r%[%QThe received response header '%]", main->warning.to, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning);
-    fl_print_format("%[%Q%]", main->warning.to, main->context.set.notable, response_header, main->context.set.notable);
-    fl_print_format("%[' is repeated.%]%r", main->warning.to, main->context.set.warning, main->context.set.warning, f_string_eol_s);
-
-    f_file_stream_unlock(main->warning.to);
-  }
-#endif // _di_control_print_warning_packet_header_duplicate_object_
-
-#ifndef _di_control_print_warning_packet_process_string_to_failed_
-  void control_print_warning_packet_process_string_to_failed(const fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) {
-
-    if (main->warning.verbosity == f_console_verbosity_debug_e) return;
-
-    f_file_stream_lock(main->warning.to);
-
-    fl_print_format("%r%[%QFailed while calling f_status_string_to() for status%] ", main->output.to, f_string_eol_s, main->context.set.warning, main->context.set.warning, main->context.set.warning);
-    fl_print_format("%[%ui%]", main->output.to, main->context.set.notable, status_of, main->context.set.notable);
-    fl_print_format("%[, failing with status code%] ", main->output.to, main->context.set.warning, status_error, main->context.set.warning);
-    fl_print_format("%[%ui%]", main->output.to, main->context.set.notable, status_error, main->context.set.notable);
-    fl_print_format("%[.%]%r", main->output.to, main->context.set.warning, main->context.set.warning, f_string_eol_s);
-
-    f_file_stream_unlock(main->warning.to);
-  }
-#endif // _di_control_print_warning_packet_process_string_to_failed_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/control/c/private-print.h b/level_3/control/c/private-print.h
deleted file mode 100644 (file)
index d136ec1..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Control
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_control_print_h
-#define _PRIVATE_control_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print a message about a packet response.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- * @param header
- *   The control payload packet header data.
- * @param status
- *   A string representing the name of the status code from header.status.
- */
-#ifndef _di_control_print_controller_packet_response_
-  extern void control_print_controller_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) F_attribute_visibility_internal_d;
-#endif // _di_control_print_controller_packet_response_
-
-/**
- * Print a message displaying the object and content for some packet header.
- *
- * @param main
- *   The main program data.
- * @param object
- *   The object string.
- * @param content
- *   The content string.
- * @param content_range
- *   The range representing the content where the content is found within the content string.
- */
-#ifndef _di_control_print_debug_packet_header_object_and_content_
-  extern void control_print_debug_packet_header_object_and_content(const fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) F_attribute_visibility_internal_d;
-#endif // _di_control_print_debug_packet_header_object_and_content_
-
-/**
- * Print a debug message regarding some packet.
- *
- * @param main
- *   The main program data.
- * @param message
- *   The message to print.
- *
- *   A single "%[" followed by a single "%]" is supported in the message and is replaced with "notable" context.
- * @param buffer
- *   (optional) An additonal message to print (this is syntax highlighted).
- *   Set to NULL to not use.
- * @param range
- *   (optional) The range within the buffer to print rather than printing the entire buffer.
- *   Set to NULL to not use.
- *   This is ignored when buffer is NULL.
- * @param status
- *   (optional) A status code that triggered the failure (this is syntax highlighted).
- *   Set to NULL to not use.
- */
-#ifndef _di_control_print_debug_packet_message_
-  extern void control_print_debug_packet_message(const fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) F_attribute_visibility_internal_d;
-#endif // _di_control_print_debug_packet_message_
-
-/**
- * Print an error from the packet response.
- *
- * @param main
- *   The main program data.
- * @param data
- *   The control data.
- * @param header
- *   The control payload packet header data.
- * @param status
- *   A string representing the name of the status code from header.status.
- */
-#ifndef _di_control_print_error_packet_response_
-  extern void control_print_error_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t status) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_packet_response_
-/**
- * Print an error message about no actions being provided.
- *
- * @param main
- *   The main program data.
- */
-#ifndef _di_control_print_error_parameter_actions_none_
-  extern void control_print_error_parameter_actions_none(const fll_program_data_t * const main) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_actions_none_
-
-/**
- * Print an error message about the given parameter not matching the known set of controller actions.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_not_
-  extern void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_not_
-
-/**
- * Print an error message about the given parameter being a rule action having an empty rule basename.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
-  extern void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_basename_empty_
-
-/**
- * Print an error message about the given parameter being a rule action having an empty rule directory path.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
-  extern void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_directory_empty_
-
-/**
- * Print an error message about the given parameter being a rule action having an empty rule name.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_empty_
-  extern void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_empty_
-
-/**
- * Print an error message about the given parameter being a rule action but no rule name is specified.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_not_
-  extern void control_print_error_parameter_action_rule_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_not_
-
-/**
- * Print an error message about the given parameter being a rule action having too few arguments passed.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_too_few_
-  extern void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_too_few_
-
-/**
- * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with".
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- * @param with
- *   The additional parameter in which is requiring additional arguments that are not met.
- */
-#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
-  extern void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_too_few_with_
-
-/**
- * Print an error message about the given parameter being a rule action having too many arguments passed.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- */
-#ifndef _di_control_print_error_parameter_action_rule_too_many_
-  extern void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_too_many_
-
-/**
- * Print an error message about the given parameter being a rule action having too many arguments passed for a given "with".
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- * @param with
- *   The additional parameter in which is requiring additional arguments that are not met.
- */
-#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
-  extern void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_too_many_with_
-/**
- * Print an error message about the given parameter being unknown for the use with the given action.
- *
- * @param main
- *   The main program data.
- * @param action
- *   The parameter representing an action.
- * @param with
- *   The additional parameter in which is requiring additional arguments that are not met.
- */
-#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
-  extern void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_action_rule_with_unknown_
-
-/**
- * Print an error message about the parameter's associated value being an empty string.
- *
- * @param main
- *   The main program data.
- * @param parameter
- *   The parameter name.
- */
-#ifndef _di_control_print_error_parameter_value_empty_
-  extern void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_value_empty_
-
-/**
- * Print an error message about the parameter missings its associated value.
- *
- * @param main
- *   The main program data.
- * @param parameter
- *   The parameter name.
- */
-#ifndef _di_control_print_error_parameter_value_not_
-  extern void control_print_error_parameter_value_not(const fll_program_data_t * const main, const f_string_static_t parameter) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_value_not_
-
-/**
- * Print an error message about a pipe input being unsupported.
- *
- * @param main
- *   The main program data.
- */
-#ifndef _di_control_print_error_pipe_supported_not_
-  extern void control_print_error_pipe_supported_not(const fll_program_data_t * const main) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_pipe_supported_not_
-
-/**
- * Print an error message about the response packet format either being invalid or not supported.
- *
- * @param main
- *   The main program data.
- */
-#ifndef _di_control_print_error_response_packet_valid_not_
-  extern void control_print_error_response_packet_valid_not(const fll_program_data_t * const main) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_response_packet_valid_not_
-
-/**
- * Print an error message about the request packet being too large.
- *
- * @param main
- *   The main program data.
- */
-#ifndef _di_control_print_error_request_packet_too_large_
-  void extern control_print_error_request_packet_too_large(const fll_program_data_t * const main) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_request_packet_too_large_
-
-/**
- * Print an error message about failure to connect to the socket file.
- *
- * @param main
- *   The main program data.
- * @param path_socket
- *   The socket file path.
- */
-#ifndef _di_control_print_error_socket_file_failed_
-  extern void control_print_error_socket_file_failed(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_socket_file_failed_
-
-/**
- * Print an error message about the socket file not being found.
- *
- * @param main
- *   The main program data.
- * @param path_socket
- *   The socket file path.
- */
-#ifndef _di_control_print_error_socket_file_missing_
-  extern void control_print_error_socket_file_missing(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_socket_file_missing_
-
-/**
- * Print an error message about the socket file not actually being a socket file.
- *
- * @param main
- *   The main program data.
- * @param path_socket
- *   The socket file path.
- */
-#ifndef _di_control_print_error_socket_file_not_
-  extern void control_print_error_socket_file_not(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_socket_file_not_
-
-/**
- * Print a warning message about a response header being repeated (when debugging).
- *
- * This program currently does not support multiple headers for any given valid header Object.
- *
- * @param main
- *   The main program data.
- * @param response_header
- *   The repeated response header.
- */
-#ifndef _di_control_print_warning_packet_header_duplicate_object_
-  extern void control_print_warning_packet_header_duplicate_object(const fll_program_data_t * const main, const f_string_static_t response_header) F_attribute_visibility_internal_d;
-#endif // _di_control_print_warning_packet_header_duplicate_object_
-
-/**
- * Print a warning message about a failure when calling f_status_string_to().
- *
- * @param main
- *   The main program data.
- * @param status_of
- *   The status code to be translating to a string.
- * @param status_error
- *   The status code representing the failure status returned by f_status_string_to().
- *
- * @see f_status_string_to()
- */
-#ifndef _di_control_print_warning_packet_process_string_to_failed_
-  extern void control_print_warning_packet_process_string_to_failed(const fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) F_attribute_visibility_internal_d;
-#endif // _di_control_print_warning_packet_process_string_to_failed_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_control_print_h
index fbad46344539865d1cc84892fa57f5731394b410..f60f7d211c47dff1c90a9e199fd7bcb274a34a7f 100644 (file)
@@ -35,11 +35,11 @@ build_libraries-individual_thread -lf_thread
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 
-build_sources_library control.c common.c print.c private-common.c private-control.c private-print.c
+build_sources_library 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/data.c main/print/debug.c main/print/error.c main/print/message.c main/print/warning.c main/action.c main/control.c main/packet.c main/payload.c main/signal.c main/thread.c
 
-build_sources_program main.c
+build_sources_program main/main.c
 
-build_sources_headers control.h common.h print.h
+build_sources_headers 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.h main/print/data.h main/print/debug.h main/print/error.h main/print/message.h main/print/warning.h main/action.h main/control.h main/packet.h main/payload.h main/signal.h main/thread.h
 
 build_sources_documentation man