]> Kevux Git Server - fll/commitdiff
Update: Byte Dump program structure, following newer standards.
authorKevin Day <kevin@kevux.org>
Wed, 26 Jul 2023 04:16:52 +0000 (23:16 -0500)
committerKevin Day <kevin@kevux.org>
Wed, 26 Jul 2023 04:16:52 +0000 (23:16 -0500)
I noticed two things while working on this that need to be addressed for all programs.
1) When using threads, the signal for piping data (such as byte_dump /bin/bash | head) does not trigger.
2) The color code modes are not being processed correctly.

These observed bugs will be fixed in some other commit.

36 files changed:
level_3/byte_dump/c/byte_dump.c [deleted file]
level_3/byte_dump/c/byte_dump.h [deleted file]
level_3/byte_dump/c/common.c [deleted file]
level_3/byte_dump/c/common.h [deleted file]
level_3/byte_dump/c/main/byte_dump.c [new file with mode: 0644]
level_3/byte_dump/c/main/byte_dump.h [new file with mode: 0644]
level_3/byte_dump/c/main/common.c [new file with mode: 0644]
level_3/byte_dump/c/main/common.h [new file with mode: 0644]
level_3/byte_dump/c/main/common/define.c [moved from level_3/byte_dump/c/private-common.c with 61% similarity]
level_3/byte_dump/c/main/common/define.h [new file with mode: 0644]
level_3/byte_dump/c/main/common/enumeration.c [new file with mode: 0644]
level_3/byte_dump/c/main/common/enumeration.h [new file with mode: 0644]
level_3/byte_dump/c/main/common/print.c [new file with mode: 0644]
level_3/byte_dump/c/main/common/print.h [new file with mode: 0644]
level_3/byte_dump/c/main/common/string.c [new file with mode: 0644]
level_3/byte_dump/c/main/common/string.h [new file with mode: 0644]
level_3/byte_dump/c/main/common/type.c [new file with mode: 0644]
level_3/byte_dump/c/main/common/type.h [new file with mode: 0644]
level_3/byte_dump/c/main/main.c [moved from level_3/byte_dump/c/main.c with 51% similarity]
level_3/byte_dump/c/main/main.h [moved from level_3/byte_dump/c/main.h with 100% similarity]
level_3/byte_dump/c/main/print/data.c [new file with mode: 0644]
level_3/byte_dump/c/main/print/data.h [moved from level_3/byte_dump/c/private-byte_dump.h with 58% similarity]
level_3/byte_dump/c/main/print/error.c [new file with mode: 0644]
level_3/byte_dump/c/main/print/error.h [new file with mode: 0644]
level_3/byte_dump/c/main/print/message.c [moved from level_3/byte_dump/c/print.c with 62% similarity]
level_3/byte_dump/c/main/print/message.h [new file with mode: 0644]
level_3/byte_dump/c/main/process.c [new file with mode: 0644]
level_3/byte_dump/c/main/process.h [new file with mode: 0644]
level_3/byte_dump/c/main/signal.c [new file with mode: 0644]
level_3/byte_dump/c/main/signal.h [new file with mode: 0644]
level_3/byte_dump/c/main/thread.c [new file with mode: 0644]
level_3/byte_dump/c/main/thread.h [new file with mode: 0644]
level_3/byte_dump/c/print.h [deleted file]
level_3/byte_dump/c/private-byte_dump.c [deleted file]
level_3/byte_dump/c/private-common.h [deleted file]
level_3/byte_dump/data/build/settings

diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c
deleted file mode 100644 (file)
index 39844da..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-#include "byte_dump.h"
-#include "private-common.h"
-#include "private-byte_dump.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_byte_dump_main_
-  f_status_t byte_dump_main(fll_program_data_t * const main, byte_dump_setting_t * const setting) {
-
-    f_status_t status = F_none;
-
-    setting->state.step_small = byte_dump_allocation_console_d;
-
-    status = f_console_parameter_process(arguments, &main->parameters, &setting->state, 0);
-
-    setting->state.step_small = byte_dump_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] = { byte_dump_parameter_no_color_e, byte_dump_parameter_light_e, byte_dump_parameter_dark_e };
-        choices.array = choices_array;
-        choices.used = 3;
-
-        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] = { byte_dump_parameter_verbosity_quiet_e, byte_dump_parameter_verbosity_error_e, byte_dump_parameter_verbosity_verbose_e, byte_dump_parameter_verbosity_debug_e, byte_dump_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;
-        }
-      }
-    }
-
-    byte_dump_data_t data = byte_dump_data_t_initialize;
-    data.main = main;
-    data.argv = main->parameters.arguments.array;
-
-    // Identify priority of mode parameters.
-    {
-      uint16_t choices_array[5] = { byte_dump_parameter_hexidecimal_e, byte_dump_parameter_duodecimal_e, byte_dump_parameter_octal_e, byte_dump_parameter_binary_e, byte_dump_parameter_decimal_e };
-      f_number_unsigned_t choice = 0;
-      const f_uint16s_t choices = macro_f_uint16s_t_initialize_1(choices_array, 0, 5);
-
-      status = f_console_parameter_prioritize_right(main->parameters, choices, &choice);
-
-      if (F_status_is_error(status)) {
-        fll_error_print(main->error, F_status_set_fine(status), "f_console_parameter_prioritize_right", fll_error_file_flag_fallback_e);
-
-        return F_status_set_error(status);
-      }
-
-      if (choices.array[choice] == byte_dump_parameter_hexidecimal_e) {
-        data.mode = byte_dump_mode_hexidecimal_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_duodecimal_e) {
-        data.mode = byte_dump_mode_duodecimal_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_octal_e) {
-        data.mode = byte_dump_mode_octal_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_binary_e) {
-        data.mode = byte_dump_mode_binary_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_decimal_e) {
-        data.mode = byte_dump_mode_decimal_e;
-      }
-    }
-
-    // Identify priority of presentation parameters.
-    {
-      uint16_t choices_array[3] = { byte_dump_parameter_normal_e, byte_dump_parameter_simple_e, byte_dump_parameter_classic_e };
-      f_number_unsigned_t choice = 0;
-      const f_uint16s_t choices = macro_f_uint16s_t_initialize_1(choices_array, 0, 3);
-
-      status = f_console_parameter_prioritize_right(main->parameters, choices, &choice);
-
-      if (F_status_is_error(status)) {
-        fll_error_print(main->error, F_status_set_fine(status), "f_console_parameter_prioritize_right", fll_error_file_flag_fallback_e);
-
-        return F_status_set_error(status);
-      }
-
-      if (choices.array[choice] == byte_dump_parameter_normal_e) {
-        data.presentation = byte_dump_presentation_normal_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_simple_e) {
-        data.presentation = byte_dump_presentation_simple_e;
-      }
-      else if (choices.array[choice] == byte_dump_parameter_classic_e) {
-        data.presentation = byte_dump_presentation_classic_e;
-      }
-    }
-
-    // Identify priority of narrow and wide parameters.
-    {
-      uint16_t choices_array[2] = { byte_dump_parameter_narrow_e, byte_dump_parameter_wide_e };
-      f_number_unsigned_t choice = byte_dump_parameter_wide_e;
-      const f_uint16s_t choices = macro_f_uint16s_t_initialize_1(choices_array, 0, 2);
-
-      status = f_console_parameter_prioritize_right(main->parameters, choices, &choice);
-
-      if (F_status_is_error(status)) {
-        fll_error_print(main->error, F_status_set_fine(status), "f_console_parameter_prioritize_right", fll_error_file_flag_fallback_e);
-
-        return F_status_set_error(status);
-      }
-
-      if (choices.array[choice] == byte_dump_parameter_narrow_e) {
-        if (data.options & byte_dump_option_wide_d) {
-          data.options -= byte_dump_option_wide_d;
-        }
-      }
-      else if (choices.array[choice] == byte_dump_parameter_wide_e) {
-        data.options |= byte_dump_option_wide_d;
-      }
-    }
-
-    if (main->parameters.array[byte_dump_parameter_help_e].result & f_console_result_found_e) {
-      byte_dump_print_help(setting, main->message);
-
-      return F_none;
-    }
-
-    if (main->parameters.array[byte_dump_parameter_version_e].result & f_console_result_found_e) {
-      fll_program_print_version(&main->message, byte_dump_program_version_s);
-
-      return F_none;
-    }
-
-    if (main->parameters.array[byte_dump_parameter_copyright_e].result & f_console_result_found_e) {
-      fll_program_print_copyright(&main->message);
-
-      return F_none;
-    }
-
-    status = F_none;
-
-    if (main->parameters.remaining.used || (main->pipe & fll_program_data_pipe_input_e)) {
-      if (main->parameters.array[byte_dump_parameter_width_e].result & f_console_result_found_e) {
-        f_file_stream_lock(main->error.to);
-
-        fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_width_s, 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);
-
-        return F_status_set_error(F_parameter);
-      }
-
-      if (main->parameters.array[byte_dump_parameter_width_e].result & f_console_result_value_e) {
-        const f_number_unsigned_t index = main->parameters.array[byte_dump_parameter_width_e].values.array[main->parameters.array[byte_dump_parameter_width_e].values.used - 1];
-        f_number_unsigned_t number = 0;
-
-        status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, data.argv[index], &number);
-
-        // Negative numbers are not supported.
-        if (status == F_number_negative) {
-          status = F_status_set_error(F_number_negative);
-        }
-
-        if (F_status_is_error(status) || number < 1 || number >= 0xfb) {
-          f_file_stream_lock(main->error.to);
-
-          fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_width_s, main->context.set.notable);
-          fl_print_format("%[' value can only be a number (inclusively) between %]", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[1%]", main->error.to, main->context.set.notable, main->context.set.notable);
-          fl_print_format(" %[and%] ", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[250%]", main->error.to, main->context.set.notable, 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);
-
-          if (F_status_is_error(status)) return status;
-
-          return F_status_set_error(F_parameter);
-        }
-
-        data.width = (uint8_t) number;
-      }
-
-      if (main->parameters.array[byte_dump_parameter_first_e].result & f_console_result_found_e) {
-        f_file_stream_lock(main->error.to);
-
-        fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_first_s, 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);
-
-        return F_status_set_error(F_parameter);
-      }
-
-      if (main->parameters.array[byte_dump_parameter_first_e].result & f_console_result_value_e) {
-        const f_number_unsigned_t index = main->parameters.array[byte_dump_parameter_first_e].values.array[main->parameters.array[byte_dump_parameter_first_e].values.used - 1];
-        f_number_unsigned_t number = 0;
-
-        status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, data.argv[index], &number);
-
-        // Negative numbers are not supported.
-        if (status == F_number_negative) {
-          status = F_status_set_error(F_number_negative);
-        }
-
-        if (F_status_is_error(status) || number > F_number_t_size_unsigned_d) {
-          f_file_stream_lock(main->error.to);
-
-          fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_first_s, main->context.set.notable);
-          fl_print_format("%[' value can only be a number (inclusively) between %]", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[0%]", main->error.to, main->context.set.notable, main->context.set.notable);
-          fl_print_format(" %[and%] ", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[%un%]", main->error.to, main->context.set.notable, F_number_t_size_unsigned_d, 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);
-
-          if (F_status_is_error(status)) return status;
-
-          return F_status_set_error(F_parameter);
-        }
-
-        data.first = number;
-      }
-
-      if (main->parameters.array[byte_dump_parameter_last_e].result & f_console_result_found_e) {
-        f_file_stream_lock(main->error.to);
-
-        fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_last_s, 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);
-
-        return F_status_set_error(F_parameter);
-      }
-
-      if (main->parameters.array[byte_dump_parameter_last_e].result & f_console_result_value_e) {
-        const f_number_unsigned_t index = main->parameters.array[byte_dump_parameter_last_e].values.array[main->parameters.array[byte_dump_parameter_last_e].values.used - 1];
-        f_number_unsigned_t number = 0;
-
-        status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, data.argv[index], &number);
-
-        // Negative numbers are not supported.
-        if (status == F_number_negative) {
-          status = F_status_set_error(F_number_negative);
-        }
-
-        if (F_status_is_error(status) || number < 0 || number > F_number_t_size_unsigned_d) {
-          f_file_stream_lock(main->error.to);
-
-          fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_last_s, main->context.set.notable);
-          fl_print_format("%[' value can only be a number (inclusively) between %]", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[0%]", main->error.to, main->context.set.notable, main->context.set.notable);
-          fl_print_format(" %[and%] ", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[%un%]", main->error.to, main->context.set.notable, F_number_t_size_unsigned_d, 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);
-
-          if (F_status_is_error(status)) return status;
-
-          return F_status_set_error(F_parameter);
-        }
-
-        data.last = number;
-      }
-
-      if (main->parameters.array[byte_dump_parameter_first_e].result & f_console_result_value_e && main->parameters.array[byte_dump_parameter_last_e].result & f_console_result_value_e) {
-        if (data.first > data.last) {
-          f_file_stream_lock(main->error.to);
-
-          fl_print_format("%[%QThe parameter '%]", main->error.to, 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, byte_dump_long_first_s, main->context.set.notable);
-          fl_print_format("%[' value cannot be greater than the parameter '%]", main->error.to, main->context.set.error, main->context.set.error);
-          fl_print_format("%[%r%r%]", main->error.to, main->context.set.notable, f_console_symbol_long_normal_s, byte_dump_long_last_s, main->context.set.notable);
-          fl_print_format("%[' value.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s);
-
-          f_file_stream_unlock(main->error.to);
-
-          return F_status_set_error(F_parameter);
-        }
-
-        // Store last position as a relative offset from first instead of an absolute position.
-        data.last = (data.last - data.first) + 1;
-      }
-
-      if (main->pipe & fll_program_data_pipe_input_e) {
-        f_file_t file = f_file_t_initialize;
-
-        file.id = F_type_descriptor_input_d;
-        file.stream = F_type_input_d;
-
-        f_file_stream_lock(main->output.to);
-
-        f_print_dynamic_raw(f_string_eol_s, main->output.to);
-        fl_print_format("%[Piped " BYTE_DUMP_program_name_long_s ": (in ", main->output.to, main->context.set.title);
-
-        if (data.mode == byte_dump_mode_hexidecimal_e) {
-          f_print_dynamic_raw(byte_dump_print_strings_hexidecimal_s, main->output.to);
-        }
-        else if (data.mode == byte_dump_mode_duodecimal_e) {
-          f_print_dynamic_raw(byte_dump_print_strings_duodecimal_s, main->output.to);
-        }
-        else if (data.mode == byte_dump_mode_octal_e) {
-          f_print_dynamic_raw(byte_dump_print_strings_octal_s, main->output.to);
-        }
-        else if (data.mode == byte_dump_mode_binary_e) {
-          f_print_dynamic_raw(byte_dump_print_strings_binary_s, main->output.to);
-        }
-        else if (data.mode == byte_dump_mode_decimal_e) {
-          f_print_dynamic_raw(byte_dump_print_strings_decimal_s, main->output.to);
-        }
-
-        fl_print_format(")%]%r", main->output.to, main->context.set.title, f_string_eol_s);
-
-        f_file_stream_unlock(main->output.to);
-
-        status = byte_dump_file(&data, f_string_empty_s, file);
-
-        if (F_status_is_error(status)) {
-          fll_error_print(main->error, F_status_set_fine(status), "byte_dump_file", fll_error_file_flag_fallback_e);
-
-          return status;
-        }
-      }
-
-      if (main->parameters.remaining.used) {
-
-        // Pre-process remaining arguments to ensure that they all files exist before processing.
-        {
-          f_status_t missing_files = F_none;
-
-          for (f_number_unsigned_t counter = 0; counter < main->parameters.remaining.used; ++counter) {
-
-            status = f_file_exists(data.argv[main->parameters.remaining.array[counter]], F_true);
-
-            if (status == F_false) {
-              status = F_status_set_error(F_file_found_not);
-            }
-
-            if (F_status_is_error(status)) {
-              if (missing_files == F_none) {
-                missing_files = status;
-              }
-
-              fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", fll_error_file_flag_fallback_e, data.argv[main->parameters.remaining.array[counter]], f_file_operation_open_s, fll_error_file_type_file_e);
-            }
-          } // for
-
-          if (missing_files != F_none) {
-            status = F_status_set_error(missing_files);
-
-            return status;
-          }
-        }
-
-        f_file_t file = f_file_t_initialize;
-
-        for (f_number_unsigned_t counter = 0; counter < main->parameters.remaining.used; ++counter) {
-
-          status = f_file_stream_open(data.argv[main->parameters.remaining.array[counter]], f_string_empty_s, &file);
-
-          if (F_status_is_error(status)) {
-            fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", fll_error_file_flag_fallback_e, data.argv[main->parameters.remaining.array[counter]], f_file_operation_open_s, fll_error_file_type_file_e);
-
-            return status;
-          }
-
-          f_file_stream_lock(main->output.to);
-
-          fl_print_format("%r%[" BYTE_DUMP_program_name_long_s " of: %]%[", main->output.to, f_string_eol_s, main->context.set.title, main->context.set.title, main->context.set.notable);
-          fl_print_format("%Q%] %[(in ", main->output.to, data.argv[main->parameters.remaining.array[counter]], main->context.set.notable, main->context.set.title);
-
-          if (data.mode == byte_dump_mode_hexidecimal_e) {
-            f_print_dynamic_raw(byte_dump_print_strings_hexidecimal_s, main->output.to);
-          }
-          else if (data.mode == byte_dump_mode_duodecimal_e) {
-            f_print_dynamic_raw(byte_dump_print_strings_duodecimal_s, main->output.to);
-          }
-          else if (data.mode == byte_dump_mode_octal_e) {
-            f_print_dynamic_raw(byte_dump_print_strings_octal_s, main->output.to);
-          }
-          else if (data.mode == byte_dump_mode_binary_e) {
-            f_print_dynamic_raw(byte_dump_print_strings_binary_s, main->output.to);
-          }
-          else if (data.mode == byte_dump_mode_decimal_e) {
-            f_print_dynamic_raw(byte_dump_print_strings_decimal_s, main->output.to);
-          }
-
-          fl_print_format(")%]%r", main->output.to, main->context.set.title, f_string_eol_s);
-
-          f_file_stream_unlock(main->output.to);
-
-          status = byte_dump_file(&data, data.argv[main->parameters.remaining.array[counter]], file);
-
-          f_file_stream_flush(file);
-          f_file_stream_close(&file);
-
-          if (F_status_is_error(status)) {
-            if (F_status_set_fine(status) == F_interrupt) {
-
-              // 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) {
-                f_file_stream_flush(main->output.to);
-
-                fll_print_dynamic_raw(f_string_eol_s, main->output.to);
-              }
-            }
-            else {
-              if (main->error.verbosity > f_console_verbosity_quiet_e) {
-                fll_error_file_print(main->error, F_status_set_fine(status), "byte_dump_file", fll_error_file_flag_fallback_e, data.argv[main->parameters.remaining.array[counter]], f_file_operation_process_s, fll_error_file_type_file_e);
-              }
-            }
-
-            return status;
-          }
-        } // for
-      }
-      else {
-        status = F_false;
-      }
-    }
-    else {
-      fll_print_format("%r%[%QYou failed to specify one or more filenames.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
-
-      status = F_status_set_error(F_parameter);
-    }
-
-    return status;
-  }
-#endif // _di_byte_dump_main_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/byte_dump/c/byte_dump.h b/level_3/byte_dump/c/byte_dump.h
deleted file mode 100644 (file)
index e80e959..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Byte Dump
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- *
- * This is intended to support Unicode 15.0.
- *
- * When using "text" mode, this program attempts to translate UTF-8 sequences such that certain codes don't cause printing problems.
- * There may be cases where there are unknown codes that get printed and the invalid UTF-8 marker may be displayed not by this program but instead by the shell or some other program.
- * This can potentially be seen with the program "less".
- * The solution is to add the invalid character codes to this project so that this project can properly print the invalid UTF-8 marker and therefore properly display the information.
- */
-#ifndef _byte_dump_h
-#define _byte_dump_h
-
-// Libc includes.
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-// FLL-0 includes.
-#include <fll/level_0/type.h>
-#include <fll/level_0/status.h>
-#include <fll/level_0/memory.h>
-#include <fll/level_0/string.h>
-#include <fll/level_0/utf.h>
-#include <fll/level_0/color.h>
-#include <fll/level_0/compare.h>
-#include <fll/level_0/console.h>
-#include <fll/level_0/conversion.h>
-#include <fll/level_0/file.h>
-#include <fll/level_0/pipe.h>
-#include <fll/level_0/print.h>
-#include <fll/level_0/rip.h>
-#include <fll/level_0/signal.h>
-
-// FLL-1 includes.
-#include <fll/level_1/conversion.h>
-#include <fll/level_1/print.h>
-
-// FLL-2 includes.
-#include <fll/level_2/error.h>
-#include <fll/level_2/print.h>
-#include <fll/level_2/program.h>
-
-// Byte Dump includes.
-#include <program/byte_dump/common.h>
-#include <program/byte_dump/print.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Execute main program.
- *
- * @param main
- *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
- *
- * If main.signal is non-zero, then this blocks and handles the following signals:
- *   - F_signal_abort
- *   - F_signal_broken_pipe
- *   - F_signal_hangup
- *   - F_signal_interrupt
- *   - F_signal_quit
- *   - F_signal_termination
- *
- * @return
- *   F_none on success.
- *
- *   F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- *   F_parameter (with error bit) on an argument error.
- *
- *   Status codes (with error bit) are returned on any problem.
- */
-#ifndef _di_byte_dump_main_
-  extern f_status_t byte_dump_main(fll_program_data_t * const main, byte_dump_setting_t * const setting);
-#endif // _di_byte_dump_main_
-
-/**
- * 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_byte_dump_setting_delete_
-  extern f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting);
-#endif // _di_byte_dump_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_byte_dump_setting_load_
-  extern void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting);
-#endif // _di_byte_dump_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: byte_dump_setting_delete().
- *
- * @see byte_dump_setting_delete()
- */
-#ifndef _di_byte_dump_setting_unload_
-  extern f_status_t byte_dump_setting_unload(byte_dump_main_t * const main);
-#endif // _di_byte_dump_setting_unload_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _byte_dump_h
diff --git a/level_3/byte_dump/c/common.c b/level_3/byte_dump/c/common.c
deleted file mode 100644 (file)
index d951e0d..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "byte_dump.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_byte_dump_program_version_d_
-  const f_string_static_t byte_dump_program_version_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_version_s, 0, BYTE_DUMP_program_version_s_length);
-#endif // _di_byte_dump_program_version_d_
-
-#ifndef _di_byte_dump_program_name_s_
-  const f_string_static_t byte_dump_program_name_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_name_s, 0, BYTE_DUMP_program_name_s_length);
-  const f_string_static_t byte_dump_program_name_long_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_name_long_s, 0, BYTE_DUMP_program_name_long_s_length);
-#endif // _di_byte_dump_program_name_s_
-
-#ifndef _di_byte_dump_print_s_
-  const f_string_static_t byte_dump_print_strings_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_print_strings_hexidecimal_s, 0, BYTE_DUMP_print_strings_hexidecimal_s_length);
-  const f_string_static_t byte_dump_print_strings_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_print_strings_duodecimal_s, 0, BYTE_DUMP_print_strings_duodecimal_s_length);
-  const f_string_static_t byte_dump_print_strings_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_print_strings_octal_s, 0, BYTE_DUMP_print_strings_octal_s_length);
-  const f_string_static_t byte_dump_print_strings_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_print_strings_binary_s, 0, BYTE_DUMP_print_strings_binary_s_length);
-  const f_string_static_t byte_dump_print_strings_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_print_strings_decimal_s, 0, BYTE_DUMP_print_strings_decimal_s_length);
-#endif // _di_byte_dump_print_s_
-
-#ifndef _di_byte_dump_s_
-  const f_string_static_t byte_dump_character_wall_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_wall_s, 0, BYTE_DUMP_character_wall_s_length);
-  const f_string_static_t byte_dump_character_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_placeholder_s, 0, BYTE_DUMP_character_placeholder_s_length);
-  const f_string_static_t byte_dump_character_incomplete_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_incomplete_s, 0, BYTE_DUMP_character_incomplete_s_length);
-  const f_string_static_t byte_dump_character_unused_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_unused_s, 0, BYTE_DUMP_character_unused_s_length);
-#endif // _di_byte_dump_s_
-
-#ifndef _di_byte_dump_parameter_d_
-  const f_string_static_t byte_dump_short_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_binary_s, 0, BYTE_DUMP_short_binary_s_length);
-  const f_string_static_t byte_dump_short_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_decimal_s, 0, BYTE_DUMP_short_decimal_s_length);
-  const f_string_static_t byte_dump_short_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_duodecimal_s, 0, BYTE_DUMP_short_duodecimal_s_length);
-  const f_string_static_t byte_dump_short_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_hexidecimal_s, 0, BYTE_DUMP_short_hexidecimal_s_length);
-  const f_string_static_t byte_dump_short_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_octal_s, 0, BYTE_DUMP_short_octal_s_length);
-  const f_string_static_t byte_dump_short_unicode_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_unicode_s, 0, BYTE_DUMP_short_unicode_s_length);
-
-  const f_string_static_t byte_dump_short_first_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_first_s, 0, BYTE_DUMP_short_first_s_length);
-  const f_string_static_t byte_dump_short_last_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_last_s, 0, BYTE_DUMP_short_last_s_length);
-
-  const f_string_static_t byte_dump_short_narrow_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_narrow_s, 0, BYTE_DUMP_short_narrow_s_length);
-  const f_string_static_t byte_dump_short_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_placeholder_s, 0, BYTE_DUMP_short_placeholder_s_length);
-  const f_string_static_t byte_dump_short_text_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_text_s, 0, BYTE_DUMP_short_text_s_length);
-  const f_string_static_t byte_dump_short_wide_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_wide_s, 0, BYTE_DUMP_short_wide_s_length);
-  const f_string_static_t byte_dump_short_width_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_width_s, 0, BYTE_DUMP_short_width_s_length);
-
-  const f_string_static_t byte_dump_long_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_binary_s, 0, BYTE_DUMP_long_binary_s_length);
-  const f_string_static_t byte_dump_long_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_decimal_s, 0, BYTE_DUMP_long_decimal_s_length);
-  const f_string_static_t byte_dump_long_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_duodecimal_s, 0, BYTE_DUMP_long_duodecimal_s_length);
-  const f_string_static_t byte_dump_long_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_hexidecimal_s, 0, BYTE_DUMP_long_hexidecimal_s_length);
-  const f_string_static_t byte_dump_long_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_octal_s, 0, BYTE_DUMP_long_octal_s_length);
-  const f_string_static_t byte_dump_long_unicode_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_unicode_s, 0, BYTE_DUMP_long_unicode_s_length);
-
-  const f_string_static_t byte_dump_long_first_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_first_s, 0, BYTE_DUMP_long_first_s_length);
-  const f_string_static_t byte_dump_long_last_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_last_s, 0, BYTE_DUMP_long_last_s_length);
-
-  const f_string_static_t byte_dump_long_narrow_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_narrow_s, 0, BYTE_DUMP_long_narrow_s_length);
-  const f_string_static_t byte_dump_long_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_placeholder_s, 0, BYTE_DUMP_long_placeholder_s_length);
-  const f_string_static_t byte_dump_long_text_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_text_s, 0, BYTE_DUMP_long_text_s_length);
-  const f_string_static_t byte_dump_long_wide_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_wide_s, 0, BYTE_DUMP_long_wide_s_length);
-  const f_string_static_t byte_dump_long_width_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_width_s, 0, BYTE_DUMP_long_width_s_length);
-
-  const f_string_static_t byte_dump_long_normal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_normal_s, 0, BYTE_DUMP_long_normal_s_length);
-  const f_string_static_t byte_dump_long_simple_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_simple_s, 0, BYTE_DUMP_long_simple_s_length);
-  const f_string_static_t byte_dump_long_classic_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_classic_s, 0, BYTE_DUMP_long_classic_s_length);
-#endif // _di_byte_dump_parameter_d_
-
-#ifndef _di_byte_dump_setting_delete_
-  f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting) {
-
-    if (!setting) return F_status_set_error(F_parameter);
-
-    return F_none;
-  }
-#endif // _di_byte_dump_setting_delete_
-
-#ifndef _di_byte_dump_setting_load_
-  void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting) {
-
-    if (!main) return;
-
-    main->setting.state.step_small = byte_dump_allocation_console_d;
-
-    f_console_parameter_process(arguments, &main->program.parameters, &main->setting.state, 0);
-
-    main->setting.state.step_small = byte_dump_allocation_small_d;
-
-    // Identify and pocess first/last parameters.
-    if (main->program.parameters.array[byte_dump_parameter_line_first_no_e].result & f_console_result_found_e) {
-      main->setting.flag -= main->setting.flag & byte_dump_main_flag_print_first_e;
-    }
-    else {
-      main->setting.flag |= byte_dump_main_flag_print_first_e;
-    }
-
-    if (main->program.parameters.array[byte_dump_parameter_line_last_no_e].result & f_console_result_found_e) {
-      main->setting.flag -= main->setting.flag & byte_dump_main_flag_print_last_e;
-    }
-    else {
-      main->setting.flag |= byte_dump_main_flag_print_last_e;
-    }
-
-    if (F_status_is_error(main->setting.state.status)) {
-      fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_console_parameter_process", fll_error_file_flag_fallback_e);
-
-      if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
-        fll_print_dynamic_raw(f_string_eol_s, main->program.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] = { byte_dump_parameter_no_color_e, byte_dump_parameter_light_e, byte_dump_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 };
-
-        main->setting.state.status = fll_program_parameter_process_context(choices, modes, F_true, &main->program);
-
-        if (F_status_is_error(main->setting.state.status)) {
-          fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "fll_program_parameter_process_context", fll_error_file_flag_fallback_e);
-
-          if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->program.error);
-          }
-
-          return;
-        }
-      }
-
-      // Identify and prioritize "verbosity" parameters.
-      {
-        uint16_t choices_array[5] = { byte_dump_parameter_verbosity_quiet_e, byte_dump_parameter_verbosity_error_e, byte_dump_parameter_verbosity_verbose_e, byte_dump_parameter_verbosity_debug_e, byte_dump_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 };
-
-        main->setting.state.status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program);
-
-        if (F_status_is_error(main->setting.state.status)) {
-          fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "fll_program_parameter_process_verbosity", fll_error_file_flag_fallback_e);
-
-          if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
-            fll_print_dynamic_raw(f_string_eol_s, main->program.error);
-          }
-
-          return;
-        }
-      }
-    }
-
-    main->program.output.to.id = F_type_descriptor_output_d;
-    main->program.output.to.stream = F_type_output_d;
-    main->program.output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d;
-
-    if (main->program.parameters.array[byte_dump_parameter_help_e].result & f_console_result_found_e) {
-      main->setting.flag |= byte_dump_main_flag_help_e;
-
-      return;
-    }
-
-    if (main->program.parameters.array[byte_dump_parameter_version_e].result & f_console_result_found_e) {
-      main->setting.flag |= byte_dump_main_flag_version_e;
-
-      return;
-    }
-
-    f_string_static_t * const args = main->program.parameters.arguments.array;
-
-    if (main->program.parameters.array[byte_dump_parameter_strip_invalid_e].result & f_console_result_found_e) {
-      main->setting.flag |= byte_dump_main_flag_strip_invalid_e;
-    }
-  }
-#endif // _di_byte_dump_setting_load_
-
-#ifndef _di_byte_dump_setting_unload_
-  f_status_t byte_dump_setting_unload(byte_dump_main_t * const main) {
-
-    if (!main) return F_status_set_error(F_parameter);
-
-    byte_dump_setting_delete(&main->setting);
-
-    return F_none;
-  }
-#endif // _di_byte_dump_setting_unload_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/byte_dump/c/common.h b/level_3/byte_dump/c/common.h
deleted file mode 100644 (file)
index 62c272d..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Byte Dump
- * 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 _byte_dump_common_h
-#define _byte_dump_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The program version.
- */
-#ifndef _di_byte_dump_program_version_d_
-  #define BYTE_DUMP_program_version_major_s F_string_ascii_0_s
-  #define BYTE_DUMP_program_version_minor_s F_string_ascii_7_s
-  #define BYTE_DUMP_program_version_micro_s F_string_ascii_0_s
-
-  #define BYTE_DUMP_program_version_major_s_length F_string_ascii_0_s_length
-  #define BYTE_DUMP_program_version_minor_s_length F_string_ascii_7_s_length
-  #define BYTE_DUMP_program_version_micro_s_length F_string_ascii_0_s_length
-
-  #if !(defined(BYTE_DUMP_program_version_nano_prefix_s) && defined(BYTE_DUMP_program_version_nano_prefix_s_length))
-    #define BYTE_DUMP_program_version_nano_prefix_s
-    #define BYTE_DUMP_program_version_nano_prefix_s_length 0
-  #endif // !(defined(BYTE_DUMP_program_version_nano_prefix_s) && defined(BYTE_DUMP_program_version_nano_prefix_s_length))
-
-  #if !(defined(BYTE_DUMP_program_version_nano_s) && defined(BYTE_DUMP_program_version_nano_s_length))
-    #define BYTE_DUMP_program_version_nano_s
-    #define BYTE_DUMP_program_version_nano_s_length 0
-  #endif // !(defined(BYTE_DUMP_program_version_nano_s) && defined(BYTE_DUMP_program_version_nano_s_length))
-
-  #define BYTE_DUMP_program_version_s BYTE_DUMP_program_version_major_s F_string_ascii_period_s BYTE_DUMP_program_version_minor_s F_string_ascii_period_s BYTE_DUMP_program_version_micro_s BYTE_DUMP_program_version_nano_prefix_s BYTE_DUMP_program_version_nano_s
-
-  #define BYTE_DUMP_program_version_s_length BYTE_DUMP_program_version_major_s_length + F_string_ascii_period_s_length + BYTE_DUMP_program_version_minor_s_length + F_string_ascii_period_s_length + BYTE_DUMP_program_version_micro_s_length + BYTE_DUMP_program_version_nano_prefix_s_length + BYTE_DUMP_program_version_nano_s_length
-
-  extern const f_string_static_t byte_dump_program_version_s;
-#endif // _di_byte_dump_program_version_d_
-
-/**
- * The program name.
- */
-#ifndef _di_byte_dump_program_name_s_
-  #define BYTE_DUMP_program_name_s      "byte_dump"
-  #define BYTE_DUMP_program_name_long_s "Byte Dump"
-
-  #define BYTE_DUMP_program_name_s_length      9
-  #define BYTE_DUMP_program_name_long_s_length 9
-
-  extern const f_string_static_t byte_dump_program_name_s;
-  extern const f_string_static_t byte_dump_program_name_long_s;
-#endif // _di_byte_dump_program_name_s_
-
-/**
- * The program defines.
- *
- * byte_dump_*_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_byte_dump_d_
-  #define byte_dump_allocation_console_d 4
-  #define byte_dump_allocation_large_d   256
-  #define byte_dump_allocation_small_d   16
-  #define byte_dump_signal_check_d       20000
-#endif // _di_byte_dump_d_
-
-/**
- * The program strings for printing.
- */
-#ifndef _di_byte_dump_print_s_
-  #define BYTE_DUMP_print_strings_hexidecimal_s "Hexidecimal"
-  #define BYTE_DUMP_print_strings_duodecimal_s  "Duodecimal"
-  #define BYTE_DUMP_print_strings_octal_s       "Octal"
-  #define BYTE_DUMP_print_strings_binary_s      "Binary"
-  #define BYTE_DUMP_print_strings_decimal_s     "Decimal"
-
-  #define BYTE_DUMP_print_strings_hexidecimal_s_length 11
-  #define BYTE_DUMP_print_strings_duodecimal_s_length  10
-  #define BYTE_DUMP_print_strings_octal_s_length       5
-  #define BYTE_DUMP_print_strings_binary_s_length      6
-  #define BYTE_DUMP_print_strings_decimal_s_length     7
-
-  extern const f_string_static_t byte_dump_print_strings_hexidecimal_s;
-  extern const f_string_static_t byte_dump_print_strings_duodecimal_s;
-  extern const f_string_static_t byte_dump_print_strings_octal_s;
-  extern const f_string_static_t byte_dump_print_strings_binary_s;
-  extern const f_string_static_t byte_dump_print_strings_decimal_s;
-#endif // _di_byte_dump_print_s_
-
-/**
- * Set to at least 4 to provide a UTF-8 friendly allocation step.
- */
-#ifndef _di_byte_dump_default_d_
-  #define byte_dump_default_allocation_step_d 4
-#endif // _di_byte_dump_default_d_
-
-/**
- * The program defines.
- */
-#ifndef _di_byte_dump_d_
-  #define byte_dump_option_wide_d 0x1
-
-  #define byte_dump_signal_check_d 20000
-#endif // _di_byte_dump_d_
-
-/**
- * The program enumerations.
- *
- * byte_dump_mode_*:
- *   - hexidecimal: Display using hexidecimal notation (base 16).
- *   - duodecimal:  Display using duodecimal notation (base 12).
- *   - octal:       Display using octal notation (base 8).
- *   - binary:      Display using binary notation (base 2).
- *   - decimal:     Display using decimal notation (base 10).
- *
- * byte_dump_presentation_*:
- *   - normal:  Normal presentation mode.
- *   - simple:  Simple presentation mode.
- *   - classic: Classic presentation mode.
- */
-#ifndef _di_byte_dump_e_
-  enum {
-    byte_dump_mode_hexidecimal_e = 1,
-    byte_dump_mode_duodecimal_e,
-    byte_dump_mode_octal_e,
-    byte_dump_mode_binary_e,
-    byte_dump_mode_decimal_e,
-  }; // enum
-
-  enum {
-    byte_dump_presentation_normal_e = 1,
-    byte_dump_presentation_simple_e,
-    byte_dump_presentation_classic_e,
-  }; // enum
-#endif // _di_byte_dump_e_
-
-/**
- * The program strings.
- */
-#ifndef _di_byte_dump_s_
-  #define BYTE_DUMP_character_wall_s        "|"
-  #define BYTE_DUMP_character_placeholder_s "␣" // Other likely choices: (substitute form 1: '␚', substitute form 2: '␦').
-  #define BYTE_DUMP_character_incomplete_s  "�"
-  #define BYTE_DUMP_character_unused_s      "�"
-
-  #define BYTE_DUMP_character_wall_s_length        1
-  #define BYTE_DUMP_character_placeholder_s_length 3
-  #define BYTE_DUMP_character_incomplete_s_length  3
-  #define BYTE_DUMP_character_unused_s_length      3
-
-  extern const f_string_static_t byte_dump_character_wall_s;
-  extern const f_string_static_t byte_dump_character_placeholder_s;
-  extern const f_string_static_t byte_dump_character_incomplete_s;
-  extern const f_string_static_t byte_dump_character_unused_s;
-#endif // _di_byte_dump_s_
-
-/**
- * The program parameters.
- *
- * byte_dump_long_*:
- *   - first: First offset byte size.
- *   - last:  Last offset byte size.
- *
- *   - narrow:      Each character in the displyed text will take at least 1 columns.
- *   - placeholder: Display (colored) placeholders to signify codes that are UTF-8 fragments.
- *   - text:        Display text
- *   - wide:        Each character in the displyed text will take at least 2 columns.
- *   - width:       Number of characters to display per row.
- *
- *   - binary:      Display using binary format.
- *   - decimal:     Display using decimal format.
- *   - duodecimal:  Display using duodecimal format.
- *   - hexidecimal: Display using hexidecimal format.
- *   - octal:       Display using octal format.
- *   - unicode:     Display using Unicode format.
- *
- *   - normal:  Use normal presentation, displaying UTF-8 sequence codes for ASCII special codes.
- *   - simple:  Use simple presentation, displaying spaces for ASCII special codes instead of UTF-8 sequence codes.
- *   - classic: Use classic presentation, displaying periods for ASCII special codes instead of UTF-8 sequence codes.
- */
-#ifndef _di_byte_dump_parameter_d_
-  #define BYTE_DUMP_short_binary_s      "b"
-  #define BYTE_DUMP_short_decimal_s     "d"
-  #define BYTE_DUMP_short_duodecimal_s  "D"
-  #define BYTE_DUMP_short_hexidecimal_s "x"
-  #define BYTE_DUMP_short_octal_s       "o"
-  #define BYTE_DUMP_short_unicode_s     "U"
-
-  #define BYTE_DUMP_short_first_s       "f"
-  #define BYTE_DUMP_short_last_s        "l"
-
-  #define BYTE_DUMP_short_narrow_s      "N"
-  #define BYTE_DUMP_short_placeholder_s "p"
-  #define BYTE_DUMP_short_text_s        "t"
-  #define BYTE_DUMP_short_wide_s        "W"
-  #define BYTE_DUMP_short_width_s       "w"
-
-  #define BYTE_DUMP_long_binary_s      "binary"
-  #define BYTE_DUMP_long_decimal_s     "decimal"
-  #define BYTE_DUMP_long_duodecimal_s  "duodecimal"
-  #define BYTE_DUMP_long_hexidecimal_s "hexidecimal"
-  #define BYTE_DUMP_long_octal_s       "octal"
-  #define BYTE_DUMP_long_unicode_s     "unicode"
-
-  #define BYTE_DUMP_long_first_s "first"
-  #define BYTE_DUMP_long_last_s  "last"
-
-  #define BYTE_DUMP_long_narrow_s      "narrow"
-  #define BYTE_DUMP_long_placeholder_s "placeholder"
-  #define BYTE_DUMP_long_text_s        "text"
-  #define BYTE_DUMP_long_wide_s        "wide"
-  #define BYTE_DUMP_long_width_s       "width"
-
-  #define BYTE_DUMP_long_normal_s  "normal"
-  #define BYTE_DUMP_long_simple_s  "simple"
-  #define BYTE_DUMP_long_classic_s "classic"
-
-  #define BYTE_DUMP_short_binary_s_length      1
-  #define BYTE_DUMP_short_decimal_s_length     1
-  #define BYTE_DUMP_short_duodecimal_s_length  1
-  #define BYTE_DUMP_short_hexidecimal_s_length 1
-  #define BYTE_DUMP_short_octal_s_length       1
-  #define BYTE_DUMP_short_unicode_s_length     1
-
-  #define BYTE_DUMP_short_first_s_length       1
-  #define BYTE_DUMP_short_last_s_length        1
-
-  #define BYTE_DUMP_short_narrow_s_length      1
-  #define BYTE_DUMP_short_placeholder_s_length 1
-  #define BYTE_DUMP_short_text_s_length        1
-  #define BYTE_DUMP_short_wide_s_length        1
-  #define BYTE_DUMP_short_width_s_length       1
-
-  #define BYTE_DUMP_long_binary_s_length      6
-  #define BYTE_DUMP_long_decimal_s_length     7
-  #define BYTE_DUMP_long_duodecimal_s_length  10
-  #define BYTE_DUMP_long_hexidecimal_s_length 11
-  #define BYTE_DUMP_long_octal_s_length       5
-  #define BYTE_DUMP_long_unicode_s_length     7
-
-  #define BYTE_DUMP_long_first_s_length 5
-  #define BYTE_DUMP_long_last_s_length  4
-
-  #define BYTE_DUMP_long_narrow_s_length      6
-  #define BYTE_DUMP_long_placeholder_s_length 11
-  #define BYTE_DUMP_long_text_s_length        4
-  #define BYTE_DUMP_long_wide_s_length        4
-  #define BYTE_DUMP_long_width_s_length       5
-
-  #define BYTE_DUMP_long_normal_s_length  6
-  #define BYTE_DUMP_long_simple_s_length  6
-  #define BYTE_DUMP_long_classic_s_length 7
-
-  extern const f_string_static_t byte_dump_short_binary_s;
-  extern const f_string_static_t byte_dump_short_decimal_s;
-  extern const f_string_static_t byte_dump_short_duodecimal_s;
-  extern const f_string_static_t byte_dump_short_hexidecimal_s;
-  extern const f_string_static_t byte_dump_short_octal_s;
-  extern const f_string_static_t byte_dump_short_unicode_s;
-
-  extern const f_string_static_t byte_dump_short_first_s;
-  extern const f_string_static_t byte_dump_short_last_s;
-
-  extern const f_string_static_t byte_dump_short_narrow_s;
-  extern const f_string_static_t byte_dump_short_placeholder_s;
-  extern const f_string_static_t byte_dump_short_text_s;
-  extern const f_string_static_t byte_dump_short_wide_s;
-  extern const f_string_static_t byte_dump_short_width_s;
-
-  extern const f_string_static_t byte_dump_long_binary_s;
-  extern const f_string_static_t byte_dump_long_decimal_s;
-  extern const f_string_static_t byte_dump_long_duodecimal_s;
-  extern const f_string_static_t byte_dump_long_hexidecimal_s;
-  extern const f_string_static_t byte_dump_long_octal_s;
-  extern const f_string_static_t byte_dump_long_unicode_s;
-
-  extern const f_string_static_t byte_dump_long_first_s;
-  extern const f_string_static_t byte_dump_long_last_s;
-
-  extern const f_string_static_t byte_dump_long_narrow_s;
-  extern const f_string_static_t byte_dump_long_placeholder_s;
-  extern const f_string_static_t byte_dump_long_text_s;
-  extern const f_string_static_t byte_dump_long_wide_s;
-  extern const f_string_static_t byte_dump_long_width_s;
-
-  extern const f_string_static_t byte_dump_long_normal_s;
-  extern const f_string_static_t byte_dump_long_simple_s;
-  extern const f_string_static_t byte_dump_long_classic_s;
-
-  enum {
-    byte_dump_parameter_help_e,
-    byte_dump_parameter_copyright_e,
-    byte_dump_parameter_light_e,
-    byte_dump_parameter_dark_e,
-    byte_dump_parameter_no_color_e,
-    byte_dump_parameter_verbosity_quiet_e,
-    byte_dump_parameter_verbosity_error_e,
-    byte_dump_parameter_verbosity_normal_e,
-    byte_dump_parameter_verbosity_verbose_e,
-    byte_dump_parameter_verbosity_debug_e,
-    byte_dump_parameter_version_e,
-    byte_dump_parameter_line_first_no_e,
-    byte_dump_parameter_line_last_no_e,
-
-    byte_dump_parameter_binary_e,
-    byte_dump_parameter_decimal_e,
-    byte_dump_parameter_duodecimal_e,
-    byte_dump_parameter_hexidecimal_e,
-    byte_dump_parameter_octal_e,
-    byte_dump_parameter_unicode_e,
-
-    byte_dump_parameter_first_e,
-    byte_dump_parameter_last_e,
-
-    byte_dump_parameter_narrow_e,
-    byte_dump_parameter_placeholder_e,
-    byte_dump_parameter_text_e,
-    byte_dump_parameter_wide_e,
-    byte_dump_parameter_width_e,
-
-    byte_dump_parameter_normal_e,
-    byte_dump_parameter_simple_e,
-    byte_dump_parameter_classic_e,
-  }; // enum
-
-  #define byte_dump_console_parameter_t_initialize \
-    { \
-      macro_fll_program_console_parameter_standard_initialize, \
-      \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_binary_s,      byte_dump_long_binary_s,      0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_decimal_s,     byte_dump_long_decimal_s,     0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_duodecimal_s,  byte_dump_long_duodecimal_s,  0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_hexidecimal_s, byte_dump_long_hexidecimal_s, 0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_octal_s,       byte_dump_long_octal_s,       0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_unicode_s,     byte_dump_long_unicode_s,     0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_first_s,       byte_dump_long_first_s,       1, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_last_s,        byte_dump_long_last_s,        1, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_narrow_s,      byte_dump_long_narrow_s,      0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_placeholder_s, byte_dump_long_placeholder_s, 0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_text_s,        byte_dump_long_text_s,        0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_wide_s,        byte_dump_long_wide_s,        0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_3(byte_dump_short_width_s,       byte_dump_long_width_s,       1, f_console_flag_normal_e), \
-      \
-      macro_f_console_parameter_t_initialize_5(byte_dump_long_normal_s, 0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_5(byte_dump_long_simple_s, 0, f_console_flag_normal_e), \
-      macro_f_console_parameter_t_initialize_5(byte_dump_long_classic_s, 0, f_console_flag_normal_e), \
-    }
-
-  #define byte_dump_parameter_total_d 29
-#endif // _di_byte_dump_parameter_d_
-
-/**
- * Flags passed to the main function or program.
- *
- * byte_dump_main_flag_*_e:
- *   - none:          No flags set.
- *   - file_from:     Using a specified source file.
- *   - file_to:       Using a specified destination file.
- *   - help:          Print help.
- *   - header:        Enable printing of headers.
- *   - 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_byte_dump_main_flag_e_
-  enum {
-    byte_dump_main_flag_none_e          = 0x0,
-    byte_dump_main_flag_file_from_e     = 0x1,
-    byte_dump_main_flag_file_to_e       = 0x2,
-    byte_dump_main_flag_header_e        = 0x4,
-    byte_dump_main_flag_help_e          = 0x8,
-    byte_dump_main_flag_print_first_e   = 0x10,
-    byte_dump_main_flag_print_last_e    = 0x20,
-    byte_dump_main_flag_separate_e      = 0x40,
-    byte_dump_main_flag_strip_invalid_e = 0x80,
-    byte_dump_main_flag_verify_e        = 0x100,
-    byte_dump_main_flag_version_e       = 0x200,
-  }; // enum
-#endif // _di_byte_dump_main_flag_e_
-
-/**
- * The byte dump 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.
- *   - state: The state information.
- */
-#ifndef _di_byte_dump_setting_t_
-  typedef struct {
-    uint16_t flag;
-
-    f_state_t state;
-  } byte_dump_setting_t;
-
-  #define byte_dump_setting_t_initialize \
-    { \
-      byte_dump_main_flag_none_e, \
-      f_state_t_initialize, \
-    }
-#endif // _di_byte_dump_setting_t_
-
-/**
- * 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: f_file_stream_open().
- *     Errors (with error bit) from: f_string_dynamics_resize().
- *     Errors (with error bit) from: fll_program_parameter_process_context().
- *     Errors (with error bit) from: fll_program_parameter_process_verbosity().
- * @param state
- *   A state for providing flags and handling interrupts during long running operations.
- *
- * @see f_console_parameter_process()
- * @see f_file_stream_open()
- * @see f_string_dynamics_resize()
- * @see fll_program_parameter_process_context()
- * @see fll_program_parameter_process_verbosity()
- */
-#ifndef _di_byte_dump_setting_load_
-  extern void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting);
-#endif // _di_byte_dump_setting_load_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _byte_dump_common_h
diff --git a/level_3/byte_dump/c/main/byte_dump.c b/level_3/byte_dump/c/main/byte_dump.c
new file mode 100644 (file)
index 0000000..a47adbf
--- /dev/null
@@ -0,0 +1,101 @@
+#include "byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_main_
+  void byte_dump_main(byte_dump_main_t * const main) {
+
+    if (!main) return;
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & byte_dump_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 & byte_dump_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 & (byte_dump_main_flag_help_e | byte_dump_main_flag_version_e | byte_dump_main_flag_copyright_e)) {
+      if (main->setting.flag & byte_dump_main_flag_help_e) {
+        byte_dump_print_message_help(&main->program.message);
+      }
+      else if (main->setting.flag & byte_dump_main_flag_version_e) {
+        fll_program_print_version(&main->program.message, byte_dump_program_version_s);
+      }
+      else if (main->setting.flag & byte_dump_main_flag_copyright_e) {
+        fll_program_print_copyright(&main->program.message);
+      }
+
+      if ((main->setting.flag & byte_dump_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.files.used || (main->program.pipe & fll_program_data_pipe_input_e)) {
+      f_file_t file = f_file_t_initialize;
+
+      if (main->program.pipe & fll_program_data_pipe_input_e) {
+        file.id = F_type_descriptor_input_d;
+        file.stream = F_type_input_d;
+
+        byte_dump_print_file_header(&main->program.output, f_string_empty_s);
+
+        byte_dump_process_file(main, f_string_empty_s, file);
+      }
+
+      if (main->setting.files.used && F_status_is_error_not(main->setting.state.status)) {
+        file.id = -1;
+        file.stream = 0;
+
+        for (f_number_unsigned_t i = 0; i < main->setting.files.used; ++i) {
+
+          if (byte_dump_signal_check(main)) break;
+          if (!main->setting.files.array[i].used) continue;
+
+          main->setting.state.status = f_file_stream_open(main->setting.files.array[i], f_string_empty_s, &file);
+
+          if (F_status_is_error(main->setting.state.status)) {
+            byte_dump_print_error_file(&main->program.error, macro_byte_dump_f(f_file_stream_open), main->setting.files.array[i], f_file_operation_open_s, fll_error_file_type_file_e);
+
+            break;
+          }
+
+          byte_dump_print_file_header(&main->program.output, main->setting.files.array[i]);
+
+          byte_dump_process_file(main, main->setting.files.array[i], file);
+
+          f_file_stream_flush(file);
+          f_file_stream_close(&file);
+
+          if (F_status_is_error(main->setting.state.status)) break;
+        } // for
+      }
+      else {
+        main->setting.state.status = F_false;
+      }
+    }
+    else {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      byte_dump_print_error_file_none(&main->program.error);
+    }
+
+    if ((main->setting.flag & byte_dump_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);
+    }
+  }
+#endif // _di_byte_dump_main_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/byte_dump.h b/level_3/byte_dump/c/main/byte_dump.h
new file mode 100644 (file)
index 0000000..8d89d8c
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This is intended to support Unicode 15.0.
+ *
+ * When using "text" mode, this program attempts to translate UTF-8 sequences such that certain codes don't cause printing problems.
+ * There may be cases where there are unknown codes that get printed and the invalid UTF-8 marker may be displayed not by this program but instead by the shell or some other program.
+ * This can potentially be seen with the program "less".
+ * The solution is to add the invalid character codes to this project so that this project can properly print the invalid UTF-8 marker and therefore properly display the information.
+ */
+#ifndef _byte_dump_h
+#define _byte_dump_h
+
+// Libc includes.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// FLL-0 includes.
+#include <fll/level_0/type.h>
+#include <fll/level_0/status.h>
+#include <fll/level_0/memory.h>
+#include <fll/level_0/string.h>
+#include <fll/level_0/utf.h>
+#include <fll/level_0/color.h>
+#include <fll/level_0/compare.h>
+#include <fll/level_0/console.h>
+#include <fll/level_0/conversion.h>
+#include <fll/level_0/file.h>
+#include <fll/level_0/pipe.h>
+#include <fll/level_0/print.h>
+#include <fll/level_0/rip.h>
+#include <fll/level_0/signal.h>
+#include <fll/level_0/thread.h>
+
+// FLL-1 includes.
+#include <fll/level_1/conversion.h>
+#include <fll/level_1/print.h>
+
+// FLL-2 includes.
+#include <fll/level_2/error.h>
+#include <fll/level_2/print.h>
+#include <fll/level_2/program.h>
+
+// Byte Dump includes.
+#include <program/byte_dump/main/common/define.h>
+#include <program/byte_dump/main/common/enumeration.h>
+#include <program/byte_dump/main/common/print.h>
+#include <program/byte_dump/main/common/string.h>
+#include <program/byte_dump/main/common/type.h>
+#include <program/byte_dump/main/common.h>
+#include <program/byte_dump/main/print/data.h>
+#include <program/byte_dump/main/print/error.h>
+#include <program/byte_dump/main/print/message.h>
+#include <program/byte_dump/main/process.h>
+#include <program/byte_dump/main/signal.h>
+#include <program/byte_dump/main/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Execute main program.
+ *
+ * If main.signal is non-zero, then this blocks and 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 data and settings.
+ *
+ *   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.
+ *
+ *     F_interrupt (with error bit) on (exit) signal received.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
+ */
+#ifndef _di_byte_dump_main_
+  extern void byte_dump_main(byte_dump_main_t * const main);
+#endif // _di_byte_dump_main_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_h
diff --git a/level_3/byte_dump/c/main/common.c b/level_3/byte_dump/c/main/common.c
new file mode 100644 (file)
index 0000000..724557a
--- /dev/null
@@ -0,0 +1,404 @@
+#include "byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_setting_load_
+  void byte_dump_setting_load(const f_console_arguments_t arguments, byte_dump_main_t * const main) {
+
+    if (!main) return;
+
+    main->setting.state.step_small = byte_dump_allocation_console_d;
+
+    f_console_parameter_process(arguments, &main->program.parameters, &main->setting.state, 0);
+
+    main->setting.state.step_small = byte_dump_allocation_small_d;
+
+    // Identify and process first/last parameters.
+    if (main->program.parameters.array[byte_dump_parameter_line_first_no_e].result & f_console_result_found_e) {
+      main->setting.flag -= main->setting.flag & byte_dump_main_flag_print_first_e;
+    }
+    else {
+      main->setting.flag |= byte_dump_main_flag_print_first_e;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_line_last_no_e].result & f_console_result_found_e) {
+      main->setting.flag -= main->setting.flag & byte_dump_main_flag_print_last_e;
+    }
+    else {
+      main->setting.flag |= byte_dump_main_flag_print_last_e;
+    }
+
+    if (F_status_is_error(main->setting.state.status)) {
+      if ((main->setting.flag & byte_dump_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);
+      }
+
+      byte_dump_print_error(&main->program.error, macro_byte_dump_f(f_console_parameter_process));
+
+      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] = { byte_dump_parameter_no_color_e, byte_dump_parameter_light_e, byte_dump_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 };
+
+        main->setting.state.status = fll_program_parameter_process_context(choices, modes, F_true, &main->program);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          byte_dump_print_error(&main->program.error, macro_byte_dump_f(fll_program_parameter_process_context));
+
+          return;
+        }
+      }
+
+      // Identify and prioritize "verbosity" parameters.
+      {
+        uint16_t choices_array[5] = { byte_dump_parameter_verbosity_quiet_e, byte_dump_parameter_verbosity_error_e, byte_dump_parameter_verbosity_verbose_e, byte_dump_parameter_verbosity_debug_e, byte_dump_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 };
+
+        main->setting.state.status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          byte_dump_print_error(&main->program.error, macro_byte_dump_f(fll_program_parameter_process_verbosity));
+
+          return;
+        }
+      }
+
+      // Identify priority of mode parameters.
+      {
+        uint16_t choices_array[5] = { byte_dump_parameter_hexidecimal_e, byte_dump_parameter_duodecimal_e, byte_dump_parameter_octal_e, byte_dump_parameter_binary_e, byte_dump_parameter_decimal_e };
+        choices.array = choices_array;
+        choices.used = 5;
+        choice = 0;
+
+        main->setting.state.status = f_console_parameter_prioritize_right(main->program.parameters, choices, &choice);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          byte_dump_print_error(&main->program.error, macro_byte_dump_f(f_console_parameter_prioritize_right));
+
+          return;
+        }
+
+        if (choices.array[choice] == byte_dump_parameter_hexidecimal_e) {
+          main->setting.mode = byte_dump_mode_hexidecimal_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_duodecimal_e) {
+          main->setting.mode = byte_dump_mode_duodecimal_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_octal_e) {
+          main->setting.mode = byte_dump_mode_octal_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_binary_e) {
+          main->setting.mode = byte_dump_mode_binary_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_decimal_e) {
+          main->setting.mode = byte_dump_mode_decimal_e;
+        }
+      }
+
+      // Identify priority of presentation parameters.
+      {
+        uint16_t choices_array[3] = { byte_dump_parameter_normal_e, byte_dump_parameter_simple_e, byte_dump_parameter_classic_e };
+        choices.array = choices_array;
+        choices.used = 3;
+        choice = 0;
+
+        main->setting.state.status = f_console_parameter_prioritize_right(main->program.parameters, choices, &choice);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          byte_dump_print_error(&main->program.error, macro_byte_dump_f(f_console_parameter_prioritize_right));
+
+          return;
+        }
+
+        if (choices.array[choice] == byte_dump_parameter_normal_e) {
+          main->setting.presentation = byte_dump_presentation_normal_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_simple_e) {
+          main->setting.presentation = byte_dump_presentation_simple_e;
+        }
+        else if (choices.array[choice] == byte_dump_parameter_classic_e) {
+          main->setting.presentation = byte_dump_presentation_classic_e;
+        }
+      }
+
+      // Identify priority of narrow and wide parameters.
+      {
+        uint16_t choices_array[2] = { byte_dump_parameter_narrow_e, byte_dump_parameter_wide_e };
+        choices.array = choices_array;
+        choices.used = 2;
+        choice = 1;
+
+        main->setting.state.status = f_console_parameter_prioritize_right(main->program.parameters, choices, &choice);
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          byte_dump_print_error(&main->program.error, macro_byte_dump_f(f_console_parameter_prioritize_right));
+
+          return;
+        }
+
+        if (choices.array[choice] == byte_dump_parameter_narrow_e) {
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            main->setting.flag -= byte_dump_main_flag_wide_e;
+          }
+        }
+        else if (choices.array[choice] == byte_dump_parameter_wide_e) {
+          main->setting.flag |= byte_dump_main_flag_wide_e;
+        }
+      }
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_help_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_help_e;
+
+      return;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_version_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_version_e;
+
+      return;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_copyright_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_copyright_e;
+
+      return;
+    }
+
+    f_number_unsigned_t index = 0;
+    f_number_unsigned_t number = 0;
+
+    if (main->program.parameters.array[byte_dump_parameter_width_e].result & f_console_result_value_e) {
+      index = main->program.parameters.array[byte_dump_parameter_width_e].values.array[main->program.parameters.array[byte_dump_parameter_width_e].values.used - 1];
+
+      main->setting.state.status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, main->program.parameters.arguments.array[index], &number);
+
+      // Negative numbers are not supported.
+      if (main->setting.state.status == F_number_negative) {
+        main->setting.state.status = F_status_set_error(F_number_negative);
+      }
+
+      if (F_status_is_error(main->setting.state.status) || number < 0x1 || number >= 0xfb) {
+        if ((main->setting.flag & byte_dump_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);
+        }
+
+        byte_dump_print_error_parameter_range_out(&main->program.error, byte_dump_long_width_s, 1, 250, main->program.parameters.arguments.array[index]);
+
+        return;
+      }
+
+      main->setting.width = (uint8_t) number;
+    }
+    else if (main->program.parameters.array[byte_dump_parameter_width_e].result & f_console_result_found_e) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      if ((main->setting.flag & byte_dump_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);
+      }
+
+      fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, byte_dump_long_width_s);
+
+      return;
+    }
+
+    {
+      const f_number_unsigned_t indexs[] = {
+        byte_dump_parameter_first_e,
+        byte_dump_parameter_last_e,
+      };
+
+      const f_string_static_t names[] = {
+        byte_dump_long_first_s,
+        byte_dump_long_last_s,
+      };
+
+      const uint16_t flags[] = {
+        byte_dump_main_flag_first_e,
+        byte_dump_main_flag_last_e,
+      };
+
+      uint64_t * const values[] = {
+        &main->setting.first,
+        &main->setting.last,
+      };
+
+      for (uint8_t i = 0; i < 2; ++i) {
+
+        if (main->program.parameters.array[indexs[i]].result & f_console_result_value_e) {
+          index = main->program.parameters.array[indexs[i]].values.array[main->program.parameters.array[indexs[i]].values.used - 1];
+
+          main->setting.state.status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, main->program.parameters.arguments.array[index], &number);
+
+          // Negative numbers are not supported.
+          if (main->setting.state.status == F_number_negative) {
+            main->setting.state.status = F_status_set_error(F_number_negative);
+          }
+
+          if (F_status_is_error(main->setting.state.status)) {
+            if ((main->setting.flag & byte_dump_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);
+            }
+
+            byte_dump_print_error_parameter_range_out(&main->program.error, names[i], 0, F_number_t_size_unsigned_d, main->program.parameters.arguments.array[index]);
+
+            return;
+          }
+
+          *values[i] = number;
+          main->setting.flag |= flags[i];
+        }
+        else if (main->program.parameters.array[indexs[i]].result & f_console_result_found_e) {
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, names[i]);
+
+          return;
+        }
+        else {
+          main->setting.flag -= flags[i] & main->setting.flag;
+        }
+      } // for
+
+      if ((main->setting.flag & byte_dump_main_flag_first_e) && (main->setting.flag & byte_dump_main_flag_last_e)) {
+        if (main->setting.first > main->setting.last) {
+          main->setting.state.status = F_status_set_error(F_parameter);
+
+          if ((main->setting.flag & byte_dump_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);
+          }
+
+          fll_program_print_error_parameter_first_greater_than_last(&main->program.error);
+
+          return;
+        }
+
+        // Store last position as a relative offset from first instead of an absolute position.
+        main->setting.last = (main->setting.last - main->setting.first) + 1;
+      }
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_text_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_text_e;
+    }
+    else {
+      main->setting.flag -= byte_dump_main_flag_text_e & main->setting.flag;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_unicode_e;
+    }
+    else {
+      main->setting.flag -= byte_dump_main_flag_unicode_e & main->setting.flag;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_placeholder_e;
+    }
+    else {
+      main->setting.flag -= byte_dump_main_flag_placeholder_e & main->setting.flag;
+    }
+
+    if (main->program.parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
+      main->setting.flag |= byte_dump_main_flag_classic_e;
+    }
+    else {
+      main->setting.flag -= byte_dump_main_flag_classic_e & main->setting.flag;
+    }
+
+    if (main->program.parameters.remaining.used) {
+      main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.remaining.used, &main->setting.files);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        if ((main->setting.flag & byte_dump_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);
+        }
+
+        byte_dump_print_error(&main->program.error, macro_byte_dump_f(f_string_dynamics_increase_by));
+
+        return;
+      }
+
+      f_status_t status_files = F_none;
+
+      for (index = 0; index < main->program.parameters.remaining.used; ++index) {
+
+        if (byte_dump_signal_check(main)) return;
+
+        number = main->program.parameters.remaining.array[index];
+
+        if (!main->program.parameters.arguments.array[number].used) continue;
+
+        // Statically allocate the inner strings.
+        main->setting.files.array[main->setting.files.used].string = main->program.parameters.arguments.array[number].string;
+        main->setting.files.array[main->setting.files.used].used = main->program.parameters.arguments.array[number].used;
+        main->setting.files.array[main->setting.files.used++].size = 0;
+
+        main->setting.state.status = f_file_exists(main->program.parameters.arguments.array[number], F_true);
+
+        if (main->setting.state.status == F_false) {
+          main->setting.state.status = F_status_set_error(F_file_found_not);
+        }
+
+        if (F_status_is_error(main->setting.state.status)) {
+          if (status_files == F_none) {
+            if ((main->setting.flag & byte_dump_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);
+            }
+
+            status_files = main->setting.state.status;
+          }
+
+          byte_dump_print_error_file(&main->program.error, macro_byte_dump_f(f_file_exists), main->program.parameters.arguments.array[number], f_file_operation_find_s, fll_error_file_type_file_e);
+        }
+      } // for
+
+      if (status_files != F_none) {
+        main->setting.state.status = F_status_set_error(status_files);
+      }
+    }
+  }
+#endif // _di_byte_dump_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/common.h b/level_3/byte_dump/c/main/common.h
new file mode 100644 (file)
index 0000000..be220c4
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_h
+#define _byte_dump_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_byte_dump_setting_load_
+  extern void byte_dump_setting_load(const f_console_arguments_t arguments, byte_dump_main_t * const main);
+#endif // _di_byte_dump_setting_load_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_h
similarity index 61%
rename from level_3/byte_dump/c/private-common.c
rename to level_3/byte_dump/c/main/common/define.c
index 820be9031957c1b49c779545c20abb52682caebe..1c7bc5ac876b9a1b8851bf758cd252d1855624ff 100644 (file)
@@ -1,5 +1,4 @@
-#include "byte_dump.h"
-#include "private-common.h"
+#include "../byte_dump.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/level_3/byte_dump/c/main/common/define.h b/level_3/byte_dump/c/main/common/define.h
new file mode 100644 (file)
index 0000000..374c7db
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_define_h
+#define _byte_dump_common_define_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The program allocation defines.
+ *
+ * byte_dump_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_byte_dump_allocation_d_
+  #define byte_dump_allocation_console_d 4
+  #define byte_dump_allocation_large_d   256
+  #define byte_dump_allocation_pipe_d    16384
+  #define byte_dump_allocation_small_d   16
+#endif // _di_byte_dump_allocation_d_
+
+/**
+ * The program signal defines.
+ *
+ * byte_dump_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_byte_dump_signal_d_
+  #define byte_dump_signal_check_d          500000
+  #define byte_dump_signal_check_failsafe_d 20000
+  #define byte_dump_signal_check_tiny_d     4
+  #define byte_dump_signal_check_short_d    16
+#endif // _di_byte_dump_signal_d_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_define_h
diff --git a/level_3/byte_dump/c/main/common/enumeration.c b/level_3/byte_dump/c/main/common/enumeration.c
new file mode 100644 (file)
index 0000000..1c7bc5a
--- /dev/null
@@ -0,0 +1,9 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/common/enumeration.h b/level_3/byte_dump/c/main/common/enumeration.h
new file mode 100644 (file)
index 0000000..817acfb
--- /dev/null
@@ -0,0 +1,211 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_enumeration_h
+#define _byte_dump_common_enumeration_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Byte Dump modes.
+ *
+ * byte_dump_mode_*_e:
+ *   - hexidecimal: Display using hexidecimal notation (base 16).
+ *   - duodecimal:  Display using duodecimal notation (base 12).
+ *   - octal:       Display using octal notation (base 8).
+ *   - binary:      Display using binary notation (base 2).
+ *   - decimal:     Display using decimal notation (base 10).
+ */
+#ifndef _di_byte_dump_modes_e_
+  enum {
+    byte_dump_mode_hexidecimal_e = 1,
+    byte_dump_mode_duodecimal_e,
+    byte_dump_mode_octal_e,
+    byte_dump_mode_binary_e,
+    byte_dump_mode_decimal_e,
+  }; // enum
+#endif // _di_byte_dump_modes_e_
+
+/**
+ * Byte Dump presentations.
+ *
+ * byte_dump_presentation_*_e:
+ *   - normal:  Normal presentation mode.
+ *   - simple:  Simple presentation mode.
+ *   - classic: Classic presentation mode.
+ */
+#ifndef _di_byte_dump_presentations_e_
+  enum {
+    byte_dump_presentation_normal_e = 1,
+    byte_dump_presentation_simple_e,
+    byte_dump_presentation_classic_e,
+  }; // enum
+#endif // _di_byte_dump_presentations_e_
+
+/**
+ * Flags passed to the main function or program.
+ *
+ * byte_dump_main_flag_*_e:
+ *   - none:        No flags set.
+ *   - classic:     Classic is specified.
+ *   - copyright:   Print the copyright.
+ *   - first:       The first position is specified.
+ *   - help:        Print help.
+ *   - last:        The last position is specified.
+ *   - placeholder: Placeholder is specified.
+ *   - 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.
+ *   - text:        Text is specified.
+ *   - unicode:     Unicode is specified.
+ *   - version:     Print version.
+ *   - wide:        Wide option is specified for printing wide.
+ */
+#ifndef _di_byte_dump_main_flag_e_
+  enum {
+    byte_dump_main_flag_none_e        = 0x0,
+    byte_dump_main_flag_classic_e     = 0x1,
+    byte_dump_main_flag_copyright_e   = 0x2,
+    byte_dump_main_flag_first_e       = 0x4,
+    byte_dump_main_flag_help_e        = 0x8,
+    byte_dump_main_flag_last_e        = 0x10,
+    byte_dump_main_flag_pipe_e        = 0x20,
+    byte_dump_main_flag_placeholder_e = 0x40,
+    byte_dump_main_flag_print_first_e = 0x80,
+    byte_dump_main_flag_print_last_e  = 0x100,
+    byte_dump_main_flag_text_e        = 0x200,
+    byte_dump_main_flag_unicode_e     = 0x400,
+    byte_dump_main_flag_version_e     = 0x800,
+    byte_dump_main_flag_wide_e        = 0x1000,
+  }; // enum
+#endif // _di_byte_dump_main_flag_e_
+
+/**
+ * The program parameters.
+ *
+ * byte_dump_parameter_*_e:
+ *   - first: First offset byte size.
+ *   - last:  Last offset byte size.
+ *
+ *   - narrow:      Each character in the displyed text will take at least 1 columns.
+ *   - placeholder: Display (colored) placeholders to signify codes that are UTF-8 fragments.
+ *   - text:        Display text
+ *   - wide:        Each character in the displyed text will take at least 2 columns.
+ *   - width:       Number of characters to display per row.
+ *
+ *   - binary:      Display using binary format.
+ *   - decimal:     Display using decimal format.
+ *   - duodecimal:  Display using duodecimal format.
+ *   - hexidecimal: Display using hexidecimal format.
+ *   - octal:       Display using octal format.
+ *   - unicode:     Display using Unicode format.
+ *
+ *   - normal:  Use normal presentation, displaying UTF-8 sequence codes for ASCII special codes.
+ *   - simple:  Use simple presentation, displaying spaces for ASCII special codes instead of UTF-8 sequence codes.
+ *   - classic: Use classic presentation, displaying periods for ASCII special codes instead of UTF-8 sequence codes.
+ */
+#ifndef _di_byte_dump_parameter_e_
+  enum {
+    byte_dump_parameter_help_e,
+    byte_dump_parameter_copyright_e,
+    byte_dump_parameter_light_e,
+    byte_dump_parameter_dark_e,
+    byte_dump_parameter_no_color_e,
+    byte_dump_parameter_verbosity_quiet_e,
+    byte_dump_parameter_verbosity_error_e,
+    byte_dump_parameter_verbosity_normal_e,
+    byte_dump_parameter_verbosity_verbose_e,
+    byte_dump_parameter_verbosity_debug_e,
+    byte_dump_parameter_version_e,
+    byte_dump_parameter_line_first_no_e,
+    byte_dump_parameter_line_last_no_e,
+
+    byte_dump_parameter_binary_e,
+    byte_dump_parameter_decimal_e,
+    byte_dump_parameter_duodecimal_e,
+    byte_dump_parameter_hexidecimal_e,
+    byte_dump_parameter_octal_e,
+    byte_dump_parameter_unicode_e,
+
+    byte_dump_parameter_first_e,
+    byte_dump_parameter_last_e,
+
+    byte_dump_parameter_narrow_e,
+    byte_dump_parameter_placeholder_e,
+    byte_dump_parameter_text_e,
+    byte_dump_parameter_wide_e,
+    byte_dump_parameter_width_e,
+
+    byte_dump_parameter_normal_e,
+    byte_dump_parameter_simple_e,
+    byte_dump_parameter_classic_e,
+  }; // enum
+
+  #define byte_dump_console_parameter_t_initialize \
+    { \
+      macro_fll_program_console_parameter_standard_initialize, \
+      \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_binary_s,      byte_dump_long_binary_s,      0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_decimal_s,     byte_dump_long_decimal_s,     0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_duodecimal_s,  byte_dump_long_duodecimal_s,  0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_hexidecimal_s, byte_dump_long_hexidecimal_s, 0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_octal_s,       byte_dump_long_octal_s,       0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_unicode_s,     byte_dump_long_unicode_s,     0, f_console_flag_normal_e), \
+      \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_first_s,       byte_dump_long_first_s,       1, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_last_s,        byte_dump_long_last_s,        1, f_console_flag_normal_e), \
+      \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_narrow_s,      byte_dump_long_narrow_s,      0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_placeholder_s, byte_dump_long_placeholder_s, 0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_text_s,        byte_dump_long_text_s,        0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_wide_s,        byte_dump_long_wide_s,        0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_3(byte_dump_short_width_s,       byte_dump_long_width_s,       1, f_console_flag_normal_e), \
+      \
+      macro_f_console_parameter_t_initialize_5(byte_dump_long_normal_s,  0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_5(byte_dump_long_simple_s,  0, f_console_flag_normal_e), \
+      macro_f_console_parameter_t_initialize_5(byte_dump_long_classic_s, 0, f_console_flag_normal_e), \
+    }
+
+  #define byte_dump_parameter_total_d 29
+#endif // _di_byte_dump_parameter_e_
+
+/**
+ * Flags for fine-tuned print control.
+ *
+ * byte_dump_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_byte_dump_print_flag_e_
+  enum {
+    byte_dump_print_flag_none_e    = 0x0,
+    byte_dump_print_flag_debug_e   = 0x1,
+    byte_dump_print_flag_error_e   = 0x2,
+    byte_dump_print_flag_file_e    = 0x4,
+    byte_dump_print_flag_in_e      = 0x8,
+    byte_dump_print_flag_out_e     = 0x10,
+    byte_dump_print_flag_message_e = 0x20,
+    byte_dump_print_flag_warning_e = 0x40,
+  }; // enum
+#endif // _di_byte_dump_print_flag_e_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_enumeration_h
diff --git a/level_3/byte_dump/c/main/common/print.c b/level_3/byte_dump/c/main/common/print.c
new file mode 100644 (file)
index 0000000..d751877
--- /dev/null
@@ -0,0 +1,23 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_f_a_
+  const f_string_t byte_dump_f_a[] = {
+    "f_console_parameter_prioritize_right",
+    "f_console_parameter_process",
+    "f_file_exists",
+    "f_file_stream_open",
+    "f_string_dynamics_increase_by",
+    "f_thread_create",
+    "fl_conversion_dynamic_to_unsigned_detect",
+    "fll_program_parameter_process_context",
+    "fll_program_parameter_process_verbosity",
+  };
+#endif // _di_byte_dump_f_a_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/common/print.h b/level_3/byte_dump/c/main/common/print.h
new file mode 100644 (file)
index 0000000..71ec9f9
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_print_h
+#define _byte_dump_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_byte_dump_f() is used to reference the array index by the enum name.
+ *
+ * macro_byte_dump_f():
+ *   - name: The name of the function.
+ */
+#ifndef _di_byte_dump_f_a_
+  extern const f_string_t byte_dump_f_a[];
+
+  #define macro_byte_dump_f(name) byte_dump_f_a[byte_dump_f_##name##_e]
+#endif // _di_byte_dump_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_byte_dump_f_e_
+  enum {
+    byte_dump_f_f_console_parameter_prioritize_right_e,
+    byte_dump_f_f_console_parameter_process_e,
+    byte_dump_f_f_file_exists_e,
+    byte_dump_f_f_file_stream_open_e,
+    byte_dump_f_f_string_dynamics_increase_by_e,
+    byte_dump_f_f_thread_create_e,
+    byte_dump_f_fl_conversion_dynamic_to_unsigned_detect_e,
+    byte_dump_f_fll_program_parameter_process_context_e,
+    byte_dump_f_fll_program_parameter_process_verbosity_e,
+  }; // enum
+#endif // _di_byte_dump_f_e_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_print_h
diff --git a/level_3/byte_dump/c/main/common/string.c b/level_3/byte_dump/c/main/common/string.c
new file mode 100644 (file)
index 0000000..ab6232a
--- /dev/null
@@ -0,0 +1,69 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_program_version_d_
+  const f_string_static_t byte_dump_program_version_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_version_s, 0, BYTE_DUMP_program_version_s_length);
+#endif // _di_byte_dump_program_version_d_
+
+#ifndef _di_byte_dump_program_name_s_
+  const f_string_static_t byte_dump_program_name_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_name_s, 0, BYTE_DUMP_program_name_s_length);
+  const f_string_static_t byte_dump_program_name_long_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_program_name_long_s, 0, BYTE_DUMP_program_name_long_s_length);
+#endif // _di_byte_dump_program_name_s_
+
+#ifndef _di_byte_dump_s_
+  const f_string_static_t byte_dump_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_hexidecimal_s, 0, BYTE_DUMP_hexidecimal_s_length);
+  const f_string_static_t byte_dump_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_duodecimal_s, 0, BYTE_DUMP_duodecimal_s_length);
+  const f_string_static_t byte_dump_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_octal_s, 0, BYTE_DUMP_octal_s_length);
+  const f_string_static_t byte_dump_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_binary_s, 0, BYTE_DUMP_binary_s_length);
+  const f_string_static_t byte_dump_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_decimal_s, 0, BYTE_DUMP_decimal_s_length);
+
+  const f_string_static_t byte_dump_character_wall_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_wall_s, 0, BYTE_DUMP_character_wall_s_length);
+  const f_string_static_t byte_dump_character_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_placeholder_s, 0, BYTE_DUMP_character_placeholder_s_length);
+  const f_string_static_t byte_dump_character_incomplete_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_incomplete_s, 0, BYTE_DUMP_character_incomplete_s_length);
+  const f_string_static_t byte_dump_character_unused_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_character_unused_s, 0, BYTE_DUMP_character_unused_s_length);
+#endif // _di_byte_dump_s_
+
+#ifndef _di_byte_dump_parameter_d_
+  const f_string_static_t byte_dump_short_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_binary_s, 0, BYTE_DUMP_short_binary_s_length);
+  const f_string_static_t byte_dump_short_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_decimal_s, 0, BYTE_DUMP_short_decimal_s_length);
+  const f_string_static_t byte_dump_short_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_duodecimal_s, 0, BYTE_DUMP_short_duodecimal_s_length);
+  const f_string_static_t byte_dump_short_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_hexidecimal_s, 0, BYTE_DUMP_short_hexidecimal_s_length);
+  const f_string_static_t byte_dump_short_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_octal_s, 0, BYTE_DUMP_short_octal_s_length);
+  const f_string_static_t byte_dump_short_unicode_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_unicode_s, 0, BYTE_DUMP_short_unicode_s_length);
+
+  const f_string_static_t byte_dump_short_first_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_first_s, 0, BYTE_DUMP_short_first_s_length);
+  const f_string_static_t byte_dump_short_last_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_last_s, 0, BYTE_DUMP_short_last_s_length);
+
+  const f_string_static_t byte_dump_short_narrow_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_narrow_s, 0, BYTE_DUMP_short_narrow_s_length);
+  const f_string_static_t byte_dump_short_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_placeholder_s, 0, BYTE_DUMP_short_placeholder_s_length);
+  const f_string_static_t byte_dump_short_text_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_text_s, 0, BYTE_DUMP_short_text_s_length);
+  const f_string_static_t byte_dump_short_wide_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_wide_s, 0, BYTE_DUMP_short_wide_s_length);
+  const f_string_static_t byte_dump_short_width_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_short_width_s, 0, BYTE_DUMP_short_width_s_length);
+
+  const f_string_static_t byte_dump_long_binary_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_binary_s, 0, BYTE_DUMP_long_binary_s_length);
+  const f_string_static_t byte_dump_long_decimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_decimal_s, 0, BYTE_DUMP_long_decimal_s_length);
+  const f_string_static_t byte_dump_long_duodecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_duodecimal_s, 0, BYTE_DUMP_long_duodecimal_s_length);
+  const f_string_static_t byte_dump_long_hexidecimal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_hexidecimal_s, 0, BYTE_DUMP_long_hexidecimal_s_length);
+  const f_string_static_t byte_dump_long_octal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_octal_s, 0, BYTE_DUMP_long_octal_s_length);
+  const f_string_static_t byte_dump_long_unicode_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_unicode_s, 0, BYTE_DUMP_long_unicode_s_length);
+
+  const f_string_static_t byte_dump_long_first_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_first_s, 0, BYTE_DUMP_long_first_s_length);
+  const f_string_static_t byte_dump_long_last_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_last_s, 0, BYTE_DUMP_long_last_s_length);
+
+  const f_string_static_t byte_dump_long_narrow_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_narrow_s, 0, BYTE_DUMP_long_narrow_s_length);
+  const f_string_static_t byte_dump_long_placeholder_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_placeholder_s, 0, BYTE_DUMP_long_placeholder_s_length);
+  const f_string_static_t byte_dump_long_text_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_text_s, 0, BYTE_DUMP_long_text_s_length);
+  const f_string_static_t byte_dump_long_wide_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_wide_s, 0, BYTE_DUMP_long_wide_s_length);
+  const f_string_static_t byte_dump_long_width_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_width_s, 0, BYTE_DUMP_long_width_s_length);
+
+  const f_string_static_t byte_dump_long_normal_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_normal_s, 0, BYTE_DUMP_long_normal_s_length);
+  const f_string_static_t byte_dump_long_simple_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_simple_s, 0, BYTE_DUMP_long_simple_s_length);
+  const f_string_static_t byte_dump_long_classic_s = macro_f_string_static_t_initialize_1(BYTE_DUMP_long_classic_s, 0, BYTE_DUMP_long_classic_s_length);
+#endif // _di_byte_dump_parameter_d_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/common/string.h b/level_3/byte_dump/c/main/common/string.h
new file mode 100644 (file)
index 0000000..8029813
--- /dev/null
@@ -0,0 +1,217 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_string_h
+#define _byte_dump_common_string_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The program version.
+ */
+#ifndef _di_byte_dump_program_version_d_
+  #define BYTE_DUMP_program_version_major_s F_string_ascii_0_s
+  #define BYTE_DUMP_program_version_minor_s F_string_ascii_7_s
+  #define BYTE_DUMP_program_version_micro_s F_string_ascii_0_s
+
+  #define BYTE_DUMP_program_version_major_s_length F_string_ascii_0_s_length
+  #define BYTE_DUMP_program_version_minor_s_length F_string_ascii_7_s_length
+  #define BYTE_DUMP_program_version_micro_s_length F_string_ascii_0_s_length
+
+  #if !(defined(BYTE_DUMP_program_version_nano_prefix_s) && defined(BYTE_DUMP_program_version_nano_prefix_s_length))
+    #define BYTE_DUMP_program_version_nano_prefix_s
+    #define BYTE_DUMP_program_version_nano_prefix_s_length 0
+  #endif // !(defined(BYTE_DUMP_program_version_nano_prefix_s) && defined(BYTE_DUMP_program_version_nano_prefix_s_length))
+
+  #if !(defined(BYTE_DUMP_program_version_nano_s) && defined(BYTE_DUMP_program_version_nano_s_length))
+    #define BYTE_DUMP_program_version_nano_s
+    #define BYTE_DUMP_program_version_nano_s_length 0
+  #endif // !(defined(BYTE_DUMP_program_version_nano_s) && defined(BYTE_DUMP_program_version_nano_s_length))
+
+  #define BYTE_DUMP_program_version_s BYTE_DUMP_program_version_major_s F_string_ascii_period_s BYTE_DUMP_program_version_minor_s F_string_ascii_period_s BYTE_DUMP_program_version_micro_s BYTE_DUMP_program_version_nano_prefix_s BYTE_DUMP_program_version_nano_s
+
+  #define BYTE_DUMP_program_version_s_length BYTE_DUMP_program_version_major_s_length + F_string_ascii_period_s_length + BYTE_DUMP_program_version_minor_s_length + F_string_ascii_period_s_length + BYTE_DUMP_program_version_micro_s_length + BYTE_DUMP_program_version_nano_prefix_s_length + BYTE_DUMP_program_version_nano_s_length
+
+  extern const f_string_static_t byte_dump_program_version_s;
+#endif // _di_byte_dump_program_version_d_
+
+/**
+ * The program name.
+ */
+#ifndef _di_byte_dump_program_name_s_
+  #define BYTE_DUMP_program_name_s      "byte_dump"
+  #define BYTE_DUMP_program_name_long_s "Byte Dump"
+
+  #define BYTE_DUMP_program_name_s_length      9
+  #define BYTE_DUMP_program_name_long_s_length 9
+
+  extern const f_string_static_t byte_dump_program_name_s;
+  extern const f_string_static_t byte_dump_program_name_long_s;
+#endif // _di_byte_dump_program_name_s_
+
+/**
+ * The program strings for printing.
+ */
+#ifndef _di_byte_dump_s_
+  #define BYTE_DUMP_hexidecimal_s "Hexidecimal"
+  #define BYTE_DUMP_duodecimal_s  "Duodecimal"
+  #define BYTE_DUMP_octal_s       "Octal"
+  #define BYTE_DUMP_binary_s      "Binary"
+  #define BYTE_DUMP_decimal_s     "Decimal"
+
+  #define BYTE_DUMP_character_wall_s        "|"
+  #define BYTE_DUMP_character_placeholder_s "␣" // Other likely choices: (substitute form 1: '␚', substitute form 2: '␦').
+  #define BYTE_DUMP_character_incomplete_s  "�"
+  #define BYTE_DUMP_character_unused_s      "�"
+
+  #define BYTE_DUMP_hexidecimal_s_length 11
+  #define BYTE_DUMP_duodecimal_s_length  10
+  #define BYTE_DUMP_octal_s_length       5
+  #define BYTE_DUMP_binary_s_length      6
+  #define BYTE_DUMP_decimal_s_length     7
+
+  #define BYTE_DUMP_character_wall_s_length        1
+  #define BYTE_DUMP_character_placeholder_s_length 3
+  #define BYTE_DUMP_character_incomplete_s_length  3
+  #define BYTE_DUMP_character_unused_s_length      3
+
+  extern const f_string_static_t byte_dump_hexidecimal_s;
+  extern const f_string_static_t byte_dump_duodecimal_s;
+  extern const f_string_static_t byte_dump_octal_s;
+  extern const f_string_static_t byte_dump_binary_s;
+  extern const f_string_static_t byte_dump_decimal_s;
+
+  extern const f_string_static_t byte_dump_character_wall_s;
+  extern const f_string_static_t byte_dump_character_placeholder_s;
+  extern const f_string_static_t byte_dump_character_incomplete_s;
+  extern const f_string_static_t byte_dump_character_unused_s;
+#endif // _di_byte_dump_s_
+
+/**
+ * The main program parameters.
+ */
+#ifndef _di_byte_dump_parameter_d_
+  #define BYTE_DUMP_short_binary_s      "b"
+  #define BYTE_DUMP_short_decimal_s     "d"
+  #define BYTE_DUMP_short_duodecimal_s  "D"
+  #define BYTE_DUMP_short_hexidecimal_s "x"
+  #define BYTE_DUMP_short_octal_s       "o"
+  #define BYTE_DUMP_short_unicode_s     "U"
+
+  #define BYTE_DUMP_short_first_s       "f"
+  #define BYTE_DUMP_short_last_s        "l"
+
+  #define BYTE_DUMP_short_narrow_s      "N"
+  #define BYTE_DUMP_short_placeholder_s "p"
+  #define BYTE_DUMP_short_text_s        "t"
+  #define BYTE_DUMP_short_wide_s        "W"
+  #define BYTE_DUMP_short_width_s       "w"
+
+  #define BYTE_DUMP_long_binary_s      "binary"
+  #define BYTE_DUMP_long_decimal_s     "decimal"
+  #define BYTE_DUMP_long_duodecimal_s  "duodecimal"
+  #define BYTE_DUMP_long_hexidecimal_s "hexidecimal"
+  #define BYTE_DUMP_long_octal_s       "octal"
+  #define BYTE_DUMP_long_unicode_s     "unicode"
+
+  #define BYTE_DUMP_long_first_s "first"
+  #define BYTE_DUMP_long_last_s  "last"
+
+  #define BYTE_DUMP_long_narrow_s      "narrow"
+  #define BYTE_DUMP_long_placeholder_s "placeholder"
+  #define BYTE_DUMP_long_text_s        "text"
+  #define BYTE_DUMP_long_wide_s        "wide"
+  #define BYTE_DUMP_long_width_s       "width"
+
+  #define BYTE_DUMP_long_normal_s  "normal"
+  #define BYTE_DUMP_long_simple_s  "simple"
+  #define BYTE_DUMP_long_classic_s "classic"
+
+  #define BYTE_DUMP_short_binary_s_length      1
+  #define BYTE_DUMP_short_decimal_s_length     1
+  #define BYTE_DUMP_short_duodecimal_s_length  1
+  #define BYTE_DUMP_short_hexidecimal_s_length 1
+  #define BYTE_DUMP_short_octal_s_length       1
+  #define BYTE_DUMP_short_unicode_s_length     1
+
+  #define BYTE_DUMP_short_first_s_length       1
+  #define BYTE_DUMP_short_last_s_length        1
+
+  #define BYTE_DUMP_short_narrow_s_length      1
+  #define BYTE_DUMP_short_placeholder_s_length 1
+  #define BYTE_DUMP_short_text_s_length        1
+  #define BYTE_DUMP_short_wide_s_length        1
+  #define BYTE_DUMP_short_width_s_length       1
+
+  #define BYTE_DUMP_long_binary_s_length      6
+  #define BYTE_DUMP_long_decimal_s_length     7
+  #define BYTE_DUMP_long_duodecimal_s_length  10
+  #define BYTE_DUMP_long_hexidecimal_s_length 11
+  #define BYTE_DUMP_long_octal_s_length       5
+  #define BYTE_DUMP_long_unicode_s_length     7
+
+  #define BYTE_DUMP_long_first_s_length 5
+  #define BYTE_DUMP_long_last_s_length  4
+
+  #define BYTE_DUMP_long_narrow_s_length      6
+  #define BYTE_DUMP_long_placeholder_s_length 11
+  #define BYTE_DUMP_long_text_s_length        4
+  #define BYTE_DUMP_long_wide_s_length        4
+  #define BYTE_DUMP_long_width_s_length       5
+
+  #define BYTE_DUMP_long_normal_s_length  6
+  #define BYTE_DUMP_long_simple_s_length  6
+  #define BYTE_DUMP_long_classic_s_length 7
+
+  extern const f_string_static_t byte_dump_short_binary_s;
+  extern const f_string_static_t byte_dump_short_decimal_s;
+  extern const f_string_static_t byte_dump_short_duodecimal_s;
+  extern const f_string_static_t byte_dump_short_hexidecimal_s;
+  extern const f_string_static_t byte_dump_short_octal_s;
+  extern const f_string_static_t byte_dump_short_unicode_s;
+
+  extern const f_string_static_t byte_dump_short_first_s;
+  extern const f_string_static_t byte_dump_short_last_s;
+
+  extern const f_string_static_t byte_dump_short_narrow_s;
+  extern const f_string_static_t byte_dump_short_placeholder_s;
+  extern const f_string_static_t byte_dump_short_text_s;
+  extern const f_string_static_t byte_dump_short_wide_s;
+  extern const f_string_static_t byte_dump_short_width_s;
+
+  extern const f_string_static_t byte_dump_long_binary_s;
+  extern const f_string_static_t byte_dump_long_decimal_s;
+  extern const f_string_static_t byte_dump_long_duodecimal_s;
+  extern const f_string_static_t byte_dump_long_hexidecimal_s;
+  extern const f_string_static_t byte_dump_long_octal_s;
+  extern const f_string_static_t byte_dump_long_unicode_s;
+
+  extern const f_string_static_t byte_dump_long_first_s;
+  extern const f_string_static_t byte_dump_long_last_s;
+
+  extern const f_string_static_t byte_dump_long_narrow_s;
+  extern const f_string_static_t byte_dump_long_placeholder_s;
+  extern const f_string_static_t byte_dump_long_text_s;
+  extern const f_string_static_t byte_dump_long_wide_s;
+  extern const f_string_static_t byte_dump_long_width_s;
+
+  extern const f_string_static_t byte_dump_long_normal_s;
+  extern const f_string_static_t byte_dump_long_simple_s;
+  extern const f_string_static_t byte_dump_long_classic_s;
+#endif // _di_byte_dump_parameter_d_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_string_h
diff --git a/level_3/byte_dump/c/main/common/type.c b/level_3/byte_dump/c/main/common/type.c
new file mode 100644 (file)
index 0000000..1503042
--- /dev/null
@@ -0,0 +1,30 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_main_delete_
+  void byte_dump_main_delete(byte_dump_main_t * const main) {
+
+    if (!main) return;
+
+    fll_program_data_delete(&main->program);
+    byte_dump_setting_delete(&main->setting);
+  }
+#endif // _di_byte_dump_main_delete_
+
+#ifndef _di_byte_dump_setting_delete_
+  f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting) {
+
+    if (!setting) return F_status_set_error(F_parameter);
+
+    f_string_dynamics_resize(0, &setting->files);
+
+    return F_none;
+  }
+#endif // _di_byte_dump_setting_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/common/type.h b/level_3/byte_dump/c/main/common/type.h
new file mode 100644 (file)
index 0000000..c8a07ff
--- /dev/null
@@ -0,0 +1,167 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_common_type_h
+#define _byte_dump_common_type_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A main structure for character row and column position (cell).
+ *
+ * Properties:
+ *   - column: The column position associated with the character cell.
+ *   - row:    The row position associated with the character cell.
+ */
+#ifndef _di_byte_dump_cell_t_
+  typedef struct {
+    uint8_t  column;
+    uint64_t row;
+  } byte_dump_cell_t;
+
+  #define byte_dump_cell_t_initialize \
+    { \
+      0, \
+      0, \
+    }
+#endif // _di_byte_dump_cell_t_
+
+/**
+ * A main structure for character main that overflowed from a previous line.
+ *
+ * UTF-8 Characters bytes may overflow beyond the main.width.
+ * These overflowed bytes should still have placeholders printed in the next text-mode print.
+ *
+ * Properties:
+ *   - bytes:   The number of previous bytes that overflowed from the previous line.
+ *              This is used to print the placeholders for the "text" option.
+ *   - invalid: The specific invalid value provided representing the overflowed bytes.
+ *              This is used to print the placeholders.
+ */
+#ifndef _di_byte_dump_previous_t_
+  typedef struct {
+    uint8_t bytes;
+    uint8_t invalid;
+  } byte_dump_previous_t;
+
+  #define byte_dump_previous_t_initialize \
+    { \
+      0, \
+      0, \
+    }
+#endif // _di_byte_previous_cell_
+
+/**
+ * The byte_dump 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.
+ *
+ *   - status_signal: A status used eclusively by the threaded signal handler.
+ *   - state:         The state data used when processing the FSS data.
+ *
+ *   - first:        The first position.
+ *   - last:         The last position.
+ *   - mode:         The digit representation mode.
+ *   - options:      Additional options.
+ *   - presentation: The presentation mode.
+ *   - width:        The number of columns.
+ *   - files:        An array containing all files to process.
+ */
+#ifndef _di_byte_dump_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status_signal;
+    f_state_t state;
+
+    uint64_t first;
+    uint64_t last;
+    uint8_t width;
+    uint8_t mode;
+    uint8_t presentation;
+
+    f_string_dynamics_t files;
+  } byte_dump_setting_t;
+
+  #define byte_dump_setting_t_initialize \
+    { \
+      byte_dump_main_flag_none_e, \
+      F_none, \
+      f_state_t_initialize, \
+      0, \
+      0, \
+      8, \
+      byte_dump_mode_hexidecimal_e, \
+      byte_dump_presentation_normal_e, \
+      f_string_dynamics_t_initialize, \
+    }
+#endif // _di_byte_dump_setting_t_
+
+/**
+ * The main program data as a single structure.
+ *
+ * Properties:
+ *   - program: The main program data.
+ *   - setting: The settings data.
+ */
+#ifndef _di_byte_dump_main_t_
+  typedef struct {
+    fll_program_data_t program;
+    byte_dump_setting_t setting;
+  } byte_dump_main_t;
+
+  #define byte_dump_main_t_initialize \
+    { \
+      fll_program_data_t_initialize, \
+      byte_dump_setting_t_initialize, \
+    }
+#endif // _di_byte_dump_main_t_
+
+/**
+ * Deallocate main program data.
+ *
+ * @param setting_make
+ *   The make setting data.
+ *
+ *   This does not alter main.setting.state.status.
+ */
+#ifndef _di_byte_dump_main_delete_
+  extern void byte_dump_main_delete(byte_dump_main_t * const main);
+#endif // _di_byte_dump_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.
+ */
+#ifndef _di_byte_dump_setting_delete_
+  extern f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting);
+#endif // _di_byte_dump_setting_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_common_type_h
similarity index 51%
rename from level_3/byte_dump/c/main.c
rename to level_3/byte_dump/c/main/main.c
index 7d3c5694d548ad997018539d1de934b1474b0120..d82f9ff888258d2f92bdefac449b417d9176d058 100644 (file)
@@ -16,6 +16,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
   data.program.warning.custom = (void *) &data;
 
   f_console_parameter_t parameters[] = byte_dump_console_parameter_t_initialize;
+
   data.program.parameters.array = parameters;
   data.program.parameters.used = byte_dump_parameter_total_d;
   data.program.environment = envp;
@@ -26,19 +27,47 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
   fll_program_standard_set_up(&data.program);
 
-  {
-    const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+  f_file_umask_get(&data.program.umask);
 
-    byte_dump_setting_load(arguments, &data);
-  }
+  #ifdef _di_thread_support_
+    {
+      const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+
+      byte_dump_setting_load(arguments, &data);
+    }
+
+    byte_dump_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, &byte_dump_thread_signal, (void *) &data);
+
+      if (F_status_is_error(data.setting.state.status)) {
+        byte_dump_print_error(&data.program.error, macro_byte_dump_f(f_thread_create));
+      }
+      else {
+        {
+          const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
+
+          byte_dump_setting_load(arguments, &data);
+        }
 
-  byte_dump_main(&data);
+        if (!byte_dump_signal_check(&data)) {
+          byte_dump_main(&data);
+        }
 
-  byte_dump_setting_unload(&data);
+        f_thread_cancel(id_signal);
+        f_thread_join(id_signal, 0);
+      }
+    }
+  #endif // _di_thread_support_
 
-  fll_program_data_delete(&data.program);
+  byte_dump_main_delete(&data);
 
   fll_program_standard_set_down(&data.program);
 
-  return F_status_is_error(data.setting.state.status) ? 1 : 0;
+  return (F_status_is_error(data.setting.state.status) || data.setting.state.status == F_false) ? 1 : 0;
 }
diff --git a/level_3/byte_dump/c/main/print/data.c b/level_3/byte_dump/c/main/print/data.c
new file mode 100644 (file)
index 0000000..c4f6381
--- /dev/null
@@ -0,0 +1,736 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_print_character_fragment_
+  f_status_t byte_dump_print_character_fragment(fl_print_t * const print, const f_utf_string_static_t sequence, const f_char_t invalid[], const uint8_t width_utf, const f_char_t byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, f_char_t *offset) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    byte_dump_main_t * const main = (byte_dump_main_t *) print->custom;
+
+    f_char_t byte = 0;
+    bool reset = F_false;
+    f_number_unsigned_t current = sequence.used - 1;
+
+    if (byte_current == 1) {
+      byte = macro_f_utf_char_t_to_char_1(sequence.string[current]);
+    }
+    else if (byte_current == 2) {
+      byte = macro_f_utf_char_t_to_char_2(sequence.string[current]);
+    }
+    else if (byte_current == 3) {
+      byte = macro_f_utf_char_t_to_char_3(sequence.string[current]);
+    }
+    else if (byte_current == 4) {
+      byte = macro_f_utf_char_t_to_char_4(sequence.string[current]);
+    }
+
+    if (!cell->column) {
+      fl_print_format("%[%016_UL%] ", print->to, print->set->notable, cell->row, print->set->notable);
+
+      if (*offset) {
+        f_char_t offset_to_print = *offset;
+
+        // Pad the buffer with spaces to hide any skipped bytes (skipped via --first).
+        while (offset_to_print && cell->column < main->setting.width) {
+
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            f_print_terminated("         ", print->to);
+          }
+          else if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+            f_print_terminated("   ", print->to);
+          }
+          else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+            f_print_terminated("    ", print->to);
+          }
+          else if (main->setting.mode == byte_dump_mode_octal_e) {
+            f_print_terminated("    ", print->to);
+          }
+          else if (main->setting.mode == byte_dump_mode_binary_e) {
+            f_print_terminated("         ", print->to);
+          }
+          else if (main->setting.mode == byte_dump_mode_decimal_e) {
+            f_print_terminated("    ", print->to);
+          }
+
+          --offset_to_print;
+          ++cell->column;
+
+          if (cell->column < main->setting.width) {
+            if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+              if (!(cell->column % 4)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+            else if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+              if (!(cell->column % 8)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+            else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+              if (!(cell->column % 6)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+            else if (main->setting.mode == byte_dump_mode_octal_e) {
+              if (!(cell->column % 6)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+            else if (main->setting.mode == byte_dump_mode_binary_e) {
+              if (!(cell->column % 4)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+            else if (main->setting.mode == byte_dump_mode_decimal_e) {
+              if (!(cell->column % 6)) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+              }
+            }
+          }
+        } // while
+      }
+    }
+
+    if (cell->column < main->setting.width) {
+      if ((main->setting.flag & byte_dump_main_flag_unicode_e) && !invalid[current]) {
+        if (byte_current == 1) {
+          uint32_t unicode = 0;
+
+          if (width_utf < 2) {
+
+            // 1 == U+0000 -> U+007F.
+            unicode = macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x7f;
+          }
+          else if (width_utf == 2) {
+
+            // 2 == U+0080 -> U+07FF.
+            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x1f) << 6;
+            unicode |= macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f;
+          }
+          else if (width_utf == 3) {
+
+            // 3 == U+0800 -> U+FFFF.
+            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0xf) << 12;
+            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 6;
+            unicode |= macro_f_utf_char_t_to_char_3(sequence.string[current]) & 0x3f;
+          }
+          else if (width_utf == 4) {
+
+            // 4 == U+10000 -> U+10FFFF.
+            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x7) << 18;
+            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 12;
+            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 6;
+            unicode |= macro_f_utf_char_t_to_char_4(sequence.string[current]) & 0x3f;
+          }
+
+          if (width_utf < 4) {
+            fl_print_format(" U+%04_U  ", print->to, unicode);
+          }
+          else {
+            fl_print_format(" U+%06_U", print->to, unicode);
+          }
+        }
+        else {
+
+          // Pad the sequence that are incomplete fragments of an already printed valid Unicode.
+          f_print_terminated("         ", print->to);
+        }
+      }
+      else {
+        if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            f_print_terminated("      ", print->to);
+          }
+
+          if (invalid[current]) {
+            fl_print_format(" %[%02_uii%]", print->to, print->set->error, (uint8_t) byte, print->set->error);
+          }
+          else {
+            fl_print_format(" %02_uii", print->to, (uint8_t) byte);
+          }
+        }
+        else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            f_print_terminated("     ", print->to);
+          }
+
+          if (invalid[current]) {
+            fl_print_format(" %[%03&uii%]", print->to, print->set->error, (uint8_t) byte, print->set->error);
+          }
+          else {
+            fl_print_format(" %03&uii", print->to, (uint8_t) byte);
+          }
+        }
+        else if (main->setting.mode == byte_dump_mode_octal_e) {
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            f_print_terminated("     ", print->to);
+          }
+
+          if (invalid[current]) {
+            fl_print_format(" %[%03@uii%]", print->to, print->set->error, (uint8_t) byte, print->set->error);
+          }
+          else {
+            fl_print_format(" %03@uii", print->to, (uint8_t) byte);
+          }
+        }
+        else if (main->setting.mode == byte_dump_mode_binary_e) {
+          if (invalid[current]) {
+            fl_print_format(" %[%08!uii%]", print->to, print->set->error, (uint8_t) byte, print->set->error);
+          }
+          else {
+            fl_print_format(" %08!uii", print->to, (uint8_t) byte);
+          }
+        }
+        else if (main->setting.mode == byte_dump_mode_decimal_e) {
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            f_print_terminated("     ", print->to);
+          }
+
+          if (invalid[current]) {
+            fl_print_format(" %[%3uii%]", print->to, print->set->error, (uint8_t) byte, print->set->error);
+          }
+          else {
+            fl_print_format(" %3uii", print->to, (uint8_t) byte);
+          }
+        }
+      }
+
+      ++cell->column;
+    }
+
+    if (cell->column == main->setting.width) {
+      uint8_t bytes = 0;
+
+      if (byte_current < width_utf) {
+        bytes = width_utf - byte_current;
+      }
+
+      reset = F_true;
+
+      if (main->setting.flag & byte_dump_main_flag_text_e) {
+        byte_dump_print_text(print, sequence, invalid, previous, offset);
+      }
+      else {
+        f_print_dynamic_raw(f_string_eol_s, print->to);
+      }
+
+      cell->column = 0;
+      ++cell->row;
+
+      if (bytes) {
+        previous->bytes = bytes;
+        previous->invalid = invalid[current];
+      }
+      else {
+        previous->bytes = 0;
+        previous->invalid = 0;
+      }
+    }
+    else {
+      if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+        if (!(cell->column % 4)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+      else if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+        if (!(cell->column % 8)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+      else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+        if (!(cell->column % 6)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+      else if (main->setting.mode == byte_dump_mode_octal_e) {
+        if (!(cell->column % 6)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+      else if (main->setting.mode == byte_dump_mode_binary_e) {
+        if (!(cell->column % 4)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+      else if (main->setting.mode == byte_dump_mode_decimal_e) {
+        if (!(cell->column % 6)) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      }
+    }
+
+    return reset;
+  }
+#endif // _di_byte_dump_print_character_fragment_
+
+#ifndef _di_byte_dump_print_text_
+  f_status_t byte_dump_print_text(fl_print_t * const print, const f_utf_string_static_t sequence, const f_char_t invalid[], byte_dump_previous_t *previous, f_char_t *offset) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    byte_dump_main_t * const main = (byte_dump_main_t *) print->custom;
+
+    f_char_t c = 0;
+    uint8_t at = 0;
+    uint8_t width_utf = 0;
+    bool do_print = F_true;
+
+    f_char_t byte[5] = { 0, 0, 0, 0, 0 };
+
+    fl_print_format("  %[%r%] ", print->to, print->set->notable, byte_dump_character_wall_s, print->set->notable);
+
+    if (*offset) {
+      if (main->setting.flag & byte_dump_main_flag_classic_e) {
+        while (*offset && at < main->setting.width) {
+
+          f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+          }
+
+          --(*offset);
+          ++at;
+        } // while
+      }
+      else {
+        if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+          for (; *offset && at < main->setting.width; --(*offset), ++at) {
+
+            fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+
+            if (main->setting.flag & byte_dump_main_flag_wide_e) {
+              f_print_dynamic_raw(f_string_space_s, print->to);
+            }
+          } // for
+        }
+        else {
+          for (; *offset && at < main->setting.width; --(*offset), ++at) {
+
+            f_print_dynamic_raw(f_string_space_s, print->to);
+
+            if (main->setting.flag & byte_dump_main_flag_wide_e) {
+              f_print_dynamic_raw(f_string_space_s, print->to);
+            }
+          } // for
+        }
+      }
+    }
+
+    // Print placeholders for the remaining fragments of UTF-8 sequence printed on previous lines.
+    if (at < main->setting.width) {
+      uint8_t bytes_overflow = 0;
+
+      if (previous->bytes - 1 > main->setting.width) {
+        bytes_overflow = previous->bytes - 1 - main->setting.width;
+      }
+
+      if (previous->bytes) {
+        if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+          for (; at < previous->bytes && at < main->setting.width; ++at) {
+
+            if (previous->invalid) {
+              fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_placeholder_s, print->set->error);
+            }
+            else if (main->setting.flag & byte_dump_main_flag_classic_e) {
+              f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+            }
+            else {
+              fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+            }
+
+            if (main->setting.flag & byte_dump_main_flag_wide_e) {
+              f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+            }
+          } // for
+        }
+        else {
+          for (; at < previous->bytes && at < main->setting.width; ++at) {
+
+            f_print_dynamic_raw(f_string_space_s, print->to);
+
+            if (main->setting.flag & byte_dump_main_flag_wide_e) {
+              f_print_dynamic_raw(f_string_space_s, print->to);
+            }
+          } // for
+        }
+      }
+
+      if (bytes_overflow) {
+        previous->bytes = bytes_overflow;
+      }
+      else {
+        previous->bytes = 0;
+        previous->invalid = 0;
+      }
+    }
+
+    for (uint8_t i = 0; i < sequence.used && at < main->setting.width; ++i, ++at) {
+
+      c = macro_f_utf_char_t_to_char_1(sequence.string[i]);
+      width_utf = macro_f_utf_byte_width_is(c);
+
+      if (invalid[i]) {
+        fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_incomplete_s, print->set->error);
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+      }
+      else if (f_utf_character_is_control(sequence.string[i]) == F_true) {
+        if (main->setting.presentation == byte_dump_presentation_normal_e) {
+          fl_print_format("%[%[", print->to, print->set->notable, print->set->warning);
+
+          if (width_utf) {
+            byte[0] = c;
+
+            if (width_utf > 1) {
+              byte[1] = macro_f_utf_char_t_to_char_2(sequence.string[i]);
+
+              if (width_utf > 2) {
+                byte[2] = macro_f_utf_char_t_to_char_3(sequence.string[i]);
+
+                if (width_utf > 3) {
+                  byte[3] = macro_f_utf_char_t_to_char_4(sequence.string[i]);
+                }
+                else {
+                  byte[3] = 0;
+                }
+              }
+              else {
+                byte[2] = 0;
+              }
+            }
+            else {
+              byte[1] = 0;
+            }
+
+            f_print_safely(byte, width_utf, print->to);
+          }
+          else {
+            f_print_character_safely(c, print->to);
+          }
+
+          fl_print_format("%]%]", print->to, print->set->warning, print->set->notable);
+
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            if (f_utf_character_is_wide(sequence.string[i]) != F_true) {
+              f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+            }
+          }
+        }
+        else {
+          if (main->setting.presentation == byte_dump_presentation_simple_e) {
+            f_print_dynamic_raw(f_string_space_s, print->to);
+
+            if (width_utf > 1) {
+              f_print_dynamic_raw(f_string_space_s, print->to);
+
+              if (width_utf > 2) {
+                f_print_dynamic_raw(f_string_space_s, print->to);
+
+                if (width_utf > 3) {
+                  f_print_dynamic_raw(f_string_space_s, print->to);
+                }
+              }
+            }
+          }
+          else if (main->setting.presentation == byte_dump_presentation_classic_e) {
+            f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+
+            if (width_utf > 1) {
+              f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+
+              if (width_utf > 2) {
+                f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+
+                if (width_utf > 3) {
+                  f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+                }
+              }
+            }
+          }
+
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+          }
+        }
+      }
+      else if (f_utf_character_is_whitespace(sequence.string[i], F_true) == F_true) {
+        if (main->setting.flag & byte_dump_main_flag_classic_e) {
+          f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+        }
+        else {
+          fl_print_format("%[%[%r%]%]", print->to, print->set->notable, print->set->warning, f_print_sequence_space_s, print->set->warning, print->set->notable);
+        }
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+      }
+      else if (f_utf_character_is_zero_width(sequence.string[i]) == F_true) {
+        if (main->setting.presentation == byte_dump_presentation_classic_e) {
+          f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+        }
+        else if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+          fl_print_format("%[%[%r%]%]", print->to, print->set->notable, print->set->warning, byte_dump_character_placeholder_s, print->set->warning, print->set->notable);
+        }
+        else {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+      }
+      else if (width_utf) {
+        do_print = F_false;
+
+        if (width_utf == 1) {
+
+          // Print invalid placeholder for invalid UTF-8 widths.
+          if (invalid[i]) {
+            fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_incomplete_s, print->set->error);
+          }
+          else {
+            fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_incomplete_s, print->set->warning);
+          }
+        }
+        else if (width_utf == 2) {
+          do_print = F_true;
+        }
+        else if (width_utf == 3) {
+          if (sequence.string[i] >= 0xefbfb000 && sequence.string[i] <= 0xefbfbc00) {
+
+            // Use space to represent Specials codes.
+            // 0xefbfbd00 is excluded because it is printable (and is the "Replacement Character" code).
+            f_print_dynamic_raw(f_string_space_s, print->to);
+          }
+          else if (sequence.string[i] >= 0xe290a700 && sequence.string[i] <= 0xe290bf00) {
+
+            // Use space to represent Control Pictues codes that are not currently defined but are reserved.
+            f_print_dynamic_raw(f_string_space_s, print->to);
+          }
+          else if (sequence.string[i] >= 0xee808000 && sequence.string[i] <= 0xefa3bf00) {
+
+            // Use space to represent Private Use Area codes.
+            f_print_dynamic_raw(f_string_space_s, print->to);
+          }
+          else {
+            do_print = F_true;
+          }
+        }
+        else if (sequence.string[i] >= 0xf09c80a0 && sequence.string[i] <= 0xf09c80bd) {
+
+          // Use space to represent Variation Selectors Supplement codes.
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+        else if (sequence.string[i] >= 0xf3b08080 && sequence.string[i] <= 0xf3bfbfbf) {
+
+          // Use space to represent Supplemental Private Use Area-A codes.
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+        else if (sequence.string[i] >= 0xf4808080 && sequence.string[i] <= 0xf48fbfbf) {
+
+          // Use space to represent Supplemental Private Use Area-B codes.
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+        else {
+          do_print = F_true;
+        }
+
+        if (do_print) {
+          f_print_character(c, print->to);
+
+          if (width_utf > 1) {
+            f_print_character(macro_f_utf_char_t_to_char_2(sequence.string[i]), print->to);
+
+            if (width_utf > 2) {
+              f_print_character(macro_f_utf_char_t_to_char_3(sequence.string[i]), print->to);
+
+              if (width_utf > 3) {
+                f_print_character(macro_f_utf_char_t_to_char_4(sequence.string[i]), print->to);
+              }
+            }
+          }
+
+          if (f_utf_character_is_combining(sequence.string[i]) == F_true) {
+            f_print_dynamic_raw(f_string_space_s, print->to);
+          }
+
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            if (width_utf == 1 || f_utf_character_is_wide(sequence.string[i]) != F_true) {
+              f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+            }
+          }
+        }
+        else {
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+          }
+        }
+      }
+      else {
+        f_print_character(c, print->to);
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+      }
+
+      // Print placeholders when using UTF-8 sequence to simulate the spaces bytes used for the character.
+      if (width_utf > 1 && at + 1 < main->setting.width) {
+        if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+          if (invalid[i]) {
+            fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_placeholder_s, print->set->error);
+          }
+          else if (main->setting.flag & byte_dump_main_flag_classic_e) {
+            f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+          }
+          else {
+            fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+          }
+        }
+        else {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+
+        ++at;
+
+        if (width_utf > 2 && at + 1 < main->setting.width) {
+          if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+            if (invalid[i]) {
+              fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_placeholder_s, print->set->error);
+            }
+            else if (main->setting.flag & byte_dump_main_flag_classic_e) {
+              f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+            }
+            else {
+              fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+            }
+          }
+          else {
+            f_print_dynamic_raw(f_string_space_s, print->to);
+          }
+
+          if (main->setting.flag & byte_dump_main_flag_wide_e) {
+            f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+          }
+
+          ++at;
+
+          if (width_utf > 3 && at + 1 < main->setting.width) {
+            if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+              if (invalid[i]) {
+                fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_placeholder_s, print->set->error);
+              }
+              else if (main->setting.flag & byte_dump_main_flag_classic_e) {
+                f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+              }
+              else {
+                fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+              }
+            }
+            else {
+              f_print_dynamic_raw(f_string_space_s, print->to);
+            }
+
+            if (main->setting.flag & byte_dump_main_flag_wide_e) {
+              f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+            }
+
+            ++at;
+          }
+        }
+      }
+    } // for
+
+    // Print placeholder for the remaining parts of the line.
+    if (main->setting.flag & byte_dump_main_flag_placeholder_e) {
+      for (; at < main->setting.width; ++at) {
+
+        if (invalid[at]) {
+          fl_print_format("%[%r%]", print->to, print->set->error, byte_dump_character_placeholder_s, print->set->error);
+        }
+        else if (main->setting.flag & byte_dump_main_flag_classic_e) {
+          f_print_dynamic_raw(f_string_ascii_period_s, print->to);
+        }
+        else {
+          fl_print_format("%[%r%]", print->to, print->set->warning, byte_dump_character_placeholder_s, print->set->warning);
+        }
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_ascii_space_s, print->to);
+        }
+      } // for
+    }
+    else {
+      for (; at < main->setting.width; ++at) {
+
+        f_print_dynamic_raw(f_string_space_s, print->to);
+
+        if (main->setting.flag & byte_dump_main_flag_wide_e) {
+          f_print_dynamic_raw(f_string_space_s, print->to);
+        }
+      } // for
+    }
+
+    fl_print_format(" %[%r%]%r", print->to, print->set->notable, byte_dump_character_wall_s, print->set->notable, f_string_eol_s);
+  }
+#endif // _di_byte_dump_print_text_
+
+#ifndef _di_byte_dump_print_file_header_
+  f_status_t byte_dump_print_file_header(fl_print_t * const print, const f_string_static_t name) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    byte_dump_main_t * const main = (byte_dump_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    if (name.used) {
+      fl_print_format("%r%[%r of: %]%[", print->to, f_string_eol_s, print->set->title, byte_dump_program_name_long_s, print->set->title, print->set->notable);
+      fl_print_format("%Q%] %[(in ", print->to, name, print->set->notable, print->set->title);
+    }
+    else {
+      fl_print_format("%r%[Piped %q: (in ", print->to, f_string_eol_s, print->set->title, byte_dump_program_name_long_s);
+    }
+
+    if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+      f_print_dynamic_raw(byte_dump_hexidecimal_s, print->to);
+    }
+    else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+      f_print_dynamic_raw(byte_dump_duodecimal_s, print->to);
+    }
+    else if (main->setting.mode == byte_dump_mode_octal_e) {
+      f_print_dynamic_raw(byte_dump_octal_s, print->to);
+    }
+    else if (main->setting.mode == byte_dump_mode_binary_e) {
+      f_print_dynamic_raw(byte_dump_binary_s, print->to);
+    }
+    else if (main->setting.mode == byte_dump_mode_decimal_e) {
+      f_print_dynamic_raw(byte_dump_decimal_s, print->to);
+    }
+
+    fl_print_format(")%]%r", print->to, print->set->title, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_byte_dump_print_file_header_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
similarity index 58%
rename from level_3/byte_dump/c/private-byte_dump.h
rename to level_3/byte_dump/c/main/print/data.h
index 2b9ffa6d9b72ad3632bc1ee7f396f073d3fbed65..c31a687ce1e5291ce917c37419d675e73dc16bc3 100644 (file)
@@ -4,40 +4,25 @@
  * Project: Byte Dump
  * 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 _PRIVATE_byte_dump_h
-#define _PRIVATE_byte_dump_h
+#ifndef _byte_dump_print_data_h
+#define _byte_dump_print_data_h
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * Dump the contents of the file to standard out.
- *
- * @param main
- *   The main program data.
- * @param file_name
- *   The name of the file.
- * @param file
- *   Data for the file to print.
- *   Set to NULL if file is the STDIN pipe.
- *
- * @return
- *   F_none on success.
- *
- *   F_failure (with error bit) on failure, usually when read() fails.
- *   F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- */
-#ifndef _di_byte_dump_file_
-  extern f_status_t byte_dump_file(byte_dump_data_t * const data, const f_string_static_t file_name, const f_file_t file) F_attribute_visibility_internal_d;
-#endif // _di_byte_dump_file_
-
-/**
  * Print a single character hex code and if the width is reached properly terminate the line.
  *
- * @param main
- *   The main program data.
+ * @param print
+ *   Designates the how and where to print.
+ *
+ *   This does not alter print.custom.setting.state.status.
  * @param sequence
  *   An array of UTF-8 and ASCII characters.
  * @param invalid
@@ -71,7 +56,7 @@ extern "C" {
  * @see byte_dump_print_text()
  */
 #ifndef _di_byte_dump_print_character_fragment_
-  extern bool byte_dump_print_character_fragment(byte_dump_data_t * const data, const f_utf_string_static_t sequence, const f_char_t invalid[], const uint8_t width_utf, const f_char_t byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, f_char_t *offset) F_attribute_visibility_internal_d;
+  extern f_status_t byte_dump_print_character_fragment(fl_print_t * const print, const f_utf_string_static_t sequence, const f_char_t invalid[], const uint8_t width_utf, const f_char_t byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, f_char_t *offset);
 #endif // _di_byte_dump_print_character_fragment_
 
 /**
@@ -79,8 +64,33 @@ extern "C" {
  *
  * This should be called only when text mode is enabled.
  *
- * @param main
- *   The main program data.
+ * @param print
+ *   Designates the how and where to print.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param name
+ *   The name of the file the header is associated with.
+ *   If name.used is 0 then this is assumed to be the input pipe.
+ *
+ * @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_byte_dump_print_file_header_
+  extern f_status_t byte_dump_print_file_header(fl_print_t * const print, const f_string_static_t name);
+#endif // _di_byte_dump_print_file_header_
+
+/**
+ * Print the text representation alongside the hex display.
+ *
+ * This should be called only when text mode is enabled.
+ *
+ * @param print
+ *   Designates the how and where to print.
+ *
+ *   This does not alter print.custom.setting.state.status.
  * @param sequence
  *   An array of UTF-8 and ASCII characters.
  * @param invalid
@@ -91,13 +101,19 @@ extern "C" {
  * @param offset
  *   The offset to apply before printing column cells for the row.
  *   Will be reduced to 0 once used.
+ *
+ * @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_byte_dump_print_text_
-  extern void byte_dump_print_text(byte_dump_data_t * const data, const f_utf_string_static_t sequence, const f_char_t invalid[], byte_dump_previous_t *previous, f_char_t *offset) F_attribute_visibility_internal_d;
+  extern f_status_t byte_dump_print_text(fl_print_t * const print, const f_utf_string_static_t sequence, const f_char_t invalid[], byte_dump_previous_t *previous, f_char_t *offset);
 #endif // _di_byte_dump_print_text_
 
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
-#endif // _PRIVATE_byte_dump_h
+#endif // _byte_dump_print_data_h
diff --git a/level_3/byte_dump/c/main/print/error.c b/level_3/byte_dump/c/main/print/error.c
new file mode 100644 (file)
index 0000000..fb0ebba
--- /dev/null
@@ -0,0 +1,133 @@
+#include "../byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_print_error_
+  f_status_t byte_dump_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(((byte_dump_main_t *) print->custom)->setting.state.status), function, fll_error_file_flag_fallback_e);
+
+    return F_none;
+  }
+#endif // _di_byte_dump_print_error_
+
+#ifndef _di_byte_dump_print_error_file_
+  f_status_t byte_dump_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;
+
+    byte_dump_main_t * const main = (byte_dump_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_byte_dump_print_error_file_
+
+#ifndef _di_fll_program_print_error_file_code_invalid_
+  f_status_t fll_program_print_error_file_code_invalid(fl_print_t * const print, const f_string_static_t name) {
+
+    if (!print || !print->custom) 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("%[Invalid UTF-8 codes were detected for file '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, name.used ? name : f_string_ascii_minus_s, print->set->notable);
+    fl_print_format("%['.%]%r%r", print->to, print->set->error, print->set->error, f_string_eol_s, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_fll_program_print_error_file_code_invalid_
+
+#ifndef _di_byte_dump_print_error_file_none_
+  f_status_t byte_dump_print_error_file_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 files are specified, please pipe data or designate a file.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s);
+
+    return F_none;
+  }
+#endif // _di_byte_dump_print_error_file_none_
+
+#ifndef _di_fll_program_print_error_file_read_
+  f_status_t fll_program_print_error_file_read(fl_print_t * const print, const f_string_static_t name) {
+
+    if (!print || !print->custom) 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("%[%Qread() failed for '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, name.used ? name : f_string_ascii_minus_s, print->set->notable);
+    fl_print_format("%['.%]%r%r", print->to, print->set->error, print->set->error, f_string_eol_s, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_fll_program_print_error_file_read_
+
+#ifndef _di_fll_program_print_error_parameter_first_greater_than_last_
+  f_status_t fll_program_print_error_parameter_first_greater_than_last(fl_print_t * const print) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    byte_dump_main_t * const main = (byte_dump_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe value '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, main->setting.first, print->set->notable);
+    fl_print_format("%[' for the parameter '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_first_s, print->set->notable);
+    fl_print_format("%[' cannot be greater than the value '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, main->setting.last, print->set->notable);
+    fl_print_format("%[' for the parameter '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_last_s, 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_fll_program_print_error_parameter_first_greater_than_last_
+
+#ifndef _di_byte_dump_print_error_parameter_range_out_
+  f_status_t byte_dump_print_error_parameter_range_out(fl_print_t * const print, const f_string_static_t name, const f_number_unsigned_t minimum, const f_number_unsigned_t maximum, const f_string_static_t number) {
+
+    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 '%]", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, number, print->set->notable);
+    fl_print_format("%[' for the parameter '%]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[%r%Q%]", print->to, print->set->notable, f_console_symbol_long_normal_s, name, print->set->notable);
+    fl_print_format("%[' can only be a number (inclusively) between %]", print->to, print->set->error, print->set->error);
+    fl_print_format("%[ul%]", print->to, print->set->notable, minimum, print->set->notable);
+    fl_print_format(" %[and%] ", print->to, print->set->error, print->set->error);
+    fl_print_format("%[ul%]", print->to, print->set->notable, maximum, 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_byte_dump_print_error_parameter_range_out_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/print/error.h b/level_3/byte_dump/c/main/print/error.h
new file mode 100644 (file)
index 0000000..0f544e7
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_print_error_h
+#define _byte_dump_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_byte_dump_print_error_
+  extern f_status_t byte_dump_print_error(fl_print_t * const print, const f_string_t function);
+#endif // _di_byte_dump_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_byte_dump_print_error_file_
+  extern f_status_t byte_dump_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_byte_dump_print_error_file_
+
+/**
+ * Print error message for when file contains invalid UTF-8 codes.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param name
+ *   The name of the file the header is associated with.
+ *   If name.used is 0 then this is assumed to be the input pipe.
+ *
+ * @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_fll_program_print_error_file_code_invalid_
+  extern f_status_t fll_program_print_error_file_code_invalid(fl_print_t * const print, const f_string_static_t name);
+#endif // _di_fll_program_print_error_file_code_invalid_
+
+/**
+ * Print error message for when no files are 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_byte_dump_print_error_file_none_
+  extern f_status_t byte_dump_print_error_file_none(fl_print_t * const print);
+#endif // _di_byte_dump_print_error_file_none_
+
+/**
+ * Print error message on file read error.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param name
+ *   The name of the file the header is associated with.
+ *   If name.used is 0 then this is assumed to be the input pipe.
+ *
+ * @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_fll_program_print_error_file_read_
+  extern f_status_t fll_program_print_error_file_read(fl_print_t * const print, const f_string_static_t name);
+#endif // _di_fll_program_print_error_file_read_
+
+/**
+ * Print error about "first" parameter value being greater than the "last" parameter value.
+ *
+ * @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_fll_program_print_error_parameter_first_greater_than_last_
+  extern f_status_t fll_program_print_error_parameter_first_greater_than_last(fl_print_t * const print);
+#endif // _di_fll_program_print_error_parameter_first_greater_than_last_
+
+/**
+ * Print error about given value being out of range.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param name
+ *   The name of the parameter.
+ * @param minimum
+ *   The inclusive non-negative minimum allowed number.
+ * @param maximum
+ *   The inclusive non-negative maximum allowed number.
+ * @param number
+ *   A string that is supposed to be a valid number within range (but is not).
+ *
+ * @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_byte_dump_print_error_parameter_range_out_
+  extern f_status_t byte_dump_print_error_parameter_range_out(fl_print_t * const print, const f_string_static_t name, const f_number_unsigned_t minimum, const f_number_unsigned_t maximum, const f_string_static_t number);
+#endif // _di_byte_dump_print_error_parameter_range_out_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_print_error_h
similarity index 62%
rename from level_3/byte_dump/c/print.c
rename to level_3/byte_dump/c/main/print/message.c
index 0a3467d5d737b8d8f9b26fd8da6588d51569606f..5e44bcef7285b8d7bef8ac2e2355de38648af9e5 100644 (file)
@@ -1,20 +1,23 @@
-#include "byte_dump.h"
-#include "private-common.h"
+#include "../byte_dump.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef _di_byte_dump_print_help_
-  f_status_t byte_dump_print_help(byte_dump_setting_t * const setting, const fl_print_t print) {
+#ifndef _di_byte_dump_print_message_help_
+  f_status_t byte_dump_print_message_help(fl_print_t * const print) {
 
-    f_file_stream_lock(print.to);
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+
+    byte_dump_main_t * const main = (byte_dump_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
 
     fll_program_print_help_header(print, byte_dump_program_name_long_s, byte_dump_program_version_s);
 
     fll_program_print_help_option_standard(print);
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
     fll_program_print_help_option(print, byte_dump_short_binary_s, byte_dump_long_binary_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "     Display binary representation.");
     fll_program_print_help_option(print, byte_dump_short_decimal_s, byte_dump_long_decimal_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "    Display decimal representation.");
@@ -23,12 +26,12 @@ extern "C" {
     fll_program_print_help_option(print, byte_dump_short_octal_s, byte_dump_long_octal_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "      Display octal representation.");
     fll_program_print_help_option(print, byte_dump_short_unicode_s, byte_dump_long_unicode_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "    Display using Unicode representation for valid Unicode (like: U+0000).");
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
     fll_program_print_help_option(print, byte_dump_short_first_s, byte_dump_long_first_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Start reading at this byte offset.");
     fll_program_print_help_option(print, byte_dump_short_last_s, byte_dump_long_last_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Stop reading at this (inclusive) byte offset.");
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
     fll_program_print_help_option(print, byte_dump_short_narrow_s, byte_dump_long_narrow_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "     Use narrow display, resulting in 1*width reducing size of the text columns.");
     fll_program_print_help_option(print, byte_dump_short_placeholder_s, byte_dump_long_placeholder_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Use a placeholder character instead of a space for placeholders.");
@@ -36,38 +39,34 @@ extern "C" {
     fll_program_print_help_option(print, byte_dump_short_wide_s, byte_dump_long_wide_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "       Use wide display, resulting in 2*width allowing for space for wide characters in the text columns.");
     fll_program_print_help_option(print, byte_dump_short_width_s, byte_dump_long_width_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "      Set number of columns of Bytes to display.");
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
-    f_print_dynamic_raw(f_string_eol_s, print.to);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
-    fl_print_format(" %[Special Options:%] ", print.to, context.set.important, context.set.important);
+    fl_print_format(" %[Special Options:%] ", print->to, print->set->important, print->set->important);
 
-    fll_program_print_help_option_long(print.to, context, byte_dump_long_normal_s, f_console_symbol_long_normal_s, " Display UTF-8 symbols for ASCII control codes.");
-    fll_program_print_help_option_long(print.to, context, byte_dump_long_simple_s, f_console_symbol_long_normal_s, " Display spaces for ASCII control codes.");
-    fll_program_print_help_option_long(print.to, context, byte_dump_long_classic_s, f_console_symbol_long_normal_s, "Display periods for ASCII control codes.");
+    fll_program_print_help_option_long(print, byte_dump_long_normal_s, f_console_symbol_long_normal_s, " Display UTF-8 symbols for ASCII control codes.");
+    fll_program_print_help_option_long(print, byte_dump_long_simple_s, f_console_symbol_long_normal_s, " Display spaces for ASCII control codes.");
+    fll_program_print_help_option_long(print, byte_dump_long_classic_s, f_console_symbol_long_normal_s, "Display periods for ASCII control codes.");
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
-    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, byte_dump_program_name_s, fll_program_parameter_filenames_s);
 
-    f_print_dynamic_raw(f_string_eol_s, print.to);
-
-    fl_print_format("  When using the %[%r%r%] option, some UTF-8 characters may be replaced by your instance and cause display alignment issues.%r%r", print.to, context.set.notable, f_console_symbol_long_normal_s, byte_dump_long_text_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+    fl_print_format("%r  When using the %[%r%r%] option, some UTF-8 characters may be replaced by your instance and cause display alignment issues.%r%r", print->to, f_string_eol_s, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_text_s, print->set->notable, f_string_eol_s, f_string_eol_s);
 
-    fl_print_format("  Special UTF-8 characters and non-spacing UTF-8 characters may be replaced with a space (or a placeholder when the %[%r%r%] option is used).%r%r", print.to, context.set.notable, f_console_symbol_long_normal_s, byte_dump_long_placeholder_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+    fl_print_format("  Special UTF-8 characters and non-spacing UTF-8 characters may be replaced with a space (or a placeholder when the %[%r%r%] option is used).%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_placeholder_s, print->set->notable, f_string_eol_s, f_string_eol_s);
 
-    fl_print_format("  UTF-8 \"Combining\" characters might have a space appended to allow a proper display but this may cause copy and paste issues.%r%r", print.to, f_string_eol_s, f_string_eol_s);
+    fl_print_format("  UTF-8 \"Combining\" characters might have a space appended to allow a proper display but this may cause copy and paste issues.%r%r", print->to, f_string_eol_s, f_string_eol_s);
 
-    fl_print_format("  When %[%r%r%] is used, any UTF-8 sequences will still be printed in full should any part is found within the requested range.%r%r", print.to, context.set.notable, f_console_symbol_long_normal_s, byte_dump_long_last_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+    fl_print_format("  When %[%r%r%] is used, any UTF-8 sequences will still be printed in full should any part is found within the requested range.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_last_s, print->set->notable, f_string_eol_s, f_string_eol_s);
 
-    fl_print_format("  When using the %[%r%r%] option, invalid Unicode will fallback to being displayed using one of the other modes.%r", print.to, context.set.notable, f_console_symbol_long_normal_s, byte_dump_long_unicode_s, context.set.notable, f_string_eol_s);
+    fl_print_format("  When using the %[%r%r%] option, invalid Unicode will fallback to being displayed using one of the other modes.%r", print->to, print->set->notable, f_console_symbol_long_normal_s, byte_dump_long_unicode_s, print->set->notable, f_string_eol_s);
 
-    f_file_stream_flush(output);
-    f_file_stream_unlock(print.to);
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
 
     return F_none;
   }
-#endif // _di_byte_dump_print_help_
+#endif // _di_byte_dump_print_message_help_
 
 #ifdef __cplusplus
 } // extern "C"
diff --git a/level_3/byte_dump/c/main/print/message.h b/level_3/byte_dump/c/main/print/message.h
new file mode 100644 (file)
index 0000000..59f9ee0
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_print_message_h
+#define _byte_dump_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_byte_dump_print_message_help_
+  extern f_status_t byte_dump_print_message_help(fl_print_t * const print);
+#endif // _di_byte_dump_print_message_help_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_print_message_h
diff --git a/level_3/byte_dump/c/main/process.c b/level_3/byte_dump/c/main/process.c
new file mode 100644 (file)
index 0000000..b937e2e
--- /dev/null
@@ -0,0 +1,332 @@
+#include "byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_byte_dump_process_file_
+  void byte_dump_process_file(byte_dump_main_t * const main, const f_string_static_t name, const f_file_t file) {
+
+    if (!main) return;
+
+    uint64_t position = 0;
+    f_char_t byte = 0;
+    f_char_t offset = 0;
+    int byte_get = 0;
+
+    int8_t width_utf = -1;
+    int8_t width_count = 0;
+
+    byte_dump_cell_t cell = byte_dump_cell_t_initialize;
+    byte_dump_previous_t previous = byte_dump_previous_t_initialize;
+
+    bool character_reset = 0;
+    bool found_invalid_utf = F_false;
+
+    // Store the current character main until it can be printed.
+    f_utf_string_dynamic_t sequence = f_utf_string_dynamic_t_initialize;
+    f_utf_char_t block[main->setting.width];
+    f_number_unsigned_t current = 0;
+
+    // The row starts based on the first byte starting point and how many columns of bytes are displayed per row.
+    if (main->setting.first) {
+      cell.row = main->setting.first / main->setting.width;
+      offset = main->setting.first % main->setting.width;
+
+      // fseek() cannot be used on a PIPE, so read instead of seek.
+      if (name.used) {
+        byte_get = fseek(file.stream, main->setting.first, SEEK_SET);
+      }
+      else {
+        f_char_t skip[main->setting.first];
+
+        byte_get = fread(skip, 1, main->setting.first, file.stream);
+      }
+    }
+
+    memset(&block, 0, sizeof(f_utf_char_t) * main->setting.width);
+    sequence.string = block;
+    sequence.used = 0;
+    sequence.size = main->setting.width;
+
+    // Record when a character is invalid.
+    f_char_t invalid[main->setting.width];
+    memset(&invalid, 0, sizeof(f_char_t) * main->setting.width);
+
+    if (byte_get >= 0) {
+      for (;;) {
+
+        if (byte_dump_signal_check(main)) return;
+
+        byte_get = getc(file.stream);
+
+        if (byte_get < 0) {
+          if (width_utf == -1 && character_reset) {
+            sequence.used = 0;
+            character_reset = F_false;
+            memset(&invalid, 0, sizeof(f_char_t) * main->setting.width);
+          }
+
+          break;
+        }
+
+        byte = (f_char_t) byte_get;
+
+        // Storing the next character is designated by width_utf == -1.
+        if (width_utf == -1) {
+          width_utf = macro_f_utf_byte_width_is(byte);
+          width_count = 0;
+
+          // The character is reset, the sequence.used is to be reset.
+          if (character_reset) {
+            sequence.used = 0;
+            character_reset = F_false;
+            memset(&invalid, 0, sizeof(f_char_t) * main->setting.width);
+          }
+
+          current = sequence.used++;
+          invalid[current] = 0;
+        }
+
+        // When width_count == 0, then this is that start of a new character sequence.
+        if (!width_count) {
+          sequence.string[current] = macro_f_utf_char_t_from_char_1(byte);
+          width_count = 1;
+
+          // The first character in a UTF-8 sequence cannot have a width of 1.
+          if (width_utf == 1) {
+            found_invalid_utf = F_true;
+            invalid[current] = 1;
+          }
+          // Process the UTF-8 character.
+          else if (width_utf > 1) {
+            continue;
+          }
+        }
+        // Process a UTF-8 character fragment.
+        else if (width_count < width_utf) {
+          if (width_count == 1) {
+            sequence.string[current] |= macro_f_utf_char_t_from_char_2(byte);
+          }
+          else if (width_count == 2) {
+            sequence.string[current] |= macro_f_utf_char_t_from_char_3(byte);
+          }
+          else if (width_count == 3) {
+            sequence.string[current] |= macro_f_utf_char_t_from_char_4(byte);
+          }
+
+          ++width_count;
+
+          // Grab the next UTF-8 character fragment if the entire sequence is not collected yet.
+          if (width_count < width_utf) continue;
+        }
+
+        // At this point: an ASCII character is collected, the entire UTF-8 character sequence is collected, or an invalid UTF-8 was processed.
+        if (!invalid[current] && width_utf > 1) {
+          if (f_utf_character_is_valid(sequence.string[current]) != F_true) {
+            found_invalid_utf = F_true;
+            invalid[current] = width_utf;
+          }
+          else if (f_utf_character_is_unassigned(sequence.string[current]) == F_true) {
+
+            // Consider unassigned invalid.
+            found_invalid_utf = F_true;
+            invalid[current] = width_utf;
+          }
+        }
+
+        f_file_stream_lock(main->program.output.to);
+
+        if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 1, &previous, &cell, &offset) == F_true) {
+          character_reset = F_true;
+        }
+
+        if (width_utf > 1) {
+          if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 2, &previous, &cell, &offset) == F_true) {
+            character_reset = F_true;
+          }
+
+          if (width_utf > 2) {
+            if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 3, &previous, &cell, &offset) == F_true) {
+              character_reset = F_true;
+            }
+
+            if (width_utf > 3) {
+              if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 4, &previous, &cell, &offset) == F_true) {
+                character_reset = F_true;
+              }
+            }
+          }
+
+          if (main->setting.last) {
+            position += width_utf;
+
+            if (position >= main->setting.last) {
+              f_file_stream_unlock(main->program.output.to);
+
+              break;
+            }
+          }
+        }
+        else if (main->setting.last) {
+          ++position;
+
+          if (position >= main->setting.last) {
+            f_file_stream_unlock(main->program.output.to);
+
+            break;
+          }
+        }
+
+        f_file_stream_unlock(main->program.output.to);
+
+        width_utf = -1;
+      } // for
+    }
+
+    f_file_stream_lock(main->program.output.to);
+
+    // Print placeholders to fill out the remaining line and then optionally print the text block.
+    if (cell.column && cell.column < main->setting.width) {
+      const uint8_t width_missing = width_utf <= 0 ? 0 : width_utf - width_count;
+
+      if (width_missing) {
+        const uint8_t column_offset = main->setting.width - cell.column;
+        width_count = 0;
+
+        // Handle incomplete character at the end of the stream.
+        found_invalid_utf = F_true;
+        invalid[current] = width_utf;
+
+        if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 1, &previous, &cell, &offset) == F_true) {
+          character_reset = F_true;
+        }
+
+        if (++width_count < width_missing) {
+          if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 2, &previous, &cell, &offset) == F_true) {
+            character_reset = F_true;
+          }
+
+          if (++width_count < width_missing) {
+            if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 3, &previous, &cell, &offset) == F_true) {
+              character_reset = F_true;
+            }
+
+            if (++width_count < width_missing) {
+              if (byte_dump_print_character_fragment(&main->program.output, sequence, invalid, width_utf, 4, &previous, &cell, &offset) == F_true) {
+                character_reset = F_true;
+              }
+            }
+          }
+        }
+
+        if (character_reset) {
+          sequence.used = 0;
+          memset(&invalid, 0, sizeof(f_char_t) * main->setting.width);
+
+          previous.bytes = column_offset;
+          previous.invalid = previous.bytes;
+        }
+        else {
+          previous.bytes = 0;
+          previous.invalid = 0;
+        }
+      }
+      else {
+        previous.bytes = 0;
+        previous.invalid = 0;
+      }
+    }
+
+    if (cell.column && cell.column < main->setting.width) {
+      while (cell.column < main->setting.width) {
+
+        if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+          f_print_terminated("         ", main->program.output.to);
+        }
+        else if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+          f_print_terminated("   ", main->program.output.to);
+        }
+        else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+          f_print_terminated("    ", main->program.output.to);
+        }
+        else if (main->setting.mode == byte_dump_mode_octal_e) {
+          f_print_terminated("    ", main->program.output.to);
+        }
+        else if (main->setting.mode == byte_dump_mode_binary_e) {
+          f_print_terminated("         ", main->program.output.to);
+        }
+        else if (main->setting.mode == byte_dump_mode_decimal_e) {
+          f_print_terminated("    ", main->program.output.to);
+        }
+
+        ++cell.column;
+
+        if (cell.column < main->setting.width) {
+          if (main->setting.flag & byte_dump_main_flag_unicode_e) {
+            if (!(cell.column % 4)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+          else if (main->setting.mode == byte_dump_mode_hexidecimal_e) {
+            if (!(cell.column % 8)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+          else if (main->setting.mode == byte_dump_mode_duodecimal_e) {
+            if (!(cell.column % 6)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+          else if (main->setting.mode == byte_dump_mode_octal_e) {
+            if (!(cell.column % 6)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+          else if (main->setting.mode == byte_dump_mode_binary_e) {
+            if (!(cell.column % 6)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+          else if (main->setting.mode == byte_dump_mode_decimal_e) {
+            if (!(cell.column % 6)) {
+              f_print_dynamic_raw(f_string_space_s, main->program.output.to);
+            }
+          }
+        }
+      } // while
+
+      if (main->setting.flag & byte_dump_main_flag_text_e) {
+        byte_dump_print_text(&main->program.output, sequence, invalid, &previous, &offset);
+      }
+      else {
+        f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+      }
+    }
+
+    f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
+
+    f_file_stream_unlock(main->program.output.to);
+    f_file_stream_flush(main->program.output.to);
+
+    if (found_invalid_utf) {
+      f_file_stream_flush(main->program.error.to);
+
+      fll_program_print_error_file_code_invalid(&main->program.error, name);
+    }
+
+    if (ferror(file.stream)) {
+      f_file_stream_flush(main->program.error.to);
+
+      fll_program_print_error_file_read(&main->program.error, name);
+    }
+
+    if (!F_status_is_error(main->setting.state.status)) {
+      main->setting.state.status = F_none;
+    }
+  }
+#endif // byte_dump_process_file
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/process.h b/level_3/byte_dump/c/main/process.h
new file mode 100644 (file)
index 0000000..451c6d4
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_process_h
+#define _byte_dump_process_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dump the contents of the file to standard out.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *
+ *     F_failure (with error bit) on failure, usually when read() fails.
+ *     F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
+ * @param name
+ *   The name of the file.
+ * @param file
+ *   Data for the file to print.
+ *   Set to NULL if file is the STDIN pipe.
+ */
+#ifndef _di_byte_dump_process_file_
+  extern void byte_dump_process_file(byte_dump_main_t * const main, const f_string_static_t name, const f_file_t file);
+#endif // _di_byte_dump_process_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_process_h
diff --git a/level_3/byte_dump/c/main/signal.c b/level_3/byte_dump/c/main/signal.c
new file mode 100644 (file)
index 0000000..20c3667
--- /dev/null
@@ -0,0 +1,111 @@
+#include "byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_byte_dump_signal_check_) && defined(_di_thread_support_)
+  f_status_t byte_dump_signal_check(byte_dump_main_t * const main) {
+
+    if (!main || main->program.signal.id == -1) return F_false;
+
+    if (!((++main->program.signal_check) % byte_dump_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_byte_dump_signal_check_) && defined(_di_thread_support_)
+
+#if !defined(_di_byte_dump_signal_check_) && !defined(_di_thread_support_)
+  f_status_t byte_dump_signal_check(byte_dump_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_byte_dump_signal_check_) && !defined(_di_thread_support_)
+
+#if !defined(_di_byte_dump_signal_handler_) && !defined(_di_thread_support_)
+  void byte_dump_signal_handler(byte_dump_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 >= byte_dump_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_byte_dump_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/signal.h b/level_3/byte_dump/c/main/signal.h
new file mode 100644 (file)
index 0000000..4a7f789
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_signal_h
+#define _byte_dump_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 byte_dump_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 byte_dump_signal_handler()
+ *
+ * @see fll_program_standard_signal_received()
+ */
+#ifndef _di_byte_dump_signal_check_
+  extern f_status_t byte_dump_signal_check(byte_dump_main_t * const main);
+#endif // _di_byte_dump_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_byte_dump_signal_handler_) && !defined(_di_thread_support_)
+  extern void byte_dump_signal_handler(byte_dump_main_t * const main);
+#endif // !defined(_di_byte_dump_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_signal_h
diff --git a/level_3/byte_dump/c/main/thread.c b/level_3/byte_dump/c/main/thread.c
new file mode 100644 (file)
index 0000000..f68baf8
--- /dev/null
@@ -0,0 +1,26 @@
+#include "byte_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_byte_dump_thread_signal_) && !defined(_di_thread_support_)
+  void * byte_dump_thread_signal(void * const main) {
+
+    f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+    if (main) {
+      byte_dump_signal_handler((byte_dump_main_t *) main);
+    }
+
+    return 0;
+  }
+#endif // !defined(_di_byte_dump_thread_signal_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/byte_dump/c/main/thread.h b/level_3/byte_dump/c/main/thread.h
new file mode 100644 (file)
index 0000000..7d2fbb5
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Byte Dump
+ * 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 _byte_dump_thread_h
+#define _byte_dump_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 byte_dump_main_t.
+ *
+ * @return
+ *   0, always.
+ *
+ * @see f_thread_cancel_state_set()
+ *
+ * @see byte_dump_signal_handler()
+ */
+#if !defined(_di_byte_dump_thread_signal_) && !defined(_di_thread_support_)
+  extern void * byte_dump_thread_signal(void * const main);
+#endif // !defined(_di_byte_dump_thread_signal_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _byte_dump_thread_h
diff --git a/level_3/byte_dump/c/print.h b/level_3/byte_dump/c/print.h
deleted file mode 100644 (file)
index 9fc38d1..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Byte Dump
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _byte_dump_print_h
-#define _byte_dump_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print help.
- *
- * @param setting
- *   The main program settings.
- *
- *   This does not alter setting.state.status.
- * @param output
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- *
- * @see byte_dump_main()
- */
-#ifndef _di_byte_dump_print_help_
-  extern f_status_t byte_dump_print_help(byte_dump_setting_t * const setting, const fl_print_t print);
-#endif // _di_byte_dump_print_help_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _byte_dump_print_h
diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c
deleted file mode 100644 (file)
index a8f769b..0000000
+++ /dev/null
@@ -1,1035 +0,0 @@
-#include "byte_dump.h"
-#include "private-common.h"
-#include "private-byte_dump.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_byte_dump_file_
-  f_status_t byte_dump_file(byte_dump_data_t * const data, const f_string_static_t file_name, const f_file_t file) {
-
-    f_status_t status = F_none;
-
-    uint64_t position = 0;
-    f_char_t byte = 0;
-    f_char_t offset = 0;
-    int byte_get = 0;
-
-    int8_t width_utf = -1;
-    int8_t width_count = 0;
-
-    byte_dump_cell_t cell = byte_dump_cell_t_initialize;
-    byte_dump_previous_t previous = byte_dump_previous_t_initialize;
-
-    bool character_reset = 0;
-    bool found_invalid_utf = F_false;
-
-    // Store the current character main until it can be printed.
-    f_utf_string_dynamic_t sequence = f_utf_string_dynamic_t_initialize;
-    f_utf_char_t block[data->width];
-    f_number_unsigned_t current = 0;
-
-    // The row starts based on the first byte starting point and how many columns of bytes are displayed per row.
-    if (data->first) {
-      cell.row = data->first / data->width;
-      offset = data->first % data->width;
-
-      // fseek() cannot be used on a PIPE, so read instead of seek.
-      if (file_name.used) {
-        byte_get = fseek(file.stream, data->first, SEEK_SET);
-      }
-      else {
-        f_char_t skip[data->first];
-
-        byte_get = fread(skip, 1, data->first, file.stream);
-      }
-    }
-
-    memset(&block, 0, sizeof(f_utf_char_t) * data->width);
-    sequence.string = block;
-    sequence.used = 0;
-    sequence.size = data->width;
-
-    // Record when a character is invalid.
-    f_char_t invalid[data->width];
-    memset(&invalid, 0, sizeof(f_char_t) * data->width);
-
-    if (byte_get >= 0) {
-      for (;;) {
-
-        if (!((++data->main->signal_check) % byte_dump_signal_check_d)) {
-          if (fll_program_standard_signal_received(data->main)) {
-            fll_program_print_signal_received(main->warning, main->signal_received);
-
-            return F_status_set_error(F_interrupt);
-          }
-
-          data->main->signal_check = 0;
-        }
-
-        byte_get = getc(file.stream);
-
-        if (byte_get < 0) {
-          if (width_utf == -1 && character_reset) {
-            sequence.used = 0;
-            character_reset = F_false;
-            memset(&invalid, 0, sizeof(f_char_t) * data->width);
-          }
-
-          break;
-        }
-
-        byte = (f_char_t) byte_get;
-
-        // Storing the next character is designated by width_utf == -1.
-        if (width_utf == -1) {
-          width_utf = macro_f_utf_byte_width_is(byte);
-          width_count = 0;
-
-          // The character is reset, the sequence.used is to be reset.
-          if (character_reset) {
-            sequence.used = 0;
-            character_reset = F_false;
-            memset(&invalid, 0, sizeof(f_char_t) * data->width);
-          }
-
-          current = sequence.used++;
-          invalid[current] = 0;
-        }
-
-        // When width_count == 0, then this is that start of a new character sequence.
-        if (!width_count) {
-          sequence.string[current] = macro_f_utf_char_t_from_char_1(byte);
-          width_count = 1;
-
-          // The first character in a UTF-8 sequence cannot have a width of 1.
-          if (width_utf == 1) {
-            found_invalid_utf = F_true;
-            invalid[current] = 1;
-          }
-          // Process the UTF-8 character.
-          else if (width_utf > 1) {
-            continue;
-          }
-        }
-        // Process a UTF-8 character fragment.
-        else if (width_count < width_utf) {
-          if (width_count == 1) {
-            sequence.string[current] |= macro_f_utf_char_t_from_char_2(byte);
-          }
-          else if (width_count == 2) {
-            sequence.string[current] |= macro_f_utf_char_t_from_char_3(byte);
-          }
-          else if (width_count == 3) {
-            sequence.string[current] |= macro_f_utf_char_t_from_char_4(byte);
-          }
-
-          ++width_count;
-
-          // Grab the next UTF-8 character fragment if the entire sequence is not collected yet.
-          if (width_count < width_utf) continue;
-        }
-
-        // At this point: an ASCII character is collected, the entire UTF-8 character sequence is collected, or an invalid UTF-8 was processed.
-        if (!invalid[current] && width_utf > 1) {
-          if (f_utf_character_is_valid(sequence.string[current]) != F_true) {
-            found_invalid_utf = F_true;
-            invalid[current] = width_utf;
-          }
-          else if (f_utf_character_is_unassigned(sequence.string[current]) == F_true) {
-
-            // Consider unassigned invalid.
-            found_invalid_utf = F_true;
-            invalid[current] = width_utf;
-          }
-        }
-
-        f_file_stream_lock(data->main->output);
-
-        if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 1, &previous, &cell, &offset) == F_true) {
-          character_reset = F_true;
-        }
-
-        if (width_utf > 1) {
-          if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 2, &previous, &cell, &offset) == F_true) {
-            character_reset = F_true;
-          }
-
-          if (width_utf > 2) {
-            if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 3, &previous, &cell, &offset) == F_true) {
-              character_reset = F_true;
-            }
-
-            if (width_utf > 3) {
-              if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 4, &previous, &cell, &offset) == F_true) {
-                character_reset = F_true;
-              }
-            }
-          }
-
-          if (data->last) {
-            position += width_utf;
-
-            if (position >= data->last) {
-              f_file_stream_unlock(data->main->output);
-
-              break;
-            }
-          }
-        }
-        else if (data->last) {
-          ++position;
-
-          if (position >= data->last) {
-            f_file_stream_unlock(data->main->output);
-
-            break;
-          }
-        }
-
-        f_file_stream_unlock(data->main->output);
-
-        width_utf = -1;
-      } // for
-    }
-
-    f_file_stream_lock(data->main->output);
-
-    // Print placeholders to fill out the remaining line and then optionally print the text block.
-    if (cell.column && cell.column < data->width) {
-      const uint8_t width_missing = width_utf <= 0 ? 0 : width_utf - width_count;
-
-      if (width_missing) {
-        const uint8_t column_offset = data->width - cell.column;
-        width_count = 0;
-
-        // Handle incomplete character at the end of the stream.
-        found_invalid_utf = F_true;
-        invalid[current] = width_utf;
-
-        if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 1, &previous, &cell, &offset) == F_true) {
-          character_reset = F_true;
-        }
-
-        if (++width_count < width_missing) {
-          if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 2, &previous, &cell, &offset) == F_true) {
-            character_reset = F_true;
-          }
-
-          if (++width_count < width_missing) {
-            if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 3, &previous, &cell, &offset) == F_true) {
-              character_reset = F_true;
-            }
-
-            if (++width_count < width_missing) {
-              if (byte_dump_print_character_fragment(data, sequence, invalid, width_utf, 4, &previous, &cell, &offset) == F_true) {
-                character_reset = F_true;
-              }
-            }
-          }
-        }
-
-        if (character_reset) {
-          sequence.used = 0;
-          memset(&invalid, 0, sizeof(f_char_t) * data->width);
-
-          previous.bytes = column_offset;
-          previous.invalid = previous.bytes;
-        }
-        else {
-          previous.bytes = 0;
-          previous.invalid = 0;
-        }
-      }
-      else {
-        previous.bytes = 0;
-        previous.invalid = 0;
-      }
-    }
-
-    if (cell.column && cell.column < data->width) {
-      while (cell.column < data->width) {
-
-        if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-          f_print_terminated("         ", data->main->output.to);
-        }
-        else if (data->mode == byte_dump_mode_hexidecimal_e) {
-          f_print_terminated("   ", data->main->output.to);
-        }
-        else if (data->mode == byte_dump_mode_duodecimal_e) {
-          f_print_terminated("    ", data->main->output.to);
-        }
-        else if (data->mode == byte_dump_mode_octal_e) {
-          f_print_terminated("    ", data->main->output.to);
-        }
-        else if (data->mode == byte_dump_mode_binary_e) {
-          f_print_terminated("         ", data->main->output.to);
-        }
-        else if (data->mode == byte_dump_mode_decimal_e) {
-          f_print_terminated("    ", data->main->output.to);
-        }
-
-        ++cell.column;
-
-        if (cell.column < data->width) {
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            if (!(cell.column % 4)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-          else if (data->mode == byte_dump_mode_hexidecimal_e) {
-            if (!(cell.column % 8)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-          else if (data->mode == byte_dump_mode_duodecimal_e) {
-            if (!(cell.column % 6)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-          else if (data->mode == byte_dump_mode_octal_e) {
-            if (!(cell.column % 6)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-          else if (data->mode == byte_dump_mode_binary_e) {
-            if (!(cell.column % 6)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-          else if (data->mode == byte_dump_mode_decimal_e) {
-            if (!(cell.column % 6)) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          }
-        }
-      } // while
-
-      if (data->main->parameters.array[byte_dump_parameter_text_e].result & f_console_result_found_e) {
-        byte_dump_print_text(data, sequence, invalid, &previous, &offset);
-      }
-      else {
-        f_print_dynamic_raw(f_string_eol_s, data->main->output.to);
-      }
-    }
-
-    f_print_dynamic_raw(f_string_eol_s, data->main->output.to);
-
-    f_file_stream_unlock(data->main->output);
-
-    // Make sure to flush standard out to help prevent standard error from causing problems.
-    f_file_stream_flush(data->main->output.to);
-
-    if (found_invalid_utf) {
-      if (data->main->error.verbosity > f_console_verbosity_quiet_e) {
-        f_file_stream_lock(data->main->error);
-
-        fl_print_format("%[Invalid UTF-8 codes were detected for file '%]", data->main->error.to, data->main->context.set.error, data->main->context.set.error);
-        fl_print_format("%[%Q%]", data->main->error.to, data->main->context.set.notable, file_name.used ? file_name : f_string_ascii_minus_s, data->main->context.set.notable);
-        fl_print_format("%['.%]%r%r", data->main->error.to, data->main->context.set.error, data->main->context.set.error, f_string_eol_s, f_string_eol_s);
-
-        f_file_stream_unlock(data->main->error);
-      }
-    }
-
-    if (ferror(file.stream)) {
-      if (data->main->error.verbosity > f_console_verbosity_quiet_e) {
-        f_file_stream_lock(data->main->error);
-
-        fl_print_format("%[%Qread() failed for '%]", data->main->error.to, data->main->context.set.error, data->main->error.prefix, data->main->context.set.error);
-        fl_print_format("%[%Q%]", data->main->error.to, data->main->context.set.notable, file_name.used ? file_name : f_string_ascii_minus_s, data->main->context.set.notable);
-        fl_print_format("%['.%]%r%r", data->main->error.to, data->main->context.set.error, data->main->context.set.error, f_string_eol_s, f_string_eol_s);
-
-        f_file_stream_unlock(data->main->error);
-      }
-
-      status = F_status_set_error(F_failure);
-    }
-
-    f_file_stream_flush(data->main->error.to);
-
-    return status;
-  }
-#endif // _di_byte_dump_file_
-
-#ifndef _di_byte_dump_print_character_fragment_
-  bool byte_dump_print_character_fragment(byte_dump_data_t * const data, const f_utf_string_static_t sequence, const f_char_t invalid[], const uint8_t width_utf, const f_char_t byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, f_char_t *offset) {
-
-    f_char_t byte = 0;
-
-    bool reset = F_false;
-
-    f_number_unsigned_t current = sequence.used - 1;
-
-    if (byte_current == 1) {
-      byte = macro_f_utf_char_t_to_char_1(sequence.string[current]);
-    }
-    else if (byte_current == 2) {
-      byte = macro_f_utf_char_t_to_char_2(sequence.string[current]);
-    }
-    else if (byte_current == 3) {
-      byte = macro_f_utf_char_t_to_char_3(sequence.string[current]);
-    }
-    else if (byte_current == 4) {
-      byte = macro_f_utf_char_t_to_char_4(sequence.string[current]);
-    }
-
-    if (!cell->column) {
-      fl_print_format("%[%016_UL%] ", data->main->output.to, data->main->context.set.notable, cell->row, data->main->context.set.notable);
-
-      if (*offset) {
-        f_char_t offset_to_print = *offset;
-
-        // Pad the buffer with spaces to hide any skipped bytes (skipped via --first).
-        while (offset_to_print && cell->column < data->width) {
-
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            f_print_terminated("         ", data->main->output.to);
-          }
-          else if (data->mode == byte_dump_mode_hexidecimal_e) {
-            f_print_terminated("   ", data->main->output.to);
-          }
-          else if (data->mode == byte_dump_mode_duodecimal_e) {
-            f_print_terminated("    ", data->main->output.to);
-          }
-          else if (data->mode == byte_dump_mode_octal_e) {
-            f_print_terminated("    ", data->main->output.to);
-          }
-          else if (data->mode == byte_dump_mode_binary_e) {
-            f_print_terminated("         ", data->main->output.to);
-          }
-          else if (data->mode == byte_dump_mode_decimal_e) {
-            f_print_terminated("    ", data->main->output.to);
-          }
-
-          --offset_to_print;
-          ++cell->column;
-
-          if (cell->column < data->width) {
-            if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-              if (!(cell->column % 4)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-            else if (data->mode == byte_dump_mode_hexidecimal_e) {
-              if (!(cell->column % 8)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-            else if (data->mode == byte_dump_mode_duodecimal_e) {
-              if (!(cell->column % 6)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-            else if (data->mode == byte_dump_mode_octal_e) {
-              if (!(cell->column % 6)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-            else if (data->mode == byte_dump_mode_binary_e) {
-              if (!(cell->column % 4)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-            else if (data->mode == byte_dump_mode_decimal_e) {
-              if (!(cell->column % 6)) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-              }
-            }
-          }
-        }
-      }
-    }
-
-    if (cell->column < data->width) {
-      if ((data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) && !invalid[current]) {
-        if (byte_current == 1) {
-          uint32_t unicode = 0;
-
-          if (width_utf < 2) {
-
-            // 1 == U+0000 -> U+007F.
-            unicode = macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x7f;
-          }
-          else if (width_utf == 2) {
-
-            // 2 == U+0080 -> U+07FF.
-            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x1f) << 6;
-            unicode |= macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f;
-          }
-          else if (width_utf == 3) {
-
-            // 3 == U+0800 -> U+FFFF.
-            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0xf) << 12;
-            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 6;
-            unicode |= macro_f_utf_char_t_to_char_3(sequence.string[current]) & 0x3f;
-          }
-          else if (width_utf == 4) {
-
-            // 4 == U+10000 -> U+10FFFF.
-            unicode = (macro_f_utf_char_t_to_char_1(sequence.string[current]) & 0x7) << 18;
-            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 12;
-            unicode |= (macro_f_utf_char_t_to_char_2(sequence.string[current]) & 0x3f) << 6;
-            unicode |= macro_f_utf_char_t_to_char_4(sequence.string[current]) & 0x3f;
-          }
-
-          if (width_utf < 4) {
-            fl_print_format(" U+%04_U  ", data->main->output.to, unicode);
-          }
-          else {
-            fl_print_format(" U+%06_U", data->main->output.to, unicode);
-          }
-        }
-        else {
-
-          // Pad the sequence that are incomplete fragments of an already printed valid Unicode.
-          f_print_terminated("         ", data->main->output.to);
-        }
-      }
-      else {
-        if (data->mode == byte_dump_mode_hexidecimal_e) {
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            f_print_terminated("      ", data->main->output.to);
-          }
-
-          if (invalid[current]) {
-            fl_print_format(" %[%02_uii%]", data->main->output.to, data->main->context.set.error, (uint8_t) byte, data->main->context.set.error);
-          }
-          else {
-            fl_print_format(" %02_uii", data->main->output.to, (uint8_t) byte);
-          }
-        }
-        else if (data->mode == byte_dump_mode_duodecimal_e) {
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            f_print_terminated("     ", data->main->output.to);
-          }
-
-          if (invalid[current]) {
-            fl_print_format(" %[%03&uii%]", data->main->output.to, data->main->context.set.error, (uint8_t) byte, data->main->context.set.error);
-          }
-          else {
-            fl_print_format(" %03&uii", data->main->output.to, (uint8_t) byte);
-          }
-        }
-        else if (data->mode == byte_dump_mode_octal_e) {
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            f_print_terminated("     ", data->main->output.to);
-          }
-
-          if (invalid[current]) {
-            fl_print_format(" %[%03@uii%]", data->main->output.to, data->main->context.set.error, (uint8_t) byte, data->main->context.set.error);
-          }
-          else {
-            fl_print_format(" %03@uii", data->main->output.to, (uint8_t) byte);
-          }
-        }
-        else if (data->mode == byte_dump_mode_binary_e) {
-          if (invalid[current]) {
-            fl_print_format(" %[%08!uii%]", data->main->output.to, data->main->context.set.error, (uint8_t) byte, data->main->context.set.error);
-          }
-          else {
-            fl_print_format(" %08!uii", data->main->output.to, (uint8_t) byte);
-          }
-        }
-        else if (data->mode == byte_dump_mode_decimal_e) {
-          if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-            f_print_terminated("     ", data->main->output.to);
-          }
-
-          if (invalid[current]) {
-            fl_print_format(" %[%3uii%]", data->main->output.to, data->main->context.set.error, (uint8_t) byte, data->main->context.set.error);
-          }
-          else {
-            fl_print_format(" %3uii", data->main->output.to, (uint8_t) byte);
-          }
-        }
-      }
-
-      ++cell->column;
-    }
-
-    if (cell->column == data->width) {
-      uint8_t bytes = 0;
-
-      if (byte_current < width_utf) {
-        bytes = width_utf - byte_current;
-      }
-
-      reset = F_true;
-
-      if (data->main->parameters.array[byte_dump_parameter_text_e].result & f_console_result_found_e) {
-        byte_dump_print_text(data, sequence, invalid, previous, offset);
-      }
-      else {
-        f_print_dynamic_raw(f_string_eol_s, data->main->output.to);
-      }
-
-      cell->column = 0;
-      ++cell->row;
-
-      if (bytes) {
-        previous->bytes = bytes;
-        previous->invalid = invalid[current];
-      }
-      else {
-        previous->bytes = 0;
-        previous->invalid = 0;
-      }
-    }
-    else {
-      if (data->main->parameters.array[byte_dump_parameter_unicode_e].result & f_console_result_found_e) {
-        if (!(cell->column % 4)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-      else if (data->mode == byte_dump_mode_hexidecimal_e) {
-        if (!(cell->column % 8)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-      else if (data->mode == byte_dump_mode_duodecimal_e) {
-        if (!(cell->column % 6)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-      else if (data->mode == byte_dump_mode_octal_e) {
-        if (!(cell->column % 6)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-      else if (data->mode == byte_dump_mode_binary_e) {
-        if (!(cell->column % 4)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-      else if (data->mode == byte_dump_mode_decimal_e) {
-        if (!(cell->column % 6)) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      }
-    }
-
-    return reset;
-  }
-#endif // _di_byte_dump_print_character_fragment_
-
-#ifndef _di_byte_dump_print_text_
-  void byte_dump_print_text(byte_dump_data_t * const data, const f_utf_string_static_t sequence, const f_char_t invalid[], byte_dump_previous_t *previous, f_char_t *offset) {
-
-    f_char_t c = 0;
-    uint8_t at = 0;
-    uint8_t width_utf = 0;
-    bool print = F_true;
-
-    f_char_t byte[5] = { 0, 0, 0, 0, 0 };
-
-    fl_print_format("  %[%r%] ", data->main->output.to, data->main->context.set.notable, byte_dump_character_wall_s, data->main->context.set.notable);
-
-    if (*offset) {
-      if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-        while (*offset && at < data->width) {
-
-          f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-
-          if (data->options & byte_dump_option_wide_d) {
-            f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-          }
-
-          --(*offset);
-          ++at;
-        } // while
-      }
-      else {
-        if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-          for (; *offset && at < data->width; --(*offset), ++at) {
-
-            fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-
-            if (data->options & byte_dump_option_wide_d) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          } // for
-        }
-        else {
-          for (; *offset && at < data->width; --(*offset), ++at) {
-
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-            if (data->options & byte_dump_option_wide_d) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          } // for
-        }
-      }
-    }
-
-    // Print placeholders for the remaining fragments of UTF-8 sequence printed on previous lines.
-    if (at < data->width) {
-      uint8_t bytes_overflow = 0;
-
-      if (previous->bytes - 1 > data->width) {
-        bytes_overflow = previous->bytes - 1 - data->width;
-      }
-
-      if (previous->bytes) {
-        if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-          for (; at < previous->bytes && at < data->width; ++at) {
-
-            if (previous->invalid) {
-              fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_placeholder_s, data->main->context.set.error);
-            }
-            else if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-              f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-            }
-            else {
-              fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-            }
-
-            if (data->options & byte_dump_option_wide_d) {
-              f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-            }
-          } // for
-        }
-        else {
-          for (; at < previous->bytes && at < data->width; ++at) {
-
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-            if (data->options & byte_dump_option_wide_d) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-          } // for
-        }
-      }
-
-      if (bytes_overflow) {
-        previous->bytes = bytes_overflow;
-      }
-      else {
-        previous->bytes = 0;
-        previous->invalid = 0;
-      }
-    }
-
-    for (uint8_t i = 0; i < sequence.used && at < data->width; ++i, ++at) {
-
-      c = macro_f_utf_char_t_to_char_1(sequence.string[i]);
-      width_utf = macro_f_utf_byte_width_is(c);
-
-      if (invalid[i]) {
-        fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_incomplete_s, data->main->context.set.error);
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-      }
-      else if (f_utf_character_is_control(sequence.string[i]) == F_true) {
-        if (data->presentation == byte_dump_presentation_normal_e) {
-          fl_print_format("%[%[", data->main->output.to, data->main->context.set.notable, data->main->context.set.warning);
-
-          if (width_utf) {
-            byte[0] = c;
-
-            if (width_utf > 1) {
-              byte[1] = macro_f_utf_char_t_to_char_2(sequence.string[i]);
-
-              if (width_utf > 2) {
-                byte[2] = macro_f_utf_char_t_to_char_3(sequence.string[i]);
-
-                if (width_utf > 3) {
-                  byte[3] = macro_f_utf_char_t_to_char_4(sequence.string[i]);
-                }
-                else {
-                  byte[3] = 0;
-                }
-              }
-              else {
-                byte[2] = 0;
-              }
-            }
-            else {
-              byte[1] = 0;
-            }
-
-            f_print_safely(byte, width_utf, data->main->output.to);
-          }
-          else {
-            f_print_character_safely(c, data->main->output.to);
-          }
-
-          fl_print_format("%]%]", data->main->output.to, data->main->context.set.warning, data->main->context.set.notable);
-
-          if (data->options & byte_dump_option_wide_d) {
-            if (f_utf_character_is_wide(sequence.string[i]) != F_true) {
-              f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-            }
-          }
-        }
-        else {
-          if (data->presentation == byte_dump_presentation_simple_e) {
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-            if (width_utf > 1) {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-              if (width_utf > 2) {
-                f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-                if (width_utf > 3) {
-                  f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-                }
-              }
-            }
-          }
-          else if (data->presentation == byte_dump_presentation_classic_e) {
-            f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-
-            if (width_utf > 1) {
-              f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-
-              if (width_utf > 2) {
-                f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-
-                if (width_utf > 3) {
-                  f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-                }
-              }
-            }
-          }
-
-          if (data->options & byte_dump_option_wide_d) {
-            f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-          }
-        }
-      }
-      else if (f_utf_character_is_whitespace(sequence.string[i], F_true) == F_true) {
-        if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-          f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-        }
-        else {
-          fl_print_format("%[%[%r%]%]", data->main->output.to, data->main->context.set.notable, data->main->context.set.warning, f_print_sequence_space_s, data->main->context.set.warning, data->main->context.set.notable);
-        }
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-      }
-      else if (f_utf_character_is_zero_width(sequence.string[i]) == F_true) {
-        if (data->presentation == byte_dump_presentation_classic_e) {
-          f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-        }
-        else if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-          fl_print_format("%[%[%r%]%]", data->main->output.to, data->main->context.set.notable, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning, data->main->context.set.notable);
-        }
-        else {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-      }
-      else if (width_utf) {
-        print = F_false;
-
-        if (width_utf == 1) {
-
-          // Print invalid placeholder for invalid UTF-8 widths.
-          if (invalid[i]) {
-            fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_incomplete_s, data->main->context.set.error);
-          }
-          else {
-            fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_incomplete_s, data->main->context.set.warning);
-          }
-        }
-        else if (width_utf == 2) {
-          print = F_true;
-        }
-        else if (width_utf == 3) {
-          if (sequence.string[i] >= 0xefbfb000 && sequence.string[i] <= 0xefbfbc00) {
-
-            // Use space to represent Specials codes.
-            // 0xefbfbd00 is excluded because it is printable (and is the "Replacement Character" code).
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-          }
-          else if (sequence.string[i] >= 0xe290a700 && sequence.string[i] <= 0xe290bf00) {
-
-            // Use space to represent Control Pictues codes that are not currently defined but are reserved.
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-          }
-          else if (sequence.string[i] >= 0xee808000 && sequence.string[i] <= 0xefa3bf00) {
-
-            // Use space to represent Private Use Area codes.
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-          }
-          else {
-            print = F_true;
-          }
-        }
-        else if (sequence.string[i] >= 0xf09c80a0 && sequence.string[i] <= 0xf09c80bd) {
-
-          // Use space to represent Variation Selectors Supplement codes.
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-        else if (sequence.string[i] >= 0xf3b08080 && sequence.string[i] <= 0xf3bfbfbf) {
-
-          // Use space to represent Supplemental Private Use Area-A codes.
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-        else if (sequence.string[i] >= 0xf4808080 && sequence.string[i] <= 0xf48fbfbf) {
-
-          // Use space to represent Supplemental Private Use Area-B codes.
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-        else {
-          print = F_true;
-        }
-
-        if (print) {
-          f_print_character(c, data->main->output.to);
-
-          if (width_utf > 1) {
-            f_print_character(macro_f_utf_char_t_to_char_2(sequence.string[i]), data->main->output.to);
-
-            if (width_utf > 2) {
-              f_print_character(macro_f_utf_char_t_to_char_3(sequence.string[i]), data->main->output.to);
-
-              if (width_utf > 3) {
-                f_print_character(macro_f_utf_char_t_to_char_4(sequence.string[i]), data->main->output.to);
-              }
-            }
-          }
-
-          if (f_utf_character_is_combining(sequence.string[i]) == F_true) {
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-          }
-
-          if (data->options & byte_dump_option_wide_d) {
-            if (width_utf == 1 || f_utf_character_is_wide(sequence.string[i]) != F_true) {
-              f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-            }
-          }
-        }
-        else {
-          if (data->options & byte_dump_option_wide_d) {
-            f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-          }
-        }
-      }
-      else {
-        f_print_character(c, data->main->output.to);
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-      }
-
-      // Print placeholders when using UTF-8 sequence to simulate the spaces bytes used for the character.
-      if (width_utf > 1 && at + 1 < data->width) {
-        if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-          if (invalid[i]) {
-            fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_placeholder_s, data->main->context.set.error);
-          }
-          else if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-            f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-          }
-          else {
-            fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-          }
-        }
-        else {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-
-        ++at;
-
-        if (width_utf > 2 && at + 1 < data->width) {
-          if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-            if (invalid[i]) {
-              fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_placeholder_s, data->main->context.set.error);
-            }
-            else if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-              f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-            }
-            else {
-              fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-            }
-          }
-          else {
-            f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-          }
-
-          if (data->options & byte_dump_option_wide_d) {
-            f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-          }
-
-          ++at;
-
-          if (width_utf > 3 && at + 1 < data->width) {
-            if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-              if (invalid[i]) {
-                fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_placeholder_s, data->main->context.set.error);
-              }
-              else if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-                f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-              }
-              else {
-                fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-              }
-            }
-            else {
-              f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-            }
-
-            if (data->options & byte_dump_option_wide_d) {
-              f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-            }
-
-            ++at;
-          }
-        }
-      }
-    } // for
-
-    // Print placeholder for the remaining parts of the line.
-    if (data->main->parameters.array[byte_dump_parameter_placeholder_e].result & f_console_result_found_e) {
-      for (; at < data->width; ++at) {
-
-        if (invalid[at]) {
-          fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.error, byte_dump_character_placeholder_s, data->main->context.set.error);
-        }
-        else if (data->main->parameters.array[byte_dump_parameter_classic_e].result & f_console_result_found_e) {
-          f_print_dynamic_raw(f_string_ascii_period_s, data->main->output.to);
-        }
-        else {
-          fl_print_format("%[%r%]", data->main->output.to, data->main->context.set.warning, byte_dump_character_placeholder_s, data->main->context.set.warning);
-        }
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_ascii_space_s, data->main->output.to);
-        }
-      } // for
-    }
-    else {
-      for (; at < data->width; ++at) {
-
-        f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-
-        if (data->options & byte_dump_option_wide_d) {
-          f_print_dynamic_raw(f_string_space_s, data->main->output.to);
-        }
-      } // for
-    }
-
-    fl_print_format(" %[%r%]%r", data->main->output.to, data->main->context.set.notable, byte_dump_character_wall_s, data->main->context.set.notable, f_string_eol_s);
-  }
-#endif // _di_byte_dump_print_text_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/level_3/byte_dump/c/private-common.h b/level_3/byte_dump/c/private-common.h
deleted file mode 100644 (file)
index ae6df89..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * FLL - Level 3
- *
- * Project: Byte Dump
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_h
-#define _PRIVATE_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The program data.
- *
- * Properties:
- *   - argv:         The argument structure in the progam data parameters for simplifying syntax.
- *   - first:        The first position.
- *   - last:         The last position.
- *   - main:         The main program data.
- *   - mode:         The digit representation mode.
- *   - options:      Additional options.
- *   - presentation: The presentation mode.
- *   - width:        The number of columns.
- */
-#ifndef _di_byte_dump_data_t_
-  typedef struct {
-    fll_program_data_t *main;
-    f_string_static_t *argv;
-
-    uint64_t first;
-    uint64_t last;
-    uint8_t width;
-    uint8_t mode;
-    uint8_t presentation;
-    uint8_t options;
-  } byte_dump_data_t;
-
-  #define byte_dump_data_t_initialize \
-    { \
-      0, \
-      0, \
-      0, \
-      0, \
-      8, \
-      byte_dump_mode_hexidecimal_e, \
-      byte_dump_presentation_normal_e, \
-      byte_dump_option_wide_d, \
-    }
-#endif // _di_byte_dump_data_t_
-
-/**
- * A main structure for character row and column position (cell).
- *
- * Properties:
- *   - column: The column position associated with the character cell.
- *   - row:    The row position associated with the character cell.
- */
-#ifndef _di_byte_dump_cell_t_
-  typedef struct {
-    uint8_t  column;
-    uint64_t row;
-  } byte_dump_cell_t;
-
-  #define byte_dump_cell_t_initialize \
-    { \
-      0, \
-      0, \
-    }
-#endif // _di_byte_dump_cell_t_
-
-/**
- * A main structure for character main that overflowed from a previous line.
- *
- * UTF-8 Characters bytes may overflow beyond the main.width.
- * These overflowed bytes should still have placeholders printed in the next text-mode print.
- *
- * Properties:
- *   - bytes: The number of previous bytes that overflowed from the previous line.
- *            This is used to print the placeholders for the "text" option.
- *   - invalid: The specific invalid value provided representing the overflowed bytes.
- *              This is used to print the placeholders.
- */
-#ifndef _di_byte_dump_previous_t_
-  typedef struct {
-    uint8_t bytes;
-    uint8_t invalid;
-  } byte_dump_previous_t;
-
-  #define byte_dump_previous_t_initialize \
-    { \
-      0, \
-      0, \
-    }
-#endif // _di_byte_previous_cell_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_h
index 3b3d53b451b531e75dbf7a7ff1d716a9273fecc3..d00a32115027dcb0e094165af52b1389607d0773 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 byte_dump.c common.c print.c private-common.c private-byte_dump.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/error.c main/print/message.c main/process.c main/signal.c main/thread.c main/byte_dump.c
 
-build_sources_program main.c
+build_sources_program main/main.c
 
-build_sources_headers byte_dump.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/error.h main/print/message.h main/process.h main/signal.h main/thread.h main/byte_dump.h
 
 build_sources_documentation man