From 3f7a2f960f8140252d51c325a9846d20dd9f1c60 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 25 Jul 2023 23:16:52 -0500 Subject: [PATCH] Update: Byte Dump program structure, following newer standards. 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. --- level_3/byte_dump/c/byte_dump.c | 473 --------- level_3/byte_dump/c/byte_dump.h | 155 --- level_3/byte_dump/c/common.c | 199 ---- level_3/byte_dump/c/common.h | 458 --------- level_3/byte_dump/c/main/byte_dump.c | 101 ++ level_3/byte_dump/c/main/byte_dump.h | 98 ++ level_3/byte_dump/c/main/common.c | 404 ++++++++ level_3/byte_dump/c/main/common.h | 48 + .../c/{private-common.c => main/common/define.c} | 3 +- level_3/byte_dump/c/main/common/define.h | 55 ++ level_3/byte_dump/c/main/common/enumeration.c | 9 + level_3/byte_dump/c/main/common/enumeration.h | 211 ++++ level_3/byte_dump/c/main/common/print.c | 23 + level_3/byte_dump/c/main/common/print.h | 58 ++ level_3/byte_dump/c/main/common/string.c | 69 ++ level_3/byte_dump/c/main/common/string.h | 217 ++++ level_3/byte_dump/c/main/common/type.c | 30 + level_3/byte_dump/c/main/common/type.h | 167 ++++ level_3/byte_dump/c/{ => main}/main.c | 45 +- level_3/byte_dump/c/{ => main}/main.h | 0 level_3/byte_dump/c/main/print/data.c | 736 ++++++++++++++ .../c/{private-byte_dump.h => main/print/data.h} | 76 +- level_3/byte_dump/c/main/print/error.c | 133 +++ level_3/byte_dump/c/main/print/error.h | 176 ++++ .../byte_dump/c/{print.c => main/print/message.c} | 51 +- level_3/byte_dump/c/main/print/message.h | 52 + level_3/byte_dump/c/main/process.c | 332 +++++++ level_3/byte_dump/c/main/process.h | 44 + level_3/byte_dump/c/main/signal.c | 111 +++ level_3/byte_dump/c/main/signal.h | 86 ++ level_3/byte_dump/c/main/thread.c | 26 + level_3/byte_dump/c/main/thread.h | 46 + level_3/byte_dump/c/print.h | 40 - level_3/byte_dump/c/private-byte_dump.c | 1035 -------------------- level_3/byte_dump/c/private-common.h | 103 -- level_3/byte_dump/data/build/settings | 6 +- 36 files changed, 3344 insertions(+), 2532 deletions(-) delete mode 100644 level_3/byte_dump/c/byte_dump.c delete mode 100644 level_3/byte_dump/c/byte_dump.h delete mode 100644 level_3/byte_dump/c/common.c delete mode 100644 level_3/byte_dump/c/common.h create mode 100644 level_3/byte_dump/c/main/byte_dump.c create mode 100644 level_3/byte_dump/c/main/byte_dump.h create mode 100644 level_3/byte_dump/c/main/common.c create mode 100644 level_3/byte_dump/c/main/common.h rename level_3/byte_dump/c/{private-common.c => main/common/define.c} (61%) create mode 100644 level_3/byte_dump/c/main/common/define.h create mode 100644 level_3/byte_dump/c/main/common/enumeration.c create mode 100644 level_3/byte_dump/c/main/common/enumeration.h create mode 100644 level_3/byte_dump/c/main/common/print.c create mode 100644 level_3/byte_dump/c/main/common/print.h create mode 100644 level_3/byte_dump/c/main/common/string.c create mode 100644 level_3/byte_dump/c/main/common/string.h create mode 100644 level_3/byte_dump/c/main/common/type.c create mode 100644 level_3/byte_dump/c/main/common/type.h rename level_3/byte_dump/c/{ => main}/main.c (51%) rename level_3/byte_dump/c/{ => main}/main.h (100%) create mode 100644 level_3/byte_dump/c/main/print/data.c rename level_3/byte_dump/c/{private-byte_dump.h => main/print/data.h} (58%) create mode 100644 level_3/byte_dump/c/main/print/error.c create mode 100644 level_3/byte_dump/c/main/print/error.h rename level_3/byte_dump/c/{print.c => main/print/message.c} (62%) create mode 100644 level_3/byte_dump/c/main/print/message.h create mode 100644 level_3/byte_dump/c/main/process.c create mode 100644 level_3/byte_dump/c/main/process.h create mode 100644 level_3/byte_dump/c/main/signal.c create mode 100644 level_3/byte_dump/c/main/signal.h create mode 100644 level_3/byte_dump/c/main/thread.c create mode 100644 level_3/byte_dump/c/main/thread.h delete mode 100644 level_3/byte_dump/c/print.h delete mode 100644 level_3/byte_dump/c/private-byte_dump.c delete mode 100644 level_3/byte_dump/c/private-common.h diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c deleted file mode 100644 index 39844da..0000000 --- a/level_3/byte_dump/c/byte_dump.c +++ /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 index e80e959..0000000 --- a/level_3/byte_dump/c/byte_dump.h +++ /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 -#include -#include -#include - -// FLL-0 includes. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// FLL-1 includes. -#include -#include - -// FLL-2 includes. -#include -#include -#include - -// Byte Dump includes. -#include -#include - -#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 index d951e0d..0000000 --- a/level_3/byte_dump/c/common.c +++ /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 index 62c272d..0000000 --- a/level_3/byte_dump/c/common.h +++ /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 index 0000000..a47adbf --- /dev/null +++ b/level_3/byte_dump/c/main/byte_dump.c @@ -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 index 0000000..8d89d8c --- /dev/null +++ b/level_3/byte_dump/c/main/byte_dump.h @@ -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 +#include +#include +#include + +// FLL-0 includes. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// FLL-1 includes. +#include +#include + +// FLL-2 includes. +#include +#include +#include + +// Byte Dump includes. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..724557a --- /dev/null +++ b/level_3/byte_dump/c/main/common.c @@ -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 index 0000000..be220c4 --- /dev/null +++ b/level_3/byte_dump/c/main/common.h @@ -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 diff --git a/level_3/byte_dump/c/private-common.c b/level_3/byte_dump/c/main/common/define.c 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 820be90..1c7bc5a 100644 --- a/level_3/byte_dump/c/private-common.c +++ b/level_3/byte_dump/c/main/common/define.c @@ -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 index 0000000..374c7db --- /dev/null +++ b/level_3/byte_dump/c/main/common/define.h @@ -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 index 0000000..1c7bc5a --- /dev/null +++ b/level_3/byte_dump/c/main/common/enumeration.c @@ -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 index 0000000..817acfb --- /dev/null +++ b/level_3/byte_dump/c/main/common/enumeration.h @@ -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 index 0000000..d751877 --- /dev/null +++ b/level_3/byte_dump/c/main/common/print.c @@ -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 index 0000000..71ec9f9 --- /dev/null +++ b/level_3/byte_dump/c/main/common/print.h @@ -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 index 0000000..ab6232a --- /dev/null +++ b/level_3/byte_dump/c/main/common/string.c @@ -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 index 0000000..8029813 --- /dev/null +++ b/level_3/byte_dump/c/main/common/string.h @@ -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 index 0000000..1503042 --- /dev/null +++ b/level_3/byte_dump/c/main/common/type.c @@ -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 index 0000000..c8a07ff --- /dev/null +++ b/level_3/byte_dump/c/main/common/type.h @@ -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 diff --git a/level_3/byte_dump/c/main.c b/level_3/byte_dump/c/main/main.c similarity index 51% rename from level_3/byte_dump/c/main.c rename to level_3/byte_dump/c/main/main.c index 7d3c569..d82f9ff 100644 --- a/level_3/byte_dump/c/main.c +++ b/level_3/byte_dump/c/main/main.c @@ -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.h b/level_3/byte_dump/c/main/main.h similarity index 100% rename from level_3/byte_dump/c/main.h rename to level_3/byte_dump/c/main/main.h 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 index 0000000..c4f6381 --- /dev/null +++ b/level_3/byte_dump/c/main/print/data.c @@ -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 diff --git a/level_3/byte_dump/c/private-byte_dump.h b/level_3/byte_dump/c/main/print/data.h 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 2b9ffa6..c31a687 100644 --- a/level_3/byte_dump/c/private-byte_dump.h +++ b/level_3/byte_dump/c/main/print/data.h @@ -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 index 0000000..fb0ebba --- /dev/null +++ b/level_3/byte_dump/c/main/print/error.c @@ -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 index 0000000..0f544e7 --- /dev/null +++ b/level_3/byte_dump/c/main/print/error.h @@ -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 diff --git a/level_3/byte_dump/c/print.c b/level_3/byte_dump/c/main/print/message.c similarity index 62% rename from level_3/byte_dump/c/print.c rename to level_3/byte_dump/c/main/print/message.c index 0a3467d..5e44bce 100644 --- a/level_3/byte_dump/c/print.c +++ b/level_3/byte_dump/c/main/print/message.c @@ -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 index 0000000..59f9ee0 --- /dev/null +++ b/level_3/byte_dump/c/main/print/message.h @@ -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 index 0000000..b937e2e --- /dev/null +++ b/level_3/byte_dump/c/main/process.c @@ -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 index 0000000..451c6d4 --- /dev/null +++ b/level_3/byte_dump/c/main/process.h @@ -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 index 0000000..20c3667 --- /dev/null +++ b/level_3/byte_dump/c/main/signal.c @@ -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 index 0000000..4a7f789 --- /dev/null +++ b/level_3/byte_dump/c/main/signal.h @@ -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 index 0000000..f68baf8 --- /dev/null +++ b/level_3/byte_dump/c/main/thread.c @@ -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 index 0000000..7d2fbb5 --- /dev/null +++ b/level_3/byte_dump/c/main/thread.h @@ -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 index 9fc38d1..0000000 --- a/level_3/byte_dump/c/print.h +++ /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 index a8f769b..0000000 --- a/level_3/byte_dump/c/private-byte_dump.c +++ /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 index ae6df89..0000000 --- a/level_3/byte_dump/c/private-common.h +++ /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 diff --git a/level_3/byte_dump/data/build/settings b/level_3/byte_dump/data/build/settings index 3b3d53b..d00a321 100644 --- a/level_3/byte_dump/data/build/settings +++ b/level_3/byte_dump/data/build/settings @@ -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 -- 1.8.3.1