From 89d3bc13340e604b59f542c94996e5150bfbf64a Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 11 Nov 2021 23:04:37 -0600 Subject: [PATCH] Update: Signal related updates, consistency improvements, and miscellaneous code cleanups. Add support for setting the timeout via f_signal_read(). I am using both F_signal and F_interrupt. The F_signal is more general and in this since is more accurate. However, F_interrupt is more accurate to the intent in the design. When an interrupt is received exit. All signals being treated as an interrupt will need to exit, so just pass F_interrupt. Provide a consistent reporting of handling the signals. Setup all programs to catch and handle signals, allowing for a clean exit. There are so many changes in this regard, I went for a quick approach. In every loop that at glance look like it would be a good point to check for signal, the code now checks for signal. There is likely a need for performance consideration in this. There is likely a need for invetigating this further to make sure it is still responsive (as in, investigate to see if I need to add additional signal checks). Programs like fake and controller already handle the signal. These programs are update to be consistent with this newer design. The "main" structure used in the programs is sometimes a constant variable and other times a pointer. While there are performance and security reasons, I am finding that consistency is better at this point in time. Pass all of the "main" structures as either a constant pointe or a pointer. At some point in the future, I can see myself reviewing these and making performance improvements that might result in reverting some of this. Having be more consistent will make the code a bit more mangeable during this highly active development and design period. Miscellaneous syntax cleanups of any code that I happened to notice needs cleaning and can be easily cleaned on the spot. When interrupting, flush the output and print a new line. This is effective in properly cleaning the console (to some reasonable extent), which can be messy when exiting due to an interrupt. I did not get a change to utilize the signal handling function callbacks in the FSS processing functions. I will need to follow up this commit with such a change. I need to see if the IKI processing functions also can do this and need to do this as well. I haven't had a chance to really look at each of the programs after this change. I will need to spend time making suring there are no regressions. --- level_0/f_signal/c/signal.c | 4 +- level_0/f_signal/c/signal.h | 7 +- level_1/fl_print/c/private-print.c | 4 +- level_1/fl_signal/c/signal.c | 4 +- level_3/byte_dump/c/byte_dump.c | 62 +- level_3/byte_dump/c/byte_dump.h | 25 +- level_3/byte_dump/c/main.c | 31 +- level_3/byte_dump/c/private-byte_dump.c | 496 ++++++----- level_3/byte_dump/c/private-byte_dump.h | 14 +- level_3/byte_dump/c/private-common.c | 47 + level_3/byte_dump/c/private-common.h | 30 + level_3/byte_dump/data/build/dependencies | 1 + level_3/control/c/control.c | 21 +- level_3/control/c/control.h | 24 +- level_3/control/c/main.c | 31 +- level_3/control/c/private-common.c | 47 + level_3/control/c/private-common.h | 30 + level_3/control/data/build/dependencies | 1 + level_3/controller/c/controller.c | 94 +- level_3/controller/c/controller.h | 38 +- level_3/controller/c/main.c | 53 +- level_3/controller/c/private-common.c | 2 +- level_3/controller/c/private-common.h | 2 +- level_3/controller/c/private-controller.h | 2 +- level_3/controller/c/private-controller_print.c | 18 + level_3/controller/c/private-controller_print.h | 12 + level_3/controller/c/private-entry.c | 38 +- level_3/controller/c/private-lock.c | 4 +- level_3/controller/c/private-lock.h | 6 +- level_3/controller/c/private-lock_print.c | 2 +- level_3/controller/c/private-lock_print.h | 2 +- level_3/controller/c/private-process.c | 76 +- level_3/controller/c/private-process.h | 3 +- level_3/controller/c/private-rule.c | 222 ++--- level_3/controller/c/private-rule.h | 29 +- level_3/controller/c/private-thread.c | 14 +- level_3/controller/c/private-thread.h | 4 +- level_3/controller/c/private-thread_entry.c | 23 +- level_3/fake/c/fake.c | 39 +- level_3/fake/c/fake.h | 20 +- level_3/fake/c/main.c | 37 +- level_3/fake/c/private-build.c | 987 ++++++++++----------- level_3/fake/c/private-build.h | 74 +- level_3/fake/c/private-clean.c | 36 +- level_3/fake/c/private-clean.h | 6 +- level_3/fake/c/private-common.c | 30 + level_3/fake/c/private-common.h | 18 + level_3/fake/c/private-fake.c | 149 ++-- level_3/fake/c/private-fake.h | 46 +- level_3/fake/c/private-make.c | 560 ++++++------ level_3/fake/c/private-make.h | 90 +- level_3/fake/c/private-print.c | 508 ++++++----- level_3/fake/c/private-print.h | 64 +- level_3/fake/c/private-skeleton.c | 186 ++-- level_3/fake/c/private-skeleton.h | 14 +- level_3/firewall/c/firewall.c | 85 +- level_3/firewall/c/firewall.h | 24 +- level_3/firewall/c/main.c | 38 +- level_3/firewall/c/private-common.c | 47 + level_3/firewall/c/private-common.h | 30 + level_3/firewall/c/private-firewall.c | 282 +++--- level_3/firewall/c/private-firewall.h | 40 +- level_3/firewall/data/build/dependencies | 1 + .../fss_basic_list_read/c/fss_basic_list_read.c | 28 +- .../fss_basic_list_read/c/fss_basic_list_read.h | 20 +- level_3/fss_basic_list_read/c/main.c | 31 +- level_3/fss_basic_list_read/c/private-common.c | 47 + level_3/fss_basic_list_read/c/private-common.h | 30 + .../c/private-fss_basic_list_read.c | 58 +- .../c/private-fss_basic_list_read.h | 58 +- .../fss_basic_list_read/data/build/dependencies | 1 + .../fss_basic_list_write/c/fss_basic_list_write.c | 59 +- .../fss_basic_list_write/c/fss_basic_list_write.h | 23 +- level_3/fss_basic_list_write/c/main.c | 31 +- level_3/fss_basic_list_write/c/private-common.c | 47 + level_3/fss_basic_list_write/c/private-common.h | 30 + .../c/private-fss_basic_list_write.c | 81 +- .../c/private-fss_basic_list_write.h | 20 +- .../fss_basic_list_write/data/build/dependencies | 1 + level_3/fss_basic_read/c/fss_basic_read.c | 26 +- level_3/fss_basic_read/c/fss_basic_read.h | 22 +- level_3/fss_basic_read/c/main.c | 31 +- level_3/fss_basic_read/c/private-common.c | 47 + level_3/fss_basic_read/c/private-common.h | 30 + level_3/fss_basic_read/c/private-fss_basic_read.c | 48 +- level_3/fss_basic_read/c/private-fss_basic_read.h | 48 +- level_3/fss_basic_read/data/build/dependencies | 1 + level_3/fss_basic_write/c/fss_basic_write.c | 59 +- level_3/fss_basic_write/c/fss_basic_write.h | 22 +- level_3/fss_basic_write/c/main.c | 31 +- level_3/fss_basic_write/c/private-common.c | 47 + level_3/fss_basic_write/c/private-common.h | 30 + .../fss_basic_write/c/private-fss_basic_write.c | 78 +- .../fss_basic_write/c/private-fss_basic_write.h | 38 +- level_3/fss_basic_write/data/build/dependencies | 1 + .../c/fss_embedded_list_read.c | 53 +- .../c/fss_embedded_list_read.h | 22 +- level_3/fss_embedded_list_read/c/main.c | 31 +- level_3/fss_embedded_list_read/c/private-common.c | 47 + level_3/fss_embedded_list_read/c/private-common.h | 30 + .../c/private-fss_embedded_list_read.c | 211 ++--- .../c/private-fss_embedded_list_read.h | 46 +- .../fss_embedded_list_read/data/build/dependencies | 1 + .../c/fss_embedded_list_write.c | 64 +- .../c/fss_embedded_list_write.h | 23 +- level_3/fss_embedded_list_write/c/main.c | 31 +- level_3/fss_embedded_list_write/c/private-common.c | 47 + level_3/fss_embedded_list_write/c/private-common.h | 30 + .../c/private-fss_embedded_list_write.c | 120 +-- .../c/private-fss_embedded_list_write.h | 26 +- .../data/build/dependencies | 1 + .../c/fss_extended_list_read.c | 24 +- .../c/fss_extended_list_read.h | 20 +- level_3/fss_extended_list_read/c/main.c | 31 +- level_3/fss_extended_list_read/c/private-common.c | 47 + level_3/fss_extended_list_read/c/private-common.h | 30 + .../c/private-fss_extended_list_read.c | 34 +- .../c/private-fss_extended_list_read.h | 54 +- .../fss_extended_list_read/data/build/dependencies | 1 + .../c/fss_extended_list_write.c | 61 +- .../c/fss_extended_list_write.h | 20 +- level_3/fss_extended_list_write/c/main.c | 31 +- level_3/fss_extended_list_write/c/private-common.c | 47 + level_3/fss_extended_list_write/c/private-common.h | 30 + .../c/private-fss_extended_list_write.c | 117 +-- .../c/private-fss_extended_list_write.h | 26 +- .../data/build/dependencies | 1 + level_3/fss_extended_read/c/fss_extended_read.c | 29 +- level_3/fss_extended_read/c/fss_extended_read.h | 20 +- level_3/fss_extended_read/c/main.c | 31 +- level_3/fss_extended_read/c/private-common.c | 47 + level_3/fss_extended_read/c/private-common.h | 30 + .../c/private-fss_extended_read.c | 39 +- .../c/private-fss_extended_read.h | 76 +- level_3/fss_extended_read/data/build/dependencies | 1 + level_3/fss_extended_write/c/fss_extended_write.c | 62 +- level_3/fss_extended_write/c/fss_extended_write.h | 23 +- level_3/fss_extended_write/c/main.c | 31 +- level_3/fss_extended_write/c/private-common.c | 47 + level_3/fss_extended_write/c/private-common.h | 30 + .../c/private-fss_extended_write.c | 76 +- .../c/private-fss_extended_write.h | 30 +- level_3/fss_extended_write/data/build/dependencies | 1 + level_3/fss_identify/c/fss_identify.c | 46 +- level_3/fss_identify/c/fss_identify.h | 22 +- level_3/fss_identify/c/main.c | 31 +- level_3/fss_identify/c/private-common.c | 47 + level_3/fss_identify/c/private-common.h | 30 + level_3/fss_identify/c/private-fss_identify.c | 41 +- level_3/fss_identify/c/private-fss_identify.h | 12 +- level_3/fss_identify/data/build/dependencies | 1 + level_3/fss_status_code/c/fss_status_code.c | 38 +- level_3/fss_status_code/c/fss_status_code.h | 22 +- level_3/fss_status_code/c/main.c | 31 +- level_3/fss_status_code/c/private-common.c | 47 + level_3/fss_status_code/c/private-common.h | 30 + .../fss_status_code/c/private-fss_status_code.c | 56 +- .../fss_status_code/c/private-fss_status_code.h | 16 +- level_3/fss_status_code/data/build/dependencies | 1 + level_3/iki_read/c/iki_read.c | 49 +- level_3/iki_read/c/iki_read.h | 22 +- level_3/iki_read/c/main.c | 31 +- level_3/iki_read/c/private-common.c | 47 + level_3/iki_read/c/private-common.h | 30 + level_3/iki_read/c/private-iki_read.c | 92 +- level_3/iki_read/c/private-iki_read.h | 42 +- level_3/iki_read/data/build/dependencies | 1 + level_3/iki_write/c/iki_write.c | 40 +- level_3/iki_write/c/iki_write.h | 22 +- level_3/iki_write/c/main.c | 31 +- level_3/iki_write/c/private-common.c | 47 + level_3/iki_write/c/private-common.h | 30 + level_3/iki_write/c/private-iki_write.c | 32 +- level_3/iki_write/c/private-iki_write.h | 4 +- level_3/iki_write/data/build/dependencies | 1 + level_3/status_code/c/main.c | 31 +- level_3/status_code/c/private-common.c | 47 + level_3/status_code/c/private-common.h | 30 + level_3/status_code/c/private-status_code.c | 56 +- level_3/status_code/c/private-status_code.h | 16 +- level_3/status_code/c/status_code.c | 44 +- level_3/status_code/c/status_code.h | 22 +- level_3/status_code/data/build/dependencies | 1 + 183 files changed, 5991 insertions(+), 3236 deletions(-) diff --git a/level_0/f_signal/c/signal.c b/level_0/f_signal/c/signal.c index d046c87..0bdeb85 100644 --- a/level_0/f_signal/c/signal.c +++ b/level_0/f_signal/c/signal.c @@ -53,7 +53,7 @@ extern "C" { #endif // _di_f_signal_open_ #ifndef _di_f_signal_read_ - f_status_t f_signal_read(const f_signal_t signal, struct signalfd_siginfo *information) { + f_status_t f_signal_read(const f_signal_t signal, const int timeout, struct signalfd_siginfo *information) { if (!signal.id) { return F_data_not; @@ -67,7 +67,7 @@ extern "C" { struct pollfd polls[] = { data_poll }; - const int result = poll(polls, 1, 0); + const int result = poll(polls, 1, timeout); if (result < 0) { if (errno == EFAULT) return F_status_set_error(F_buffer); diff --git a/level_0/f_signal/c/signal.h b/level_0/f_signal/c/signal.h index 98003cf..cb0c198 100644 --- a/level_0/f_signal/c/signal.h +++ b/level_0/f_signal/c/signal.h @@ -75,10 +75,13 @@ extern "C" { #endif // _di_f_signal_open_ /** - * Read a current process signal, if one exists, in a non-blocking manner. + * Read a current process signal, if one exists. * * @param signal * The signal settings. + * @param timeout + * Block for the number of milliseconds, waiting for a signal. + * A value of 0 means that this will not block. * @param information * The signal data to be populated if a signal is found during read. * @@ -101,7 +104,7 @@ extern "C" { * @see read() */ #ifndef _di_f_signal_read_ - extern f_status_t f_signal_read(const f_signal_t signal, struct signalfd_siginfo *information); + extern f_status_t f_signal_read(const f_signal_t signal, const int timeout, struct signalfd_siginfo *information); #endif // _di_f_signal_read_ /** diff --git a/level_1/fl_print/c/private-print.c b/level_1/fl_print/c/private-print.c index dc53539..d8dbd3b 100644 --- a/level_1/fl_print/c/private-print.c +++ b/level_1/fl_print/c/private-print.c @@ -1367,7 +1367,7 @@ extern "C" { status = f_utf_is_whitespace(string + i, (length - i) + 1); - // determine if this is an end of string whitespace that needs to be trimmed. + // Determine if this is an end of string whitespace that needs to be trimmed. if (status == F_true || !string[i]) { j = i + macro_f_utf_byte_width(string[i]); status = F_none; @@ -1407,7 +1407,7 @@ extern "C" { if (j == length || status == F_true || !string[i]) break; - // print all processed whitespace (note: control characters are not whitespace so no checks for this are needed). + // Print all processed whitespace (note: control characters are not whitespace so no checks for this are needed). while (i < j) { while (at < except_at.used && except_at.array[at] < i) { diff --git a/level_1/fl_signal/c/signal.c b/level_1/fl_signal/c/signal.c index e831647..f0a81a6 100644 --- a/level_1/fl_signal/c/signal.c +++ b/level_1/fl_signal/c/signal.c @@ -30,9 +30,9 @@ extern "C" { memset(&information, 0, sizeof(struct signalfd_siginfo)); - const f_status_t status = f_signal_read(signal_interrupt->signal, &information); + const f_status_t status = f_signal_read(signal_interrupt->signal, 0, &information); - if (status == F_signal) { + if (F_status_set_fine(status) == F_interrupt) { for (f_array_length_t i = 0; i < signal_interrupt->interrupts.used; ++i) { if (information.ssi_signo == signal_interrupt->interrupts.array[i]) { diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c index 57bca1d..95985e1 100644 --- a/level_3/byte_dump/c/byte_dump.c +++ b/level_3/byte_dump/c/byte_dump.c @@ -71,7 +71,7 @@ extern "C" { #endif // _di_byte_dump_print_help_ #ifndef _di_byte_dump_main_ - f_status_t byte_dump_main(const f_console_arguments_t arguments, byte_dump_main_t *main) { + f_status_t byte_dump_main(byte_dump_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -83,7 +83,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { byte_dump_parameter_no_color, byte_dump_parameter_light, byte_dump_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -109,6 +109,7 @@ extern "C" { fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process", F_true); byte_dump_main_delete(main); + return F_status_set_error(status); } } @@ -125,6 +126,7 @@ extern "C" { fll_error_print(main->error, F_status_set_fine(status), "f_console_parameter_prioritize_right", F_true); byte_dump_main_delete(main); + return status; } @@ -215,6 +217,7 @@ extern "C" { byte_dump_print_help(main->output.to, main->context); byte_dump_main_delete(main); + return F_none; } @@ -222,6 +225,7 @@ extern "C" { fll_program_print_version(main->output.to, byte_dump_version_s); byte_dump_main_delete(main); + return F_none; } @@ -240,11 +244,11 @@ extern "C" { } else if (main->parameters[byte_dump_parameter_width].result == f_console_result_additional) { const f_array_length_t index = main->parameters[byte_dump_parameter_width].values.array[main->parameters[byte_dump_parameter_width].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); f_number_unsigned_t number = 0; - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status) || number < 1 || number >= 0xfb) { flockfile(main->error.to.stream); @@ -276,15 +280,16 @@ extern "C" { funlockfile(main->error.to.stream); byte_dump_main_delete(main); + return F_status_set_error(status); } else if (main->parameters[byte_dump_parameter_first].result == f_console_result_additional) { const f_array_length_t index = main->parameters[byte_dump_parameter_first].values.array[main->parameters[byte_dump_parameter_first].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); f_number_unsigned_t number = 0; - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status) || number > F_number_t_size_unsigned_d) { flockfile(main->error.to.stream); @@ -300,6 +305,7 @@ extern "C" { funlockfile(main->error.to.stream); byte_dump_main_delete(main); + return F_status_set_error(status); } @@ -316,15 +322,16 @@ extern "C" { funlockfile(main->error.to.stream); byte_dump_main_delete(main); + return F_status_set_error(status); } else if (main->parameters[byte_dump_parameter_last].result == f_console_result_additional) { const f_array_length_t index = main->parameters[byte_dump_parameter_last].values.array[main->parameters[byte_dump_parameter_last].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); f_number_unsigned_t number = 0; - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status) || number < 0 || number > F_number_t_size_unsigned_d) { flockfile(main->error.to.stream); @@ -340,6 +347,7 @@ extern "C" { funlockfile(main->error.to.stream); byte_dump_main_delete(main); + return F_status_set_error(status); } @@ -359,6 +367,7 @@ extern "C" { funlockfile(main->error.to.stream); byte_dump_main_delete(main); + return F_status_set_error(status); } @@ -397,7 +406,7 @@ extern "C" { funlockfile(main->output.to.stream); - status = byte_dump_file(*main, 0, file); + status = byte_dump_file(main, 0, file); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "byte_dump_file", F_true); @@ -414,7 +423,7 @@ extern "C" { for (f_array_length_t counter = 0; counter < main->remaining.used; ++counter) { - status = f_file_exists(arguments.argv[main->remaining.array[counter]]); + status = f_file_exists(arguments->argv[main->remaining.array[counter]]); if (status == F_false) { status = F_status_set_error(F_file_found_not); @@ -425,7 +434,7 @@ extern "C" { missing_files = status; } - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, arguments.argv[main->remaining.array[counter]], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, arguments->argv[main->remaining.array[counter]], "open", fll_error_file_type_file); } } // for @@ -433,6 +442,7 @@ extern "C" { status = F_status_set_error(missing_files); byte_dump_main_delete(main); + return status; } } @@ -441,12 +451,13 @@ extern "C" { for (f_array_length_t counter = 0; counter < main->remaining.used; ++counter) { - status = f_file_stream_open(arguments.argv[main->remaining.array[counter]], 0, &file); + status = f_file_stream_open(arguments->argv[main->remaining.array[counter]], 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[main->remaining.array[counter]], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments->argv[main->remaining.array[counter]], "open", fll_error_file_type_file); byte_dump_main_delete(main); + return status; } @@ -454,8 +465,7 @@ extern "C" { f_print_terminated(f_string_eol_s, main->output.to.stream); fl_print_format("%[Byte Dump of: %]%[", main->output.to.stream, main->context.set.title, main->context.set.title, main->context.set.notable); - fll_print_safely_terminated(arguments.argv[main->remaining.array[counter]], main->output.to.stream); - fl_print_format("%] %[(in ", main->output.to.stream, main->context.set.notable, main->context.set.title); + fl_print_format("%S%] %[(in ", main->output.to.stream, arguments->argv[main->remaining.array[counter]], main->context.set.notable, main->context.set.title); if (main->mode == byte_dump_mode_hexidecimal) { f_print_terminated("Hexidecimal", main->output.to.stream); @@ -477,14 +487,28 @@ extern "C" { funlockfile(main->output.to.stream); - status = byte_dump_file(*main, arguments.argv[main->remaining.array[counter]], file); + status = byte_dump_file(main, arguments->argv[main->remaining.array[counter]], file); f_file_stream_close(F_true, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "byte_dump_file", F_true, arguments.argv[main->remaining.array[counter]], "process", fll_error_file_type_file); + 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) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + else { + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_error_file_print(main->error, F_status_set_fine(status), "byte_dump_file", F_true, arguments->argv[main->remaining.array[counter]], "process", fll_error_file_type_file); + } + } byte_dump_main_delete(main); + return status; } } // for @@ -499,12 +523,13 @@ extern "C" { } byte_dump_main_delete(main); + return status; } #endif // _di_byte_dump_main_ #ifndef _di_byte_dump_main_delete_ - f_status_t byte_dump_main_delete(byte_dump_main_t *main) { + f_status_t byte_dump_main_delete(byte_dump_main_t * const main) { for (f_array_length_t i = 0; i < byte_dump_total_parameters_d; ++i) { @@ -516,6 +541,7 @@ extern "C" { macro_f_array_lengths_t_delete_simple(main->remaining); macro_f_color_context_t_delete_simple(main->context); + macro_f_color_context_t_clear(main->context) return F_none; } diff --git a/level_3/byte_dump/c/byte_dump.h b/level_3/byte_dump/c/byte_dump.h index 5c2f738..3df9f94 100644 --- a/level_3/byte_dump/c/byte_dump.h +++ b/level_3/byte_dump/c/byte_dump.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -235,6 +236,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + uint64_t first; uint64_t last; uint8_t width; @@ -252,6 +255,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ 0, \ 0, \ 8, \ @@ -281,19 +285,30 @@ extern "C" { * * Be sure to call byte_dump_main_delete() after executing this. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. + * + * 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. + * * Status codes (with error bit) are returned on any problem. * * @see byte_dump_main_delete() */ #ifndef _di_byte_dump_main_ - extern f_status_t byte_dump_main(const f_console_arguments_t arguments, byte_dump_main_t *main); + extern f_status_t byte_dump_main(byte_dump_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_byte_dump_main_ /** @@ -302,7 +317,7 @@ extern "C" { * Be sure to call this after executing byte_dump_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -312,7 +327,7 @@ extern "C" { * @see byte_dump_main() */ #ifndef _di_byte_dump_main_delete_ - extern f_status_t byte_dump_main_delete(byte_dump_main_t *main); + extern f_status_t byte_dump_main_delete(byte_dump_main_t * const main); #endif // _di_byte_dump_main_delete_ #ifdef __cplusplus diff --git a/level_3/byte_dump/c/main.c b/level_3/byte_dump/c/main.c index 2e16cbd..9389a89 100644 --- a/level_3/byte_dump/c/main.c +++ b/level_3/byte_dump/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = byte_dump_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = byte_dump_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index f0399c3..0291150 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_byte_dump_file_ - f_status_t byte_dump_file(const byte_dump_main_t main, const f_string_t file_name, const f_file_t file) { + f_status_t byte_dump_file(byte_dump_main_t * const main, const f_string_t file_name, const f_file_t file) { f_status_t status = F_none; @@ -28,37 +28,41 @@ extern "C" { // Store the current character main until it can be printed. f_utf_string_dynamic_t characters = f_utf_string_dynamic_t_initialize; - f_utf_character_t character_array[main.width]; + f_utf_character_t character_array[main->width]; f_array_length_t character_current = 0; // The row starts based on the first byte starting point and how many columns of bytes are displayed per row. - if (main.first) { - cell.row = main.first / main.width; - offset = main.first % main.width; + if (main->first) { + cell.row = main->first / main->width; + offset = main->first % main->width; // fseek() cannot be used on a PIPE, so read instead of seek. if (file_name) { - byte_get = fseek(file.stream, main.first, SEEK_SET); + byte_get = fseek(file.stream, main->first, SEEK_SET); } else { - char skip[main.first]; + char skip[main->first]; - byte_get = fread(skip, sizeof(char), main.first, file.stream); + byte_get = fread(skip, sizeof(char), main->first, file.stream); } } - memset(&character_array, 0, sizeof(f_utf_character_t) * main.width); + memset(&character_array, 0, sizeof(f_utf_character_t) * main->width); characters.string = character_array; characters.used = 0; - characters.size = main.width; + characters.size = main->width; // Record when a character is invalid. - char invalid[main.width]; - memset(&invalid, 0, sizeof(char) * main.width); + char invalid[main->width]; + memset(&invalid, 0, sizeof(char) * main->width); if (byte_get >= 0) { for (;;) { + if (byte_dump_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + byte_get = getc(file.stream); if (byte_get < 0) break; @@ -74,7 +78,7 @@ extern "C" { if (character_reset) { characters.used = 0; character_reset = F_false; - memset(&invalid, 0, sizeof(uint8_t) * main.width); + memset(&invalid, 0, sizeof(uint8_t) * main->width); } character_current = characters.used++; @@ -132,7 +136,7 @@ extern "C" { } } - flockfile(main.output.to.stream); + flockfile(main->output.to.stream); if (byte_dump_print_character_fragment(main, characters, invalid, width_utf, 1, &previous, &cell, &offset) == F_true) { character_reset = F_true; @@ -155,142 +159,142 @@ extern "C" { } } - if (main.last) { + if (main->last) { position += width_utf; - if (position >= main.last) { - funlockfile(main.output.to.stream); + if (position >= main->last) { + funlockfile(main->output.to.stream); break; } } } - else if (main.last) { + else if (main->last) { ++position; - if (position >= main.last) { - funlockfile(main.output.to.stream); + if (position >= main->last) { + funlockfile(main->output.to.stream); break; } } - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); width_utf = -1; } // for } - flockfile(main.output.to.stream); + flockfile(main->output.to.stream); // Print placeholders to fill out the remaining line and then optionally print the text block. - if (cell.column && cell.column < main.width) { + if (cell.column && cell.column < main->width) { previous.bytes = 0; previous.invalid = 0; - while (cell.column < main.width) { + while (cell.column < main->width) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_hexidecimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_hexidecimal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_duodecimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_duodecimal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_octal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_octal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_binary) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_binary) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_decimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_decimal) { + f_print_terminated(" ", main->output.to.stream); } ++cell.column; - if (cell.column < main.width) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + if (cell.column < main->width) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell.column % 4)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_hexidecimal) { + else if (main->mode == byte_dump_mode_hexidecimal) { if (!(cell.column % 8)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_duodecimal) { + else if (main->mode == byte_dump_mode_duodecimal) { if (!(cell.column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_octal) { + else if (main->mode == byte_dump_mode_octal) { if (!(cell.column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_binary) { + else if (main->mode == byte_dump_mode_binary) { if (!(cell.column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_decimal) { + else if (main->mode == byte_dump_mode_decimal) { if (!(cell.column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } } } // while - if (main.parameters[byte_dump_parameter_text].result == f_console_result_found) { + if (main->parameters[byte_dump_parameter_text].result == f_console_result_found) { byte_dump_print_text(main, characters, invalid, &previous, &offset); } else { - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); // make sure to flush standard out to help prevent standard error from causing poblems. - fflush(main.output.to.stream); + fflush(main->output.to.stream); if (found_invalid_utf) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_color_terminated("Invalid UTF-8 codes were detected for file '", main.context.set.error, main.error.to.stream); - fl_print_format("%[%S%]", main.error.to.stream, main.context.set.notable, file_name ? file_name : "-", main.context.set.notable); - fl_print_format("%['.%]%c%c", main.error.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0], f_string_eol_s[0]); + fl_print_color_terminated("Invalid UTF-8 codes were detected for file '", main->context.set.error, main->error.to.stream); + fl_print_format("%[%S%]", main->error.to.stream, main->context.set.notable, file_name ? file_name : "-", main->context.set.notable); + fl_print_format("%['.%]%c%c", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0], f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } if (ferror(file.stream)) { // @todo determine what the error is and display it. - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%[%Sread() failed for '%]", main.error.to.stream, main.context.set.error, main.error.prefix, main.context.set.error); - fl_print_format("%[%S%]", main.error.to.stream, main.context.set.notable, file_name ? file_name : "-", main.context.set.notable); - fl_print_format("%['.%]%c%c", main.error.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0], f_string_eol_s[0]); + fl_print_format("%[%Sread() failed for '%]", main->error.to.stream, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%S%]", main->error.to.stream, main->context.set.notable, file_name ? file_name : "-", main->context.set.notable); + fl_print_format("%['.%]%c%c", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0], f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); status = F_status_set_error(F_failure); } - fflush(main.error.to.stream); + fflush(main->error.to.stream); return status; } #endif // _di_byte_dump_file_ #ifndef _di_byte_dump_print_character_fragment_ - bool byte_dump_print_character_fragment(const byte_dump_main_t main, const f_utf_string_static_t characters, const char invalid[], const uint8_t width_utf, const char byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, uint8_t *offset) { + bool byte_dump_print_character_fragment(byte_dump_main_t * const main, const f_utf_string_static_t characters, const char invalid[], const uint8_t width_utf, const char byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, uint8_t *offset) { char byte = 0; @@ -312,65 +316,65 @@ extern "C" { } if (!cell->column) { - fl_print_format("%[%016_UL%] ", main.output.to.stream, main.context.set.notable, cell->row, main.context.set.notable); + fl_print_format("%[%016_UL%] ", main->output.to.stream, main->context.set.notable, cell->row, main->context.set.notable); if (*offset) { uint8_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.width) { + while (offset_to_print && cell->column < main->width) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_hexidecimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_hexidecimal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_duodecimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_duodecimal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_octal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_octal) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_binary) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_binary) { + f_print_terminated(" ", main->output.to.stream); } - else if (main.mode == byte_dump_mode_decimal) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_decimal) { + f_print_terminated(" ", main->output.to.stream); } --offset_to_print; ++cell->column; - if (cell->column < main.width) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + if (cell->column < main->width) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell->column % 4)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_hexidecimal) { + else if (main->mode == byte_dump_mode_hexidecimal) { if (!(cell->column % 8)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_duodecimal) { + else if (main->mode == byte_dump_mode_duodecimal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_octal) { + else if (main->mode == byte_dump_mode_octal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_binary) { + else if (main->mode == byte_dump_mode_binary) { if (!(cell->column % 4)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_decimal) { + else if (main->mode == byte_dump_mode_decimal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } } @@ -378,9 +382,9 @@ extern "C" { } } - if (cell->column < main.width) { + if (cell->column < main->width) { // @fixme when unicode is enabled but invalid, the mode and its respective length now matters. This needs to be included in the width calculations. - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found && !invalid[character_current]) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found && !invalid[character_current]) { if (byte_current == 1) { uint32_t unicode = 0; @@ -412,73 +416,73 @@ extern "C" { } if (width_utf < 4) { - fl_print_format(" U+%04_U ", main.output.to.stream, unicode); + fl_print_format(" U+%04_U ", main->output.to.stream, unicode); } else { - fl_print_format(" U+%06_U ", main.output.to.stream, unicode); + fl_print_format(" U+%06_U ", main->output.to.stream, unicode); } } else { // Pad the characters that are incomplete fragments of an already printed valid Unicode. - f_print_terminated(" ", main.output.to.stream); + f_print_terminated(" ", main->output.to.stream); } } else { - if (main.mode == byte_dump_mode_hexidecimal) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + if (main->mode == byte_dump_mode_hexidecimal) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } if (invalid[character_current]) { - fl_print_format(" %[%02_uii%]", main.output.to.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_format(" %[%02_uii%]", main->output.to.stream, main->context.set.error, (uint8_t) byte, main->context.set.error); } else { - fl_print_format(" %02_uii", main.output.to.stream, (uint8_t) byte); + fl_print_format(" %02_uii", main->output.to.stream, (uint8_t) byte); } } - else if (main.mode == byte_dump_mode_duodecimal) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_duodecimal) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } if (invalid[character_current]) { - fl_print_format(" %[%03&uii%]", main.output.to.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_format(" %[%03&uii%]", main->output.to.stream, main->context.set.error, (uint8_t) byte, main->context.set.error); } else { - fl_print_format(" %03&uii", main.output.to.stream, (uint8_t) byte); + fl_print_format(" %03&uii", main->output.to.stream, (uint8_t) byte); } } - else if (main.mode == byte_dump_mode_octal) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_octal) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } if (invalid[character_current]) { - fl_print_format(" %[%03@uii%]", main.output.to.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_format(" %[%03@uii%]", main->output.to.stream, main->context.set.error, (uint8_t) byte, main->context.set.error); } else { - fl_print_format(" %03@uii", main.output.to.stream, (uint8_t) byte); + fl_print_format(" %03@uii", main->output.to.stream, (uint8_t) byte); } } - else if (main.mode == byte_dump_mode_binary) { + else if (main->mode == byte_dump_mode_binary) { if (invalid[character_current]) { - fl_print_format(" %[%08!uii%]", main.output.to.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_format(" %[%08!uii%]", main->output.to.stream, main->context.set.error, (uint8_t) byte, main->context.set.error); } else { - fl_print_format(" %08!uii", main.output.to.stream, (uint8_t) byte); + fl_print_format(" %08!uii", main->output.to.stream, (uint8_t) byte); } } - else if (main.mode == byte_dump_mode_decimal) { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { - f_print_terminated(" ", main.output.to.stream); + else if (main->mode == byte_dump_mode_decimal) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + f_print_terminated(" ", main->output.to.stream); } if (invalid[character_current]) { - fl_print_format(" %[%3uii%]", main.output.to.stream, main.context.set.error, (uint8_t) byte, main.context.set.error); + fl_print_format(" %[%3uii%]", main->output.to.stream, main->context.set.error, (uint8_t) byte, main->context.set.error); } else { - fl_print_format(" %3uii", main.output.to.stream, (uint8_t) byte); + fl_print_format(" %3uii", main->output.to.stream, (uint8_t) byte); } } } @@ -486,7 +490,7 @@ extern "C" { ++cell->column; } - if (cell->column == main.width) { + if (cell->column == main->width) { uint8_t bytes = 0; if (byte_current < width_utf) { @@ -495,11 +499,11 @@ extern "C" { reset = F_true; - if (main.parameters[byte_dump_parameter_text].result == f_console_result_found) { + if (main->parameters[byte_dump_parameter_text].result == f_console_result_found) { byte_dump_print_text(main, characters, invalid, previous, offset); } else { - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } cell->column = 0; @@ -515,34 +519,34 @@ extern "C" { } } else { - if (main.parameters[byte_dump_parameter_unicode].result == f_console_result_found) { + if (main->parameters[byte_dump_parameter_unicode].result == f_console_result_found) { if (!(cell->column % 4)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_hexidecimal) { + else if (main->mode == byte_dump_mode_hexidecimal) { if (!(cell->column % 8)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_duodecimal) { + else if (main->mode == byte_dump_mode_duodecimal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_octal) { + else if (main->mode == byte_dump_mode_octal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_binary) { + else if (main->mode == byte_dump_mode_binary) { if (!(cell->column % 4)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } - else if (main.mode == byte_dump_mode_decimal) { + else if (main->mode == byte_dump_mode_decimal) { if (!(cell->column % 6)) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } } @@ -552,7 +556,7 @@ extern "C" { #endif // _di_byte_dump_print_character_fragment_ #ifndef _di_byte_dump_print_text_ - void byte_dump_print_text(const byte_dump_main_t main, const f_utf_string_static_t characters, const char invalid[], byte_dump_previous_t *previous, uint8_t *offset) { + void byte_dump_print_text(byte_dump_main_t * const main, const f_utf_string_static_t characters, const char invalid[], byte_dump_previous_t *previous, uint8_t *offset) { uint8_t j = 0; uint8_t c = 0; @@ -561,15 +565,15 @@ extern "C" { char byte[5] = { 0, 0, 0, 0, 0 }; - f_print_terminated(" ", main.output.to.stream); - fl_print_color_terminated(byte_dump_character_wall_s, main.context.set.notable, main.output.to.stream); - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_terminated(" ", main->output.to.stream); + fl_print_color_terminated(byte_dump_character_wall_s, main->context.set.notable, main->output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); if (*offset) { - if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - while (*offset && j < main.width) { + if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + while (*offset && j < main->width) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); --(*offset); ++j; } // while @@ -577,18 +581,18 @@ extern "C" { else { const char *placeholder = f_string_space_s; - while (*offset && j < main.width) { + while (*offset && j < main->width) { - f_print_terminated(" ", main.output.to.stream); + f_print_terminated(" ", main->output.to.stream); - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } else { - fl_print_color_terminated(f_string_space_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(f_string_space_s, main->context.set.warning, main->output.to.stream); } - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); --(*offset); ++j; } // while @@ -596,31 +600,31 @@ extern "C" { } // Print placeholders for the remaining fragments of UTF-8 characters printed on previous lines. - if (j < main.width) { + if (j < main->width) { uint8_t bytes_overflow = 0; - if (previous->bytes - 1 > main.width) { - bytes_overflow = previous->bytes - 1 - main.width; + if (previous->bytes - 1 > main->width) { + bytes_overflow = previous->bytes - 1 - main->width; } if (previous->bytes) { - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - for (; j < previous->bytes && j < main.width; ++j) { + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + for (; j < previous->bytes && j < main->width; ++j) { if (previous->invalid) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.error, main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } } // for } else { - for (; j < previous->bytes && j < main.width; ++j) { - f_print_character(f_string_space_s[0], main.output.to.stream); + for (; j < previous->bytes && j < main->width; ++j) { + f_print_character(f_string_space_s[0], main->output.to.stream); } // for } } @@ -634,18 +638,18 @@ extern "C" { } } - for (uint8_t i = 0; i < characters.used && j < main.width; ++i, ++j) { + for (uint8_t i = 0; i < characters.used && j < main->width; ++i, ++j) { c = macro_f_utf_character_t_to_char_1(characters.string[i]); width_utf = macro_f_utf_byte_width_is(c); if (invalid[i]) { - fl_print_color_terminated(byte_dump_character_incomplete_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_incomplete_s, main->context.set.error, main->output.to.stream); } else if (f_utf_character_is_control(characters.string[i]) == F_true) { - if (main.presentation == byte_dump_presentation_normal) { - fl_print_color_before(main.context.set.notable, main.output.to.stream); - fl_print_color_before(main.context.set.warning, main.output.to.stream); + if (main->presentation == byte_dump_presentation_normal) { + fl_print_color_before(main->context.set.notable, main->output.to.stream); + fl_print_color_before(main->context.set.warning, main->output.to.stream); if (width_utf) { byte[0] = c; @@ -671,126 +675,126 @@ extern "C" { byte[1] = 0; } - f_print_safely(byte, width_utf ? width_utf : 1, main.output.to.stream); + f_print_safely(byte, width_utf ? width_utf : 1, main->output.to.stream); } else { - f_print_character_safely(c, main.output.to.stream); + f_print_character_safely(c, main->output.to.stream); } - fl_print_color_after(main.context.set.warning, main.output.to.stream); - fl_print_color_after(main.context.set.notable, main.output.to.stream); + fl_print_color_after(main->context.set.warning, main->output.to.stream); + fl_print_color_after(main->context.set.notable, main->output.to.stream); } - else if (main.presentation == byte_dump_presentation_simple) { - f_print_character(f_string_space_s[0], main.output.to.stream); + else if (main->presentation == byte_dump_presentation_simple) { + f_print_character(f_string_space_s[0], main->output.to.stream); if (width_utf > 1) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); if (width_utf > 2) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); if (width_utf > 3) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } } } - else if (main.presentation == byte_dump_presentation_classic) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->presentation == byte_dump_presentation_classic) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); if (width_utf > 1) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); if (width_utf > 2) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); if (width_utf > 3) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } } } } } else if (f_utf_character_is_whitespace(characters.string[i]) == F_true) { - if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_before(main.context.set.notable, main.output.to.stream); - fl_print_color_terminated(byte_dump_sequence_space_s, main.context.set.warning, main.output.to.stream); - fl_print_color_after(main.context.set.notable, main.output.to.stream); + fl_print_color_before(main->context.set.notable, main->output.to.stream); + fl_print_color_terminated(byte_dump_sequence_space_s, main->context.set.warning, main->output.to.stream); + fl_print_color_after(main->context.set.notable, main->output.to.stream); } } else if (f_utf_character_is_zero_width(characters.string[i]) == F_true) { - if (main.presentation == byte_dump_presentation_classic) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + if (main->presentation == byte_dump_presentation_classic) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - fl_print_color_before(main.context.set.notable, main.output.to.stream); - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); - fl_print_color_after(main.context.set.notable, main.output.to.stream); + else if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + fl_print_color_before(main->context.set.notable, main->output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); + fl_print_color_after(main->context.set.notable, main->output.to.stream); } else { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } else if (width_utf == 2 && characters.string[i] == 0xd89d0000) { // U+061C - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xefbfb000 && characters.string[i] <= 0xefbfbc00) { // Use space to represent Specials codes. // 0xefbfbd00 is excluded because it is printable (and is the "Replacement Character" code). - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe290a700 && characters.string[i] <= 0xe290bf00) { // Use space to represent Control Pictues codes that are not currently defined but are reserved. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xee808000 && characters.string[i] <= 0xefa3bf00) { // Use space to represent Private Use Area codes. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf09c80a0 && characters.string[i] <= 0xf09c80bd) { // Use space to represent Vaiation Selectors Supplement codes. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf3b08080 && characters.string[i] <= 0xf3bfbfbf) { // Use space to represent Supplemental Private Use Area-A codes. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 4 && characters.string[i] >= 0xf4808080 && characters.string[i] <= 0xf48fbfbf) { // Use space to represent Supplemental Private Use Area-B codes. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 1) { // print invalid placeholder for invalid UTF-8 widths. if (invalid[i]) { - fl_print_color_terminated(byte_dump_character_incomplete_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_incomplete_s, main->context.set.error, main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_incomplete_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_incomplete_s, main->context.set.warning, main->output.to.stream); } } else if (width_utf) { - f_print_character(c, main.output.to.stream); + f_print_character(c, main->output.to.stream); if (width_utf > 1) { - f_print_character(macro_f_utf_character_t_to_char_2(characters.string[i]), main.output.to.stream); + f_print_character(macro_f_utf_character_t_to_char_2(characters.string[i]), main->output.to.stream); if (width_utf > 2) { - f_print_character(macro_f_utf_character_t_to_char_3(characters.string[i]), main.output.to.stream); + f_print_character(macro_f_utf_character_t_to_char_3(characters.string[i]), main->output.to.stream); if (width_utf > 3) { - f_print_character(macro_f_utf_character_t_to_char_4(characters.string[i]), main.output.to.stream); + f_print_character(macro_f_utf_character_t_to_char_4(characters.string[i]), main->output.to.stream); } } } @@ -800,94 +804,94 @@ extern "C" { if (width_utf == 2 && characters.string[i] >= 0xdea60000 && characters.string[i] <= 0xdeb00000) { // Thana combining codes: U+07A6 to U+07B0. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 2 && characters.string[i] >= 0xcc800000 && characters.string[i] <= 0xcdaf0000) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe1aab000 && characters.string[i] <= 0xe1abbf00) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe1b78000 && characters.string[i] <= 0xe1b7bf00) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 3 && characters.string[i] >= 0xe2839000 && characters.string[i] <= 0xe283bf00) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd8900000 && characters.string[i] <= 0xd89a0000) { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd98b0000 && characters.string[i] <= 0xd99f0000) { // Arabic, U+064B to U+065F. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 2 && characters.string[i] >= 0xdb960000 && characters.string[i] <= 0xdb9c0000) { // Arabic, U+06D6 to U+06DC. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } else if (width_utf == 2 && characters.string[i] >= 0xd6910000 && characters.string[i] <= 0xd6bd0000) { // Hebrew, U+0591 to U+05BD. - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } } else { - f_print_character(c, main.output.to.stream); + f_print_character(c, main->output.to.stream); } // When using UTF-8 characters, the character columns will not line up, so print placeholders to simulate the bytes that are not printed, if necessary for alignment. - if (width_utf > 1 && j + 1 < main.width) { - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + if (width_utf > 1 && j + 1 < main->width) { + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.error, main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } } else { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } ++j; - if (width_utf > 2 && j + 1 < main.width) { - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + if (width_utf > 2 && j + 1 < main->width) { + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.error, main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } } else { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } ++j; - if (width_utf > 3 && j + 1 < main.width) { - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + if (width_utf > 3 && j + 1 < main->width) { + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { if (invalid[i]) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.error, main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } } else { - f_print_character(f_string_space_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); } ++j; @@ -897,29 +901,29 @@ extern "C" { } // for // Print placeholder for the remaining parts of the line. - if (main.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { - for (; j < main.width; ++j) { + if (main->parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { + for (; j < main->width; ++j) { if (invalid[j]) { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.error, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.error, main->output.to.stream); } - else if (main.parameters[byte_dump_parameter_classic].result == f_console_result_found) { - f_print_character(f_string_ascii_period_s[0], main.output.to.stream); + else if (main->parameters[byte_dump_parameter_classic].result == f_console_result_found) { + f_print_character(f_string_ascii_period_s[0], main->output.to.stream); } else { - fl_print_color_terminated(byte_dump_character_placeholder_s, main.context.set.warning, main.output.to.stream); + fl_print_color_terminated(byte_dump_character_placeholder_s, main->context.set.warning, main->output.to.stream); } } // for } else { - for (; j < main.width; ++j) { - f_print_character(f_string_space_s[0], main.output.to.stream); + for (; j < main->width; ++j) { + f_print_character(f_string_space_s[0], main->output.to.stream); } // for } - f_print_character(f_string_space_s[0], main.output.to.stream); - fl_print_color_terminated(byte_dump_character_wall_s, main.context.set.notable, main.output.to.stream); - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_space_s[0], main->output.to.stream); + fl_print_color_terminated(byte_dump_character_wall_s, main->context.set.notable, main->output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } #endif // _di_byte_dump_file_ diff --git a/level_3/byte_dump/c/private-byte_dump.h b/level_3/byte_dump/c/private-byte_dump.h index 0a08309..8e434b6 100644 --- a/level_3/byte_dump/c/private-byte_dump.h +++ b/level_3/byte_dump/c/private-byte_dump.h @@ -16,7 +16,7 @@ extern "C" { * Dump the contents of the file to standard out. * * @param main - * The main data. + * The main program data. * @param file_name * The name of the file. * @param file @@ -25,17 +25,19 @@ extern "C" { * * @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(const byte_dump_main_t main, const f_string_t file_name, const f_file_t file) F_attribute_visibility_internal_d; + extern f_status_t byte_dump_file(byte_dump_main_t * const main, const f_string_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 data. + * The main program data. * @param characters * An array of UTF-8 and ASCII characters. * @param invalid @@ -69,7 +71,7 @@ extern "C" { * @see byte_dump_print_text() */ #ifndef _di_byte_dump_print_character_fragment_ - extern bool byte_dump_print_character_fragment(const byte_dump_main_t main, const f_utf_string_static_t characters, const char invalid[], const uint8_t width_utf, const char byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, uint8_t *offset) F_attribute_visibility_internal_d; + extern bool byte_dump_print_character_fragment(byte_dump_main_t * const main, const f_utf_string_static_t characters, const char invalid[], const uint8_t width_utf, const char byte_current, byte_dump_previous_t *previous, byte_dump_cell_t *cell, uint8_t *offset) F_attribute_visibility_internal_d; #endif // _di_byte_dump_print_character_fragment_ /** @@ -78,7 +80,7 @@ extern "C" { * This should be called only when text mode is enabled. * * @param main - * The main data. + * The main program data. * @param characters * An array of UTF-8 and ASCII characters. * @param invalid @@ -91,7 +93,7 @@ extern "C" { * Will be reduced to 0 once used. */ #ifndef _di_byte_dump_print_text_ - extern void byte_dump_print_text(const byte_dump_main_t main, const f_utf_string_static_t characters, const char invalid[], byte_dump_previous_t *previous, uint8_t *offset) F_attribute_visibility_internal_d; + extern void byte_dump_print_text(byte_dump_main_t * const main, const f_utf_string_static_t characters, const char invalid[], byte_dump_previous_t *previous, uint8_t *offset) F_attribute_visibility_internal_d; #endif // _di_byte_dump_print_text_ #ifdef __cplusplus diff --git a/level_3/byte_dump/c/private-common.c b/level_3/byte_dump/c/private-common.c index 820be90..15a0a16 100644 --- a/level_3/byte_dump/c/private-common.c +++ b/level_3/byte_dump/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_byte_dump_print_signal_received_ + void byte_dump_print_signal_received(byte_dump_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_byte_dump_print_signal_received_ + +#ifndef _di_byte_dump_signal_received_ + f_status_t byte_dump_signal_received(byte_dump_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + byte_dump_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_byte_dump_signal_received_ + #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 index 6604c7e..9200a5b 100644 --- a/level_3/byte_dump/c/private-common.h +++ b/level_3/byte_dump/c/private-common.h @@ -55,6 +55,36 @@ extern "C" { } #endif // _di_byte_previous_cell_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_byte_dump_print_signal_received_ + extern void byte_dump_print_signal_received(byte_dump_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_byte_dump_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_byte_dump_signal_received_ + extern f_status_t byte_dump_signal_received(byte_dump_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_byte_dump_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/data/build/dependencies b/level_3/byte_dump/data/build/dependencies index f48f7f0..fa07553 100644 --- a/level_3/byte_dump/data/build/dependencies +++ b/level_3/byte_dump/data/build/dependencies @@ -11,6 +11,7 @@ f_conversion f_file f_pipe f_print +f_signal fl_console fl_conversion fl_print diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c index eafccdf..a4c18eb 100644 --- a/level_3/control/c/control.c +++ b/level_3/control/c/control.c @@ -32,7 +32,7 @@ extern "C" { #endif // _di_control_print_help_ #ifndef _di_control_main_ - f_status_t control_main(const f_console_arguments_t arguments, control_main_t *main) { + f_status_t control_main(control_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -43,7 +43,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { control_parameter_no_color, control_parameter_light, control_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -72,6 +72,7 @@ extern "C" { } control_main_delete(main); + return F_status_set_error(status); } } @@ -86,6 +87,7 @@ extern "C" { if (F_status_is_error(status)) { control_main_delete(main); + return status; } @@ -118,6 +120,7 @@ extern "C" { control_print_help(main->output.to, main->context); control_main_delete(main); + return F_none; } @@ -125,25 +128,31 @@ extern "C" { fll_program_print_version(main->output.to, control_program_version_s); control_main_delete(main); + return F_none; } // @todo - // ensure a newline is always put at the end of the program execution, unless in quiet mode. - if (main->error.verbosity != f_console_verbosity_quiet) { + // 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) { if (F_status_is_error(status)) { - fll_print_terminated(f_string_eol_s, main->error.to.stream); + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_terminated(f_string_eol_s, main->output.to.stream); } } control_main_delete(main); + return status; } #endif // _di_control_main_ #ifndef _di_control_main_delete_ - f_status_t control_main_delete(control_main_t *main) { + f_status_t control_main_delete(control_main_t * const main) { for (f_array_length_t i = 0; i < control_total_parameters_d; ++i) { diff --git a/level_3/control/c/control.h b/level_3/control/c/control.h index d07caaf..c78da9d 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/control.h @@ -27,6 +27,7 @@ #include #include #include +#include // fll-1 includes #include @@ -104,6 +105,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } control_main_t; @@ -115,6 +118,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_control_data_t_ @@ -139,20 +143,30 @@ extern "C" { * * Be sure to call control_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The program main data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. * * @see control_main_delete() */ #ifndef _di_control_main_ - extern f_status_t control_main(const f_console_arguments_t arguments, control_main_t *main); + extern f_status_t control_main(control_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_control_main_ /** @@ -161,7 +175,7 @@ extern "C" { * Be sure to call this after executing control_main(). * * @param main - * The program main data. + * The main program data. * * @return * F_none on success. @@ -171,7 +185,7 @@ extern "C" { * @see control_main() */ #ifndef _di_control_main_delete_ - extern f_status_t control_main_delete(control_main_t *main); + extern f_status_t control_main_delete(control_main_t * const main); #endif // _di_control_main_delete_ #ifdef __cplusplus diff --git a/level_3/control/c/main.c b/level_3/control/c/main.c index 8976711..4d2c962 100644 --- a/level_3/control/c/main.c +++ b/level_3/control/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = control_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = control_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/control/c/private-common.c b/level_3/control/c/private-common.c index d869788..92941da 100644 --- a/level_3/control/c/private-common.c +++ b/level_3/control/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_control_print_signal_received_ + void control_print_signal_received(control_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_control_print_signal_received_ + +#ifndef _di_control_signal_received_ + f_status_t control_signal_received(control_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + control_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_control_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/c/private-common.h b/level_3/control/c/private-common.h index 58879a3..00ae160 100644 --- a/level_3/control/c/private-common.h +++ b/level_3/control/c/private-common.h @@ -12,6 +12,36 @@ extern "C" { #endif +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_control_print_signal_received_ + extern void control_print_signal_received(control_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_control_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_control_signal_received_ + extern f_status_t control_signal_received(control_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_control_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/data/build/dependencies b/level_3/control/data/build/dependencies index 95b9fce..7eeec9a 100644 --- a/level_3/control/data/build/dependencies +++ b/level_3/control/data/build/dependencies @@ -10,6 +10,7 @@ f_console f_file f_pipe f_print +f_signal fl_console fl_print fl_string diff --git a/level_3/controller/c/controller.c b/level_3/controller/c/controller.c index 145045d..e4f46bb 100644 --- a/level_3/controller/c/controller.c +++ b/level_3/controller/c/controller.c @@ -13,51 +13,51 @@ extern "C" { #endif #ifndef _di_controller_print_help_ - f_status_t controller_print_help(const controller_main_t main) { + f_status_t controller_print_help(controller_main_t * const main) { - controller_lock_print(main.output.to, 0); + controller_lock_print(main->output.to, 0); - fll_program_print_help_header(main.output.to, main.context, main.program_name_long, controller_program_version_s); + fll_program_print_help_header(main->output.to, main->context, main->program_name_long, controller_program_version_s); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Do not main.output.to in color."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity beyond normal main.output.to."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal main.output.to."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal main.output.to."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, inceasing verbosity beyond normal main.output.to."); - fll_program_print_help_option(main.output.to, main.context, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Do not main->output.to in color."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity beyond normal main->output.to."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal main->output.to."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal main->output.to."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, inceasing verbosity beyond normal main->output.to."); + fll_program_print_help_option(main->output.to, main->context, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); - fll_program_print_help_option(main.output.to, main.context, controller_short_control_s, controller_long_control_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom control group file path, such as '" F_control_group_path_system_prefix_s F_control_group_path_system_default_s "'."); - fll_program_print_help_option(main.output.to, main.context, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run in daemon only mode (do not process the entry)."); - fll_program_print_help_option(main.output.to, main.context, controller_short_init_s, controller_long_init_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The program will run as an init replacement."); - fll_program_print_help_option(main.output.to, main.context, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate that this program can be interrupted by a signal."); - fll_program_print_help_option(main.output.to, main.context, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as '" controller_path_pid_s CONTROLLER_default_s controller_path_suffix_s "'."); - fll_program_print_help_option(main.output.to, main.context, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as '" controller_path_settings_s "'."); - fll_program_print_help_option(main.output.to, main.context, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run as a simulation."); - fll_program_print_help_option(main.output.to, main.context, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Designate that this program cannot be interrupted by a signal."); - fll_program_print_help_option(main.output.to, main.context, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Validate the settings (entry and rules) without running (does not simulate)."); + fll_program_print_help_option(main->output.to, main->context, controller_short_control_s, controller_long_control_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom control group file path, such as '" F_control_group_path_system_prefix_s F_control_group_path_system_default_s "'."); + fll_program_print_help_option(main->output.to, main->context, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run in daemon only mode (do not process the entry)."); + fll_program_print_help_option(main->output.to, main->context, controller_short_init_s, controller_long_init_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The program will run as an init replacement."); + fll_program_print_help_option(main->output.to, main->context, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate that this program can be interrupted by a signal."); + fll_program_print_help_option(main->output.to, main->context, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as '" controller_path_pid_s CONTROLLER_default_s controller_path_suffix_s "'."); + fll_program_print_help_option(main->output.to, main->context, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as '" controller_path_settings_s "'."); + fll_program_print_help_option(main->output.to, main->context, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run as a simulation."); + fll_program_print_help_option(main->output.to, main->context, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Designate that this program cannot be interrupted by a signal."); + fll_program_print_help_option(main->output.to, main->context, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Validate the settings (entry and rules) without running (does not simulate)."); - fll_program_print_help_usage(main.output.to, main.context, main.program_name, "entry"); + fll_program_print_help_usage(main->output.to, main->context, main->program_name, "entry"); - fl_print_format(" When both the %[%s%s%] parameter and the", main.output.to.stream, main.context.set.notable, f_console_symbol_long_enable_s, controller_long_simulate_s, main.context.set.notable); - fl_print_format(" %[%s%s%] parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.%c%c", main.output.to.stream, main.context.set.notable, f_console_symbol_long_enable_s, controller_long_validate_s, main.context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); + fl_print_format(" When both the %[%s%s%] parameter and the", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_simulate_s, main->context.set.notable); + fl_print_format(" %[%s%s%] parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.%c%c", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_validate_s, main->context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); - fl_print_format(" The default interrupt behavior is to operate as if the %[%s%s%] parameter is passed.%c%c", main.output.to.stream, main.context.set.notable, f_console_symbol_long_enable_s, main.setting_default.used ? controller_long_uninterruptible_s : controller_long_interruptible_s, main.context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); + fl_print_format(" The default interrupt behavior is to operate as if the %[%s%s%] parameter is passed.%c%c", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, main->setting_default.used ? controller_long_uninterruptible_s : controller_long_interruptible_s, main->context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); - fl_print_format(" Specify an empty string for the %[%s%s%] parameter to disable pid file creation for this program.%c%c", main.output.to.stream, main.context.set.notable, f_console_symbol_long_enable_s, controller_long_pid_s, main.context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); + fl_print_format(" Specify an empty string for the %[%s%s%] parameter to disable pid file creation for this program.%c%c", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_pid_s, main->context.set.notable, f_string_eol_s[0], f_string_eol_s[0]); - controller_unlock_print_flush(main.output.to, 0); + controller_unlock_print_flush(main->output.to, 0); return F_none; } #endif // _di_controller_print_help_ #ifndef _di_controller_main_ - f_status_t controller_main(const f_console_arguments_t arguments, controller_main_t *main) { + f_status_t controller_main(controller_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -68,7 +68,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { controller_parameter_no_color, controller_parameter_light, controller_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -140,7 +140,7 @@ extern "C" { } if (main->parameters[controller_parameter_help].result == f_console_result_found) { - controller_print_help(*main); + controller_print_help(main); controller_main_delete(main); return F_none; @@ -160,7 +160,7 @@ extern "C" { controller_setting_t setting = controller_setting_t_initialize; if (main->remaining.used) { - status = f_string_append_nulless(arguments.argv[main->remaining.array[0]], strnlen(arguments.argv[main->remaining.array[0]], f_console_parameter_size), &setting.name_entry); + status = f_string_append_nulless(arguments->argv[main->remaining.array[0]], strnlen(arguments->argv[main->remaining.array[0]], f_console_parameter_size), &setting.name_entry); } else { status = f_string_append_nulless(controller_default_s, controller_default_s_length, &setting.name_entry); @@ -206,7 +206,7 @@ extern "C" { else if (main->parameters[controller_parameter_settings].locations.used) { const f_array_length_t location = main->parameters[controller_parameter_settings].values.array[main->parameters[controller_parameter_settings].values.used - 1]; - status = fll_path_canonical(arguments.argv[location], &setting.path_setting); + status = fll_path_canonical(arguments->argv[location], &setting.path_setting); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true); @@ -245,8 +245,8 @@ extern "C" { else if (main->parameters[controller_parameter_pid].locations.used) { const f_array_length_t location = main->parameters[controller_parameter_pid].values.array[main->parameters[controller_parameter_pid].values.used - 1]; - if (strnlen(arguments.argv[location], f_console_parameter_size)) { - status = fll_path_canonical(arguments.argv[location], &setting.path_pid); + if (strnlen(arguments->argv[location], f_console_parameter_size)) { + status = fll_path_canonical(arguments->argv[location], &setting.path_pid); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true); @@ -297,8 +297,8 @@ extern "C" { else if (main->parameters[controller_parameter_control].locations.used) { const f_array_length_t location = main->parameters[controller_parameter_control].values.array[main->parameters[controller_parameter_control].values.used - 1]; - if (strnlen(arguments.argv[location], f_console_parameter_size)) { - status = fll_path_canonical(arguments.argv[location], &setting.path_control); + if (strnlen(arguments->argv[location], f_console_parameter_size)) { + status = fll_path_canonical(arguments->argv[location], &setting.path_control); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true); @@ -379,7 +379,7 @@ extern "C" { status = f_signal_open(&main->signal); } - // if there is an error opening a signal descriptor, then do not handle signals. + // If there is an error opening a signal descriptor, then do not handle signals. if (F_status_is_error(status)) { f_signal_mask(SIG_UNBLOCK, &main->signal.set, 0); f_signal_close(&main->signal); @@ -418,16 +418,16 @@ extern "C" { } // Ensure a newline is always put at the end of the program execution, unless in quiet mode. - if (!(status == F_child || status == F_signal)) { - if (F_status_is_error(status) && main->error.verbosity != f_console_verbosity_quiet) { - f_print_terminated(f_string_eol_s, main->error.to.stream); + if (F_status_is_error(status) && main->output.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); } - } - f_signal_close(&main->signal); + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } if (status != F_child && setting.pid_created) { - f_status_t status_delete = controller_file_pid_delete(main->pid, setting.path_pid); + const f_status_t status_delete = controller_file_pid_delete(main->pid, setting.path_pid); if (F_status_is_error(status_delete) && main->warning.verbosity == f_console_verbosity_debug) { if (F_status_set_fine(status_delete) == F_number_not) { @@ -441,7 +441,7 @@ extern "C" { controller_unlock_print_flush(main->warning.to, 0); } - else { + else if (F_status_set_fine(status_delete) != F_interrupt) { fll_error_file_print(main->warning, F_status_set_fine(status_delete), "controller_file_pid_delete", F_true, setting.path_pid.string, "delete", fll_error_file_type_file); } } @@ -450,7 +450,7 @@ extern "C" { controller_setting_delete_simple(&setting); controller_main_delete(main); - if (status == F_child || status == F_signal) { + if (status == F_child) { return status; } @@ -459,7 +459,7 @@ extern "C" { #endif // _di_controller_main_ #ifndef _di_controller_main_delete_ - f_status_t controller_main_delete(controller_main_t *main) { + f_status_t controller_main_delete(controller_main_t * const main) { for (f_array_length_t i = 0; i < controller_total_parameters_d; ++i) { diff --git a/level_3/controller/c/controller.h b/level_3/controller/c/controller.h index ec535d5..bfe398c 100644 --- a/level_3/controller/c/controller.h +++ b/level_3/controller/c/controller.h @@ -227,10 +227,11 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + pid_t pid; mode_t umask; int child; - f_signal_t signal; f_string_t program_name; f_string_t program_name_long; @@ -249,10 +250,10 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ 0, \ 0, \ 0, \ - f_signal_t_initialize, \ f_string_t_initialize, \ f_string_t_initialize, \ f_string_static_t_initialize, \ @@ -265,13 +266,13 @@ extern "C" { * Print help. * * @param main - * The program main data. + * The main program data. * * @return * F_none on success. */ #ifndef _di_controller_print_help_ - extern f_status_t controller_print_help(const controller_main_t main); + extern f_status_t controller_print_help(controller_main_t * const main); #endif // _di_controller_print_help_ /** @@ -279,20 +280,31 @@ extern "C" { * * Be sure to call controller_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The program main data. * * @return * F_none on success. + * F_child if this is a child process returning. + * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * * Status codes (with error bit) are returned on any problem. * * @see controller_main_delete() */ #ifndef _di_controller_main_ - extern f_status_t controller_main(const f_console_arguments_t arguments, controller_main_t *main); + extern f_status_t controller_main(controller_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_controller_main_ /** @@ -300,8 +312,16 @@ extern "C" { * * Be sure to call this after executing controller_main(). * + * 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 program main data. + * The main program data. * * @return * F_none on success. @@ -311,7 +331,7 @@ extern "C" { * @see controller_main() */ #ifndef _di_controller_main_delete_ - extern f_status_t controller_main_delete(controller_main_t *main); + extern f_status_t controller_main_delete(controller_main_t * const main); #endif // _di_controller_main_delete_ #ifdef __cplusplus diff --git a/level_3/controller/c/main.c b/level_3/controller/c/main.c index 352d08e..d82171e 100644 --- a/level_3/controller/c/main.c +++ b/level_3/controller/c/main.c @@ -4,7 +4,6 @@ int main(const int argc, const f_string_t *argv) { const f_console_arguments_t arguments = { argc, argv }; controller_main_t data = controller_main_t_initialize; - f_status_t status = F_none; if (f_pipe_input_exists()) { data.process_pipe = F_true; @@ -12,30 +11,37 @@ int main(const int argc, const f_string_t *argv) { data.pid = getpid(); - f_signal_set_empty(&data.signal.set); - f_signal_set_add(F_signal_abort, &data.signal.set); - f_signal_set_add(F_signal_hangup, &data.signal.set); - f_signal_set_add(F_signal_interrupt, &data.signal.set); - f_signal_set_add(F_signal_quit, &data.signal.set); - f_signal_set_add(F_signal_termination, &data.signal.set); - f_signal_mask(SIG_BLOCK, &data.signal.set, 0); - - status = f_signal_open(&data.signal); - - // if there is an error opening a signal descriptor, then do not handle signals. - if (F_status_is_error(status)) { - f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); - f_signal_close(&data.signal); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } } // @fixme bad design in POSIX where there is no get umask without setting it. data.umask = umask(0); - // restore umask. + // Restore umask. umask(data.umask); // when run as "init" by default, provide the default system-level init path. - // this change must only exist within this main file so that the change only exists within the program rather than the library. + // This change must only exist within this main file so that the change only exists within the program rather than the library. #ifdef _controller_as_init_ data.program_name = controller_program_name_init_s; data.program_name_long = controller_program_name_init_long_s; @@ -51,29 +57,26 @@ int main(const int argc, const f_string_t *argv) { data.path_pid.used = controller_path_pid_s_length; #endif // _controller_as_init_ - status = controller_main(arguments, &data); + const f_status_t status = controller_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); f_signal_close(&data.signal); + // When the child process exits, it must return the code to the parent so the parent knows how to handle the exit. if (status == F_child) { exit(data.child); } if (F_status_is_error(status)) { - - // do not return error when interrupt was received. - if (F_status_set_fine(status) != F_interrupt) { - return 1; - } + return 1; } return 0; diff --git a/level_3/controller/c/private-common.c b/level_3/controller/c/private-common.c index 1fa0ada..26d2d25 100644 --- a/level_3/controller/c/private-common.c +++ b/level_3/controller/c/private-common.c @@ -491,7 +491,7 @@ extern "C" { #endif // _di_controller_rule_actions_increase_by_ #ifndef _di_controller_rule_delete_simple_ - void controller_rule_delete_simple(controller_rule_t *rule) { + void controller_rule_delete_simple(controller_rule_t * const rule) { f_string_dynamic_resize(0, &rule->alias); f_string_dynamic_resize(0, &rule->name); diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 8fd7e5a..2d1b194 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -2205,7 +2205,7 @@ extern "C" { * @see f_thread_mutex_unlock() */ #ifndef _di_controller_thread_delete_simple_ - extern void controller_thread_delete_simple(controller_thread_t *thread) F_attribute_visibility_internal_d; + extern void controller_thread_delete_simple(controller_thread_t * const thread) F_attribute_visibility_internal_d; #endif // _di_controller_thread_delete_simple_ #ifdef __cplusplus diff --git a/level_3/controller/c/private-controller.h b/level_3/controller/c/private-controller.h index 75c4ca8..76b02c5 100644 --- a/level_3/controller/c/private-controller.h +++ b/level_3/controller/c/private-controller.h @@ -359,7 +359,7 @@ extern "C" { * The signals will not be unblocked when in uninterruptible mode. * * @param main - * The program main data. + * The main program data. * @param setting * The settings. * @param time diff --git a/level_3/controller/c/private-controller_print.c b/level_3/controller/c/private-controller_print.c index 546e10e..2615b1e 100644 --- a/level_3/controller/c/private-controller_print.c +++ b/level_3/controller/c/private-controller_print.c @@ -44,6 +44,24 @@ extern "C" { } #endif // _di_controller_print_error_file_ +#ifndef _di_controller_print_signal_received_ + void controller_print_signal_received(controller_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_controller_print_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/private-controller_print.h b/level_3/controller/c/private-controller_print.h index 78365f0..0a0bf08 100644 --- a/level_3/controller/c/private-controller_print.h +++ b/level_3/controller/c/private-controller_print.h @@ -64,6 +64,18 @@ extern "C" { extern void controller_print_error_file(const fl_print_t print, const f_status_t status, const f_string_t function, const bool fallback, const f_string_t name, const f_string_t operation, const uint8_t type, controller_thread_t *thread) F_attribute_visibility_internal_d; #endif // _di_controller_print_error_file_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_controller_print_signal_received_ + extern void controller_print_signal_received(controller_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_controller_print_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c index 120215f..aa5098b 100644 --- a/level_3/controller/c/private-entry.c +++ b/level_3/controller/c/private-entry.c @@ -910,7 +910,7 @@ extern "C" { } // while if (!controller_thread_is_enabled(is_entry, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } // if ready was never found in the entry, then default to always ready. @@ -1194,7 +1194,7 @@ extern "C" { else if (entry_action->type == controller_entry_action_type_consider || controller_entry_action_type_is_rule(entry_action->type)) { status_lock = controller_lock_write(is_entry, global->thread, &global->thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global->main->error, F_status_set_fine(status_lock), F_false, global->thread); break; } @@ -1221,9 +1221,8 @@ extern "C" { status_lock = controller_lock_read(is_entry, global->thread, &global->thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global->main->error, F_status_set_fine(status_lock), F_true, global->thread); - break; } @@ -1279,7 +1278,7 @@ extern "C" { status_lock = controller_lock_write(is_entry, global->thread, &global->thread->lock.rule); - if (!(status_lock == F_signal || F_status_is_error(status_lock))) { + if (F_status_is_fine(status_lock)) { status = controller_rule_read(is_entry, alias_rule, *global, cache, entry, &global->setting->rules.array[global->setting->rules.used]); } @@ -1299,13 +1298,12 @@ extern "C" { cache->action.line_action = cache_line_action; cache->action.line_item = cache_line_item; - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global->main->error, F_status_set_fine(status_lock), F_false, global->thread); - break; } - if (status == F_signal || !controller_thread_is_enabled(is_entry, global->thread)) { + if (F_status_set_fine(status) == F_interrupt || !controller_thread_is_enabled(is_entry, global->thread)) { f_thread_unlock(&global->thread->lock.rule); break; @@ -1313,13 +1311,11 @@ extern "C" { if (F_status_is_error(status)) { if (global->main->error.verbosity != f_console_verbosity_quiet) { - if (F_status_set_fine(status) != F_interrupt) { - controller_lock_print(global->main->error.to, global->thread); + controller_lock_print(global->main->error.to, global->thread); - controller_entry_print_error_cache(is_entry, global->main->error, cache->action); + controller_entry_print_error_cache(is_entry, global->main->error, cache->action); - controller_unlock_print_flush(global->main->error.to, global->thread); - } + controller_unlock_print_flush(global->main->error.to, global->thread); } // Designate the action as failed. @@ -1373,7 +1369,7 @@ extern "C" { status = controller_rule_process_begin(options_force, alias_rule, controller_entry_action_type_to_rule_action_type(entry_action->type), options_process, is_entry ? controller_process_type_entry : controller_process_type_exit, stack, *global, *cache); - if (F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal) { + if (F_status_set_fine(status) == F_memory_not || status == F_child || F_status_set_fine(status) == F_interrupt) { break; } @@ -1517,7 +1513,7 @@ extern "C" { } } // for - if (status == F_child || status == F_signal) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt) break; cache->action.line_action = 0; cache->action.name_action.used = 0; @@ -1554,7 +1550,7 @@ extern "C" { } // while if (!controller_thread_is_enabled(is_entry, global->thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } if (status == F_child) { @@ -1569,11 +1565,11 @@ extern "C" { if (F_status_is_error_not(status) && !failsafe && global->main->parameters[controller_parameter_validate].result == f_console_result_none) { const f_status_t status_wait = controller_rule_wait_all(is_entry, *global, F_true, 0); - if (status_wait == F_signal || F_status_is_error(status_wait)) { + if (F_status_is_error(status_wait)) { return status_wait; } - if (F_status_set_fine(status_wait) == F_require) { + if (status_wait == F_require) { return F_status_set_error(F_require); } } @@ -1834,8 +1830,8 @@ extern "C" { } } // for - if (is_entry && status == F_signal) { - return F_signal; + if (is_entry && F_status_set_fine(status) == F_interrupt) { + return status; } if (F_status_is_error_not(status)) { @@ -1869,7 +1865,7 @@ extern "C" { for (j = 0; j < entry->items.array[i].actions.used; ++j) { if (!controller_thread_is_enabled(is_entry, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } action = &entry->items.array[i].actions.array[j]; diff --git a/level_3/controller/c/private-lock.c b/level_3/controller/c/private-lock.c index a4d06b0..8ff399d 100644 --- a/level_3/controller/c/private-lock.c +++ b/level_3/controller/c/private-lock.c @@ -45,7 +45,7 @@ extern "C" { if (status == F_time) { if (!controller_thread_is_enabled(is_normal, thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } else { @@ -86,7 +86,7 @@ extern "C" { if (status == F_time) { if (!controller_thread_is_enabled(is_normal, thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } else { diff --git a/level_3/controller/c/private-lock.h b/level_3/controller/c/private-lock.h index 27fb83b..cb17fe4 100644 --- a/level_3/controller/c/private-lock.h +++ b/level_3/controller/c/private-lock.h @@ -46,9 +46,10 @@ extern "C" { * * @return * F_none on success. - * F_signal on (exit) signal received, lock will not be set when this is returned. * F_status if main thread is disabled and write lock was never achieved. * + * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned. + * * Status from: f_thread_lock_read_timed(). * * Errors (with error bit) from: f_thread_lock_read_timed(). @@ -122,9 +123,10 @@ extern "C" { * * @return * F_none on success. - * F_signal on (exit) signal received, lock will not be set when this is returned. * F_status if main thread is disabled and write lock was never achieved. * + * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned. + * * Status from: f_thread_lock_write_timed(). * * Errors (with error bit) from: f_thread_lock_write_timed(). diff --git a/level_3/controller/c/private-lock_print.c b/level_3/controller/c/private-lock_print.c index 2111521..4f78afd 100644 --- a/level_3/controller/c/private-lock_print.c +++ b/level_3/controller/c/private-lock_print.c @@ -10,7 +10,7 @@ extern "C" { void controller_lock_print_error_critical(const fl_print_t print, const f_status_t status, const bool read, controller_thread_t *thread) { // A signal is not an error. - if (status == F_signal) return; + if (status == F_interrupt) return; if (print.verbosity != f_console_verbosity_quiet) { controller_lock_print(print.to, thread); diff --git a/level_3/controller/c/private-lock_print.h b/level_3/controller/c/private-lock_print.h index 1c7645c..c0e0410 100644 --- a/level_3/controller/c/private-lock_print.h +++ b/level_3/controller/c/private-lock_print.h @@ -15,7 +15,7 @@ extern "C" { /** * Print a r/w lock related error message, locking the print mutex during the print. * - * This will ignore F_signal and not print any messages, if passed. + * This will ignore F_interrupt and not print any messages, if passed. * * @param print * Designates how printing is to be performed. diff --git a/level_3/controller/c/private-process.c b/level_3/controller/c/private-process.c index d5bb3dd..5f9dfc9 100644 --- a/level_3/controller/c/private-process.c +++ b/level_3/controller/c/private-process.c @@ -36,30 +36,17 @@ extern "C" { f_status_t status = F_none; - if (status == F_signal || F_status_is_error(status)) { - controller_lock_print_error_critical(global.main->error, F_status_set_fine(status), F_true, global.thread); - - return status; - } - if (controller_process_find(action, alias, global.thread->processs, id) == F_false) { f_thread_unlock(&global.thread->lock.process); status = controller_lock_write(is_normal, global.thread, &global.thread->lock.process); - if (status == F_signal || F_status_is_error(status)) { + if (F_status_is_error(status)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status), F_false, global.thread); - - const f_status_t status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process); - - if (status_lock == F_signal || F_status_is_error(status_lock)) { - return F_status_set_error(F_lock); - } - - return status; } - - status = controller_processs_increase(&global.thread->processs); + else { + status = controller_processs_increase(&global.thread->processs); + } if (F_status_is_error_not(status) && global.thread->processs.array[global.thread->processs.used]) { @@ -67,46 +54,38 @@ extern "C" { status = controller_lock_write(is_normal, global.thread, &process->lock); - if (status == F_signal || F_status_is_error(status)) { + if (F_status_is_error(status)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status), F_false, global.thread); - - f_thread_unlock(&global.thread->lock.process); - - const f_status_t status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process); - - if (status_lock == F_signal || F_status_is_error(status_lock)) { - return F_status_set_error(F_lock); - } - - return status; } + else { + process->action = action; + process->rule.alias.used = 0; - process->action = action; - process->rule.alias.used = 0; - - status = f_string_dynamic_append(alias, &process->rule.alias); - - if (F_status_is_error_not(status)) { - status = f_string_dynamic_terminate_after(&process->rule.alias); + status = f_string_dynamic_append(alias, &process->rule.alias); if (F_status_is_error_not(status)) { - process->id = global.thread->processs.used++; - status = F_none; + status = f_string_dynamic_terminate_after(&process->rule.alias); + + if (F_status_is_error_not(status)) { + process->id = global.thread->processs.used++; + status = F_none; - if (id) { - *id = process->id; + if (id) { + *id = process->id; + } } } - } - f_thread_unlock(&process->lock); + f_thread_unlock(&process->lock); + } } f_thread_unlock(&global.thread->lock.process); + // The read lock must be restored on return. const f_status_t status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { return F_status_set_error(F_lock); } } @@ -129,7 +108,7 @@ extern "C" { f_status_t controller_process_wait(const controller_global_t global, controller_process_t *process) { if (!controller_thread_is_enabled_process(process, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } struct timespec time; @@ -160,16 +139,14 @@ extern "C" { f_thread_mutex_unlock(&process->wait_lock); if (!controller_thread_is_enabled_process(process, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } - if (F_status_is_error(status)) { - break; - } + if (F_status_is_error(status)) break; status_lock = controller_lock_read_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); break; @@ -180,7 +157,8 @@ extern "C" { return F_none; } - else if (status != F_time) { + + if (status != F_time) { // move up the wait timer after a trigger was received. if (count < controller_thread_wait_timeout_2_before_d) { diff --git a/level_3/controller/c/private-process.h b/level_3/controller/c/private-process.h index 795dd1a..c4345f4 100644 --- a/level_3/controller/c/private-process.h +++ b/level_3/controller/c/private-process.h @@ -126,7 +126,8 @@ extern "C" { * * @return * F_none on success. - * F_signal on success and signal found. + * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * * Success from: f_thread_condition_wait_timed(). * diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index ebce3ff..ab11d7d 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -1102,7 +1102,7 @@ extern "C" { for (j = 0; j < process->rule.items.array[i].actions.used; ++j) { if (!controller_thread_is_enabled_process(process, global.thread)) { - status = F_signal; + status = F_status_set_error(F_interrupt); break; } @@ -1125,7 +1125,7 @@ extern "C" { status = controller_rule_execute_foreground(process->rule.items.array[i].type, 0, process->rule.items.array[i].actions.array[j].parameters, options, &execute_set, process); - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break; if (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) { @@ -1135,7 +1135,7 @@ extern "C" { break; } // for - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status)) { process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure); @@ -1155,7 +1155,7 @@ extern "C" { status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.script.used ? process->rule.script.string : controller_default_program_script_s, arguments_none, options, &execute_set, process); - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break; if (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) { @@ -1165,7 +1165,7 @@ extern "C" { break; } // for - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status)) { process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure); @@ -1184,7 +1184,7 @@ extern "C" { status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, 0, process->rule.items.array[i].actions.array[j].parameters, options, process->rule.items.array[i].with, &execute_set, process); - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break; if (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) { @@ -1194,7 +1194,7 @@ extern "C" { break; } // for - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status)) { process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure); @@ -1222,7 +1222,7 @@ extern "C" { status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.script.used ? process->rule.script.string : controller_default_program_script_s, arguments_none, options, process->rule.items.array[i].with, &execute_set, process); - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break; if (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) { @@ -1232,7 +1232,7 @@ extern "C" { break; } // for - if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break; if (F_status_is_error(status)) { process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure); @@ -1271,7 +1271,7 @@ extern "C" { } } // for - if (status == F_child || status == F_signal || F_status_is_error(status) && !(options & controller_process_option_simulate_d)) { + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_is_error(status) && !(options & controller_process_option_simulate_d)) { break; } } // for @@ -1282,7 +1282,7 @@ extern "C" { if (F_status_set_fine(status) == F_lock) { status = controller_lock_read(process, global.thread, &process->lock); - if (status == F_signal || F_status_is_error(status)) { + if (F_status_is_error(status)) { return F_status_set_error(F_lock); } @@ -1290,7 +1290,7 @@ extern "C" { } if (!controller_thread_is_enabled_process(process, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } if (status == F_child || F_status_is_error(status)) { @@ -1336,9 +1336,9 @@ extern "C" { { f_array_length_t i = 0; - for (; i < process->childs.used && process->childs.array[i]; ++i) { - // do nothing - } // for + while (i < process->childs.used && process->childs.array[i]) { + ++i; + } // while child = &process->childs.array[i]; @@ -1377,16 +1377,16 @@ extern "C" { controller_unlock_print_flush(main->output.to, thread); } - // sleep for less than a second to better show simulation of synchronous vs asynchronous. + // Sleep for less than a second to better show simulation of synchronous vs asynchronous. { const struct timespec delay = controller_time_milliseconds(controller_thread_simulation_timeout_d); if (controller_time_sleep_nanoseconds(main, (controller_setting_t *) process->main_setting, delay) == -1) { - status = F_signal; + status = F_status_set_error(F_interrupt); } } - if (status != F_signal) { + if (F_status_set_fine(status) != F_interrupt) { const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0); const f_string_statics_t simulated_arguments = f_string_statics_t_initialize; fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program); @@ -1406,10 +1406,10 @@ extern "C" { status_lock = controller_lock_write_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_false, thread); - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { status = controller_lock_read_process(process, thread, &process->lock); if (status == F_none) { @@ -1420,26 +1420,26 @@ extern "C" { return F_status_set_error(F_lock); } - // assign the child process id to allow for the cancel process to send appropriate termination signals to the child process. + // Assign the child process id to allow for the cancel process to send appropriate termination signals to the child process. *child = id_child; f_thread_unlock(&process->lock); status_lock = controller_lock_read_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_true, thread); } - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { - // have the parent wait for the child process to finish. + // Have the parent wait for the child process to finish. waitpid(id_child, &result.status, 0); } - if (status_lock == F_signal || !controller_thread_is_enabled_process(process, thread)) { + if (F_status_set_fine(status_lock) == F_interrupt || !controller_thread_is_enabled_process(process, thread)) { if (status_lock == F_none) { - return F_signal; + return F_status_set_error(F_interrupt); } return F_status_set_error(F_lock); @@ -1451,10 +1451,10 @@ extern "C" { status_lock = controller_lock_write_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_false, thread); - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { status = controller_lock_read_process(process, thread, &process->lock); if (status == F_none) { @@ -1474,7 +1474,7 @@ extern "C" { status_lock = controller_lock_read_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_true, thread); return F_status_set_error(F_lock); @@ -1491,7 +1491,7 @@ extern "C" { main->child = result.status; if (!controller_thread_is_enabled_process(process, thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } @@ -1506,7 +1506,7 @@ extern "C" { } } - if (status == F_child || status == F_signal) { + if (status == F_child || F_status_set_fine(status) == F_interrupt) { return status; } @@ -1560,9 +1560,9 @@ extern "C" { { f_array_length_t i = 0; - for (; i < process->childs.used && process->childs.array[i]; ++i) { - // do nothing - } // for + while (i < process->childs.used && process->childs.array[i]) { + ++i; + } // while child = &process->childs.array[i]; @@ -1571,7 +1571,7 @@ extern "C" { } for (i = 0; i < process->path_pids.used && process->path_pids.array[i].used; ++i) { - // do nothing + // Do nothing. } // for child_pid_file = &process->path_pids.array[i]; @@ -1633,16 +1633,16 @@ extern "C" { controller_unlock_print_flush(main->error.to, thread); } - // sleep for less than a second to better show simulation of synchronous vs asynchronous. + // Sleep for less than a second to better show simulation of synchronous vs asynchronous. { const struct timespec delay = controller_time_milliseconds(controller_thread_simulation_timeout_d); if (controller_time_sleep_nanoseconds(main, (controller_setting_t *) process->main_setting, delay) == -1) { - status = F_signal; + status = F_status_set_error(F_interrupt); } } - if (status != F_signal) { + if (F_status_set_fine(status) != F_interrupt) { const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0); const f_string_statics_t simulated_arguments = f_string_statics_t_initialize; fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program); @@ -1662,10 +1662,10 @@ extern "C" { status_lock = controller_lock_write_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_false, thread); - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { status = controller_lock_read_process(process, thread, &process->lock); if (status == F_none) { @@ -1676,29 +1676,29 @@ extern "C" { return F_status_set_error(F_lock); } - // assign the child process id to allow for the cancel process to send appropriate termination signals to the child process. + // Assign the child process id to allow for the cancel process to send appropriate termination signals to the child process. *child = id_child; f_thread_unlock(&process->lock); status_lock = controller_lock_read_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_true, thread); } - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { - // the child process should perform the change into background, therefore it is safe to wait for the child to exit (another process is spawned). + // The child process should perform the change into background, therefore it is safe to wait for the child to exit (another process is spawned). waitpid(id_child, &result.status, 0); } if (!controller_thread_is_enabled_process(process, thread)) { if (status_lock == F_none) { - return F_signal; + return F_status_set_error(F_interrupt); } - return F_signal; + return F_status_set_error(F_lock); } if (status_lock == F_none) { @@ -1707,10 +1707,10 @@ extern "C" { status_lock = controller_lock_write_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_false, thread); - if (status_lock != F_signal) { + if (F_status_set_fine(status_lock) != F_interrupt) { status = controller_lock_read_process(process, thread, &process->lock); if (status == F_none) { @@ -1723,14 +1723,14 @@ extern "C" { process->result = result.status; - // remove the pid now that waidpid() has returned. + // Remove the pid now that waidpid() has returned. *child = 0; f_thread_unlock(&process->lock); status_lock = controller_lock_read_process(process, thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(main->error, F_status_set_fine(status_lock), F_true, thread); return F_status_set_error(F_lock); @@ -1747,7 +1747,7 @@ extern "C" { main->child = result.status; if (!controller_thread_is_enabled_process(process, thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } @@ -1762,7 +1762,7 @@ extern "C" { } } - if (status == F_child || status == F_signal) { + if (status == F_child || F_status_set_fine(status) == F_interrupt) { return status; } @@ -2359,7 +2359,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.process); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); } else { @@ -2368,7 +2368,7 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_lock) { if (!controller_thread_is_enabled_process_type(process->type, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } else { @@ -2397,7 +2397,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &dependency->active); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); status = F_false; @@ -2410,7 +2410,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); status = F_false; @@ -2463,7 +2463,7 @@ extern "C" { else if (found) { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); found = F_false; @@ -2485,7 +2485,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &dependency->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); status = status_lock; @@ -2502,7 +2502,7 @@ extern "C" { else { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); f_thread_unlock(&dependency->lock); @@ -2523,10 +2523,10 @@ extern "C" { options_process |= controller_process_option_validate_d; } - // synchronously execute dependency. + // Synchronously execute dependency. status = controller_rule_process_begin(0, alias_other, process->action, options_process, process->type, process->stack, global, dependency->cache); - if (status == F_child || status == F_signal) { + if (status == F_child || F_status_set_fine(status) == F_interrupt) { f_thread_unlock(&dependency->active); break; @@ -2574,15 +2574,15 @@ extern "C" { break; } - if (status_lock != F_signal && F_status_is_error_not(status_lock)) { + if (F_status_is_error_not(status_lock)) { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); } } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { if (F_status_is_error(status_lock)) { controller_rule_item_print_error_need_want_wish(global.main->error, strings[i], alias_other_buffer, "due to lock failure"); } @@ -2631,25 +2631,25 @@ extern "C" { } } // for - if (status == F_child || status == F_signal) break; + if (status == F_child || F_status_set_fine(status) == F_interrupt) break; if (F_status_is_error(status) && !(process->options & controller_process_option_simulate_d)) break; } // for } - if (status == F_child || status == F_signal) { + if (status == F_child || F_status_set_fine(status) == F_interrupt) { return status; } if (!controller_thread_is_enabled_process(process, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } if ((process->options & controller_process_option_wait_d) && F_status_is_error_not(status) && (process->options & controller_process_option_validate_d)) { status_lock = controller_rule_wait_all_process_type(process->type, global, F_false, process); - if (status_lock == F_signal) { - return F_signal; + if (F_status_set_fine(status_lock) == F_interrupt) { + return status_lock; } } @@ -2711,7 +2711,7 @@ extern "C" { if (F_status_is_error_not(status)) { status = controller_rule_execute(process->action, process->options, global, process); - if (status == F_child || status == F_signal || status == F_status_set_error(F_lock)) { + if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) { return status; } @@ -2727,13 +2727,13 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); - if (status_lock != F_signal) { + if (F_status_set_fine(status) != F_interrupt) { status = controller_lock_read_process(process, global.thread, &process->lock); - if (status != F_signal && F_status_is_error_not(status)) { + if (F_status_is_error_not(status)) { return status_lock; } } @@ -2750,14 +2750,14 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&process->lock); status = controller_lock_read_process(process, global.thread, &process->lock); - if (status != F_signal && F_status_is_error_not(status)) { + if (F_status_is_error_not(status)) { return status_lock; } @@ -2792,7 +2792,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); return F_status_set_error(F_lock); @@ -2806,7 +2806,7 @@ extern "C" { f_status_t controller_rule_process_begin(const uint8_t options_force, const f_string_static_t alias_rule, const uint8_t action, const uint8_t options, const uint8_t type, const f_array_lengths_t stack, const controller_global_t global, const controller_cache_t cache) { if (!controller_thread_is_enabled_process_type(type, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } f_status_t status = F_none; @@ -2816,7 +2816,7 @@ extern "C" { status = controller_lock_read_process_type(type, global.thread, &global.thread->lock.process); - if (status == F_signal || F_status_is_error(status)) { + if (F_status_is_error(status)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status), F_true, global.thread); return status; @@ -2846,7 +2846,7 @@ extern "C" { status = controller_lock_read_process_type(type, global.thread, &process->active); - if (status == F_signal || F_status_is_error(status)) { + if (F_status_is_error(status)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status), F_true, global.thread); controller_rule_item_print_error(global.main->error, cache.action, F_false, F_status_set_fine(status), global.thread); @@ -2857,7 +2857,7 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&process->active); @@ -2893,7 +2893,7 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&process->active); @@ -2984,7 +2984,7 @@ extern "C" { else { status = controller_rule_process_do(options_force, process); - if (status == F_child || status == F_signal) { + if (status == F_child || F_status_set_fine(status) == F_interrupt) { f_thread_unlock(&process->active); return status; @@ -2996,7 +2996,7 @@ extern "C" { { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&process->active); @@ -3040,7 +3040,7 @@ extern "C" { if (options_force & controller_process_option_asynchronous_d) { status_lock = controller_lock_read_process(process, global.thread, &process->active); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); return status_lock; @@ -3049,7 +3049,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); if (options_force & controller_process_option_asynchronous_d) { @@ -3067,7 +3067,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); f_thread_unlock(&process->lock); @@ -3084,7 +3084,7 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&global.thread->lock.rule); @@ -3104,7 +3104,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); f_thread_unlock(&global.thread->lock.rule); @@ -3162,7 +3162,7 @@ extern "C" { f_thread_unlock(&process->active); } - return F_signal; + return F_status_set_error(F_interrupt); } if (F_status_is_error_not(status)) { @@ -3176,7 +3176,7 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); if (options_force & controller_process_option_asynchronous_d) { @@ -3192,7 +3192,7 @@ extern "C" { status_lock = controller_lock_read_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); if (options_force & controller_process_option_asynchronous_d) { @@ -3236,7 +3236,7 @@ extern "C" { status_lock = controller_lock_write_process(process, global.thread, &global.thread->lock.rule); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); if (F_status_set_fine(status) != F_lock) { @@ -3262,17 +3262,17 @@ extern "C" { f_thread_unlock(&process->lock); } - if (status == F_signal || F_status_set_fine(status) == F_lock && !controller_thread_is_enabled_process(process, global.thread)) { + if (F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock && !controller_thread_is_enabled_process(process, global.thread)) { if (options_force & controller_process_option_asynchronous_d) { f_thread_unlock(&process->active); } - return F_signal; + return F_status_set_error(F_interrupt); } status_lock = controller_lock_write_process(process, global.thread, &process->lock); - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); if (options_force & controller_process_option_asynchronous_d) { @@ -3306,7 +3306,7 @@ extern "C" { return status; } - return F_signal; + return F_status_set_error(F_interrupt); } #endif // _di_controller_rule_process_do_ @@ -5884,7 +5884,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); return status_lock; @@ -5931,7 +5931,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process); } - if (status_lock == F_signal || F_status_is_error(status_lock)) break; + if (F_status_is_error(status_lock)) break; if (!process_list[i]) { f_thread_unlock(&global.thread->lock.process); @@ -5946,7 +5946,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->active); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { f_thread_unlock(&global.thread->lock.process); break; @@ -5963,7 +5963,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.rule); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { f_thread_unlock(&process_list[i]->active); break; @@ -6010,7 +6010,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { f_thread_unlock(&process_list[i]->active); break; @@ -6037,7 +6037,7 @@ extern "C" { status_lock = controller_lock_write(is_normal, global.thread, &process_list[i]->lock); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_false, global.thread); f_thread_unlock(&process_list[i]->active); @@ -6068,7 +6068,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->active); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { f_thread_unlock(&process_list[i]->lock); break; @@ -6084,7 +6084,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock); } - if (status_lock == F_signal || F_status_is_error(status_lock)) break; + if (F_status_is_error(status_lock)) break; } if (process_list[i]->options & controller_process_option_require_d) { @@ -6114,7 +6114,7 @@ extern "C" { status = controller_process_wait(global, process_list[i]); - if (status == F_signal) { + if (F_status_set_fine(status) == F_interrupt) { f_thread_unlock(&process_list[i]->active); break; @@ -6127,7 +6127,7 @@ extern "C" { status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock); } - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { f_thread_unlock(&process_list[i]->active); break; @@ -6153,10 +6153,10 @@ extern "C" { f_thread_unlock(&process_list[i]->active); - if (status == F_signal || F_status_set_fine(status) == F_require) break; + if (F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_require) break; } // for - if (status_lock == F_signal || F_status_is_error(status_lock)) { + if (F_status_is_error(status_lock)) { controller_lock_print_error_critical(global.main->error, F_status_set_fine(status_lock), F_true, global.thread); return status_lock; @@ -6164,16 +6164,16 @@ extern "C" { if (caller) { if (!controller_thread_is_enabled_process(caller, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } else { if (!controller_thread_is_enabled(is_normal, global.thread)) { - return F_signal; + return F_status_set_error(F_interrupt); } } - if (status == F_signal || F_status_set_fine(status) == F_require) { + if (F_status_set_fine(status) == F_require) { return status; } diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index fa2f4e4..23ae316 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -222,10 +222,10 @@ extern "C" { * @return * F_none on success. * F_child on child process exiting. - * F_signal on (exit) signal received. * F_ignore if the rule is unknown and nothing can be done. * * F_failure (with error bit) if failed to execute. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning. * * On success and the rule is run synchronously, then the individual status for the rule is set to F_complete. @@ -258,8 +258,8 @@ extern "C" { * @return * F_none on success. * F_child on child process exiting. - * F_signal on (exit) signal received. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning. * * Errors (with error bit) from: fll_execute_program(). @@ -299,10 +299,10 @@ extern "C" { * @return * F_none on success. * F_child on child process exiting. - * F_signal on (exit) signal received. * - * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning. * F_file_found (with error bit) if the PID file already exists. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning. * * Errors (with error bit) from: fll_execute_program(). * @@ -327,7 +327,7 @@ extern "C" { * 0 to designate do not re-run. * -1 to designate an error from nanosleep(), with errno set to values like: * - EFAULT: Designates that there was a problem copying information from user space. - * - EINTR: Consider this having returned F_signal. + * - EINTR: Consider this having returned F_interrupt. * - EINVAL: Consider this having returned F_status_set_error(F_parameter); * -2 to designate exit due to signal/disabled thread. */ @@ -501,9 +501,9 @@ extern "C" { * @return * F_none on success. * F_child on child process exiting. - * F_signal on (exit) signal received. * F_failure on execution failure. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning. * * Errors (with error bit) from: controller_lock_read(). @@ -540,9 +540,9 @@ extern "C" { * @return * F_none on success. * F_busy on success and the process was found to already be running (nothing to do). - * F_signal on (exit) signal received. * * F_found_not (with error bit) if unable to for a process for the given rule id. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * F_recurse (with error bit) on recursion error (the process is already on the process stack). * * Status from: controller_rule_process(). @@ -577,9 +577,9 @@ extern "C" { * F_none on success. * F_found on the process was found to already be running (nothing to do). * F_process_not if the process was not executed because it is a "consider" Action. - * F_signal on (exit) signal received. * * F_found_not (with error bit) if unable to for a process for the given rule id. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. * * Status from: controller_rule_process(). * @@ -652,6 +652,7 @@ extern "C" { * * @return * F_none on success. + * * F_valid_not (with error bit) on failure due to invalid value. * * Errors (with error bit) from: fl_conversion_string_to_number_signed(). @@ -685,6 +686,7 @@ extern "C" { * * @return * F_none on success. + * * F_valid_not (with error bit) on success but there were one or more invalid settings encountered. * * Errors (with error bit) from: f_string_dynamic_partial_append_nulless(). @@ -748,12 +750,12 @@ extern "C" { * Failure to set this to the process on a thread running/executing a process will likely result in a deadlock. * * @return - * F_none on success. - * F_data_not on success and nothing to do. - * F_require on success, but a required rule has not been run yet. - * F_signal on (exit) signal received. + * F_none on success. + * F_data_not on success and nothing to do. + * F_require on success, but a required rule has not been run yet. * - * F_require (with error bit set) if a required process is in failed status when required is TRUE. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * F_require (with error bit set) if a required process is in failed status when required is TRUE. */ #ifndef _di_controller_rule_wait_all_ extern f_status_t controller_rule_wait_all(const bool is_normal, const controller_global_t global, const bool required, controller_process_t *caller) F_attribute_visibility_internal_d; @@ -775,7 +777,6 @@ extern "C" { * Failure to set this to the process on a thread running/executing a process will likely result in a deadlock. * * @return - * * Success from controller_rule_wait_all(). * * Errors (with error bit) from: controller_rule_wait_all(). diff --git a/level_3/controller/c/private-thread.c b/level_3/controller/c/private-thread.c index f37db17..f0df2a8 100644 --- a/level_3/controller/c/private-thread.c +++ b/level_3/controller/c/private-thread.c @@ -253,7 +253,7 @@ extern "C" { } // only make the rule and control threads available once any/all pre-processing and are completed. - if (F_status_is_error_not(status) && status != F_signal && status != F_failure && status != F_child && thread.enabled == controller_thread_enabled) { + if (F_status_is_error_not(status) && status != F_failure && status != F_child && thread.enabled == controller_thread_enabled) { if (main->parameters[controller_parameter_validate].result == f_console_result_none) { // wait for the entry thread to complete before starting the rule thread. @@ -293,7 +293,7 @@ extern "C" { return F_child; } - if (F_status_is_error_not(status) && status != F_signal && status != F_failure && main->parameters[controller_parameter_validate].result == f_console_result_none && controller_thread_is_enabled(F_true, &thread)) { + if (F_status_is_error_not(status) && status != F_failure && main->parameters[controller_parameter_validate].result == f_console_result_none && controller_thread_is_enabled(F_true, &thread)) { if (setting->mode == controller_setting_mode_service) { controller_thread_join(&thread.id_signal); @@ -324,8 +324,14 @@ extern "C" { return F_status_set_error(F_failure); } - if (status == F_signal) { - return F_signal; + if (F_status_set_fine(status) == F_interrupt) { + controller_print_signal_received(main, thread.signal); + + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + + return F_status_set_error(F_interrupt); } return F_none; diff --git a/level_3/controller/c/private-thread.h b/level_3/controller/c/private-thread.h index f297e1f..713c343 100644 --- a/level_3/controller/c/private-thread.h +++ b/level_3/controller/c/private-thread.h @@ -83,16 +83,16 @@ extern "C" { * Start all threads, wait on threads, and handle requests. * * @param main - * The main data. + * The main program data. * @param setting * The controller settings data. * * @return * F_none on success. * F_child on child process exiting. - * F_signal on signal received. * * F_failure (with error bit) on any failure. + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. */ #ifndef _di_controller_thread_main_ extern f_status_t controller_thread_main(controller_main_t *main, controller_setting_t *setting) F_attribute_visibility_internal_d; diff --git a/level_3/controller/c/private-thread_entry.c b/level_3/controller/c/private-thread_entry.c index 21a38d7..e196952 100644 --- a/level_3/controller/c/private-thread_entry.c +++ b/level_3/controller/c/private-thread_entry.c @@ -25,14 +25,18 @@ extern "C" { *status = controller_entry_read(F_true, *entry->global, cache); - if (F_status_is_error(*status)) { + + if (F_status_set_fine(*status) == F_interrupt) { + entry->setting->ready = controller_setting_ready_abort; + } + else if (F_status_is_error(*status)) { entry->setting->ready = controller_setting_ready_fail; } - else if (*status != F_signal && *status != F_child) { + else if (*status != F_child) { *status = controller_entry_preprocess(F_true, *entry->global, cache); } - if (F_status_is_error_not(*status) && *status != F_signal && *status != F_child) { + if (F_status_is_error_not(*status) && *status != F_child) { if (main->parameters[controller_parameter_validate].result == f_console_result_none || main->parameters[controller_parameter_simulate].result == f_console_result_found) { if (entry->setting->entry.pid == controller_entry_pid_require && f_file_exists(entry->setting->path_pid.string) == F_true) { @@ -102,7 +106,7 @@ extern "C" { } } } - else if (*status == F_signal) { + else if (F_status_set_fine(*status) == F_interrupt) { entry->setting->ready = controller_setting_ready_abort; } else if (*status != F_child) { @@ -146,17 +150,20 @@ extern "C" { *status = controller_entry_read(F_false, *entry->global, cache); - if (F_status_is_error(*status)) { + if (F_status_set_fine(*status) == F_interrupt) { + entry->setting->ready = controller_setting_ready_abort; + } + else if (F_status_is_error(*status)) { entry->setting->ready = controller_setting_ready_fail; } else if (*status == F_file_found_not) { entry->setting->ready = controller_setting_ready_done; } - else if (*status != F_signal && *status != F_child) { + else if (*status != F_child) { *status = controller_entry_preprocess(F_false, *entry->global, cache); } - if (F_status_is_error_not(*status) && *status != F_signal && *status != F_child && *status != F_file_found_not) { + if (F_status_is_error_not(*status) && *status != F_child && *status != F_file_found_not) { if (main->parameters[controller_parameter_validate].result == f_console_result_none || main->parameters[controller_parameter_simulate].result == f_console_result_found) { *status = controller_entry_process(F_false, F_false, entry->global, cache); @@ -214,7 +221,7 @@ extern "C" { } } } - else if (*status == F_signal) { + else if (F_status_set_fine(*status) == F_interrupt) { entry->setting->ready = controller_setting_ready_abort; } else if (*status != F_child) { diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c index 3b510e7..e4cb8ae 100644 --- a/level_3/fake/c/fake.c +++ b/level_3/fake/c/fake.c @@ -82,7 +82,7 @@ extern "C" { #endif // _di_fake_print_help_ #ifndef _di_fake_main_ - f_status_t fake_main(const f_console_arguments_t arguments, fake_main_t *main) { + f_status_t fake_main(fake_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -94,7 +94,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fake_parameter_no_color, fake_parameter_light, fake_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -295,11 +295,11 @@ extern "C" { if (main->operation == fake_operation_build) { if (validate_parameter_directories) { - status = fake_validate_parameter_directories(arguments, *main); + status = fake_validate_parameter_directories(arguments, main); validate_parameter_directories = F_false; } - if (F_status_is_error_not(status) && status != F_signal) { + if (F_status_is_error_not(status)) { f_string_static_t stub = f_string_static_t_initialize; status = fake_build_operate(stub, main); @@ -307,21 +307,21 @@ extern "C" { } else if (main->operation == fake_operation_clean) { if (validate_parameter_directories) { - status = fake_validate_parameter_directories(arguments, *main); + status = fake_validate_parameter_directories(arguments, main); validate_parameter_directories = F_false; } - if (F_status_is_error_not(status) && status != F_signal) { - status = fake_clean_operate(*main); + if (F_status_is_error_not(status)) { + status = fake_clean_operate(main); } } else if (main->operation == fake_operation_make) { if (validate_parameter_directories) { - status = fake_validate_parameter_directories(arguments, *main); + status = fake_validate_parameter_directories(arguments, main); validate_parameter_directories = F_false; } - if (F_status_is_error_not(status) && status != F_signal) { + if (F_status_is_error_not(status)) { status = fake_make_operate(main); if (status == F_child) { @@ -330,10 +330,14 @@ extern "C" { } } else if (main->operation == fake_operation_skeleton) { - status = fake_skeleton_operate(*main); + status = fake_skeleton_operate(main); } - if (status == F_signal || status == F_child || fake_signal_received(*main)) { + if (status == F_child) { + break; + } + else if (F_status_set_fine(status) == F_interrupt || fake_signal_received(main)) { + status = F_status_set_error(F_interrupt); break; } else if (F_status_is_error(status)) { @@ -351,10 +355,13 @@ extern "C" { } } // for - // ensure a newline is always put at the end of the program execution, unless in quiet mode. if (main->error.verbosity != f_console_verbosity_quiet) { - if (F_status_is_error(status) || status == F_signal) { - fll_print_character(f_string_eol_s[0], main->error.to.stream); + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_terminated(f_string_eol_s, main->output.to.stream); } else if (status != F_child) { fll_print_format("%cAll operations complete.%c%c", main->output.to.stream, f_string_eol_s[0], f_string_eol_s[0], f_string_eol_s[0]); @@ -370,14 +377,16 @@ extern "C" { } fake_main_delete(main); + return status; } #endif // _di_fake_main_ #ifndef _di_fake_main_delete_ - f_status_t fake_main_delete(fake_main_t *main) { + f_status_t fake_main_delete(fake_main_t * const main) { for (f_array_length_t i = 0; i < fake_total_parameters_d; ++i) { + macro_f_array_lengths_t_delete_simple(main->parameters[i].locations); macro_f_array_lengths_t_delete_simple(main->parameters[i].locations_sub); macro_f_array_lengths_t_delete_simple(main->parameters[i].values); diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index 2ef527e..d081bde 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -393,11 +393,12 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + uint8_t operation; mode_t umask; int child; - f_signal_t signal; f_string_dynamics_t define; f_string_dynamic_t fakefile; @@ -463,10 +464,10 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ 0, \ 0, \ 0, \ - f_signal_t_initialize, \ f_string_dynamics_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamics_t_initialize, \ @@ -537,26 +538,29 @@ extern "C" { * * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. - * F_status if one of the above signals is received. + * F_child if this is a child process returning. + * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. * * Status codes (with error bit) are returned on any problem. * * @see fake_main_delete() */ #ifndef _di_fake_main_ - extern f_status_t fake_main(const f_console_arguments_t arguments, fake_main_t *main); + extern f_status_t fake_main(fake_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fake_main_ /** @@ -565,7 +569,7 @@ extern "C" { * Be sure to call this after executing fake_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -575,7 +579,7 @@ extern "C" { * @see fake_main() */ #ifndef _di_fake_main_delete_ - extern f_status_t fake_main_delete(fake_main_t *main); + extern f_status_t fake_main_delete(fake_main_t * const main); #endif // _di_fake_main_delete_ #ifdef __cplusplus diff --git a/level_3/fake/c/main.c b/level_3/fake/c/main.c index cae110f..6ae5366 100644 --- a/level_3/fake/c/main.c +++ b/level_3/fake/c/main.c @@ -18,24 +18,27 @@ int main(const int argc, const f_string_t *argv) { const f_console_arguments_t arguments = { argc, argv }; fake_main_t data = fake_main_t_initialize; - f_status_t status = F_none; - f_signal_set_empty(&data.signal.set); - f_signal_set_add(F_signal_abort, &data.signal.set); - f_signal_set_add(F_signal_hangup, &data.signal.set); - f_signal_set_add(F_signal_interrupt, &data.signal.set); - f_signal_set_add(F_signal_quit, &data.signal.set); - f_signal_set_add(F_signal_termination, &data.signal.set); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); - status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); - if (F_status_is_error_not(status)) { - status = f_signal_open(&data.signal); + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); - // if there is an error opening a signal descriptor, then do not handle signals. - if (F_status_is_error(status)) { - f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); - f_signal_close(&data.signal); + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } } } @@ -45,13 +48,13 @@ int main(const int argc, const f_string_t *argv) { // restore umask. umask(data.umask); - status = fake_main(arguments, &data); + const f_status_t status = fake_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index 86fa951..18e9b1a 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -10,31 +10,31 @@ extern "C" { #endif #ifndef _di_fake_build_arguments_standard_add_ - void fake_build_arguments_standard_add(const fake_main_t main, const fake_build_data_t data_build, const bool is_shared, const bool is_library, f_string_dynamics_t *arguments, f_status_t *status) { + void fake_build_arguments_standard_add(fake_main_t * const main, const fake_build_data_t data_build, const bool is_shared, const bool is_library, f_string_dynamics_t *arguments, f_status_t *status) { if (F_status_is_error(*status)) return; - f_array_length_t build_libraries_length = fake_build_parameter_library_link_path_s_length + main.path_build_libraries_shared.used; + f_array_length_t build_libraries_length = fake_build_parameter_library_link_path_s_length + main->path_build_libraries_shared.used; char build_libraries[build_libraries_length + 1]; memcpy(build_libraries, fake_build_parameter_library_link_path_s, fake_build_parameter_library_link_path_s_length); if (is_shared) { - memcpy(build_libraries + fake_build_parameter_library_link_path_s_length, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); + memcpy(build_libraries + fake_build_parameter_library_link_path_s_length, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); } else { - memcpy(build_libraries + fake_build_parameter_library_link_path_s_length, main.path_build_libraries_static.string, main.path_build_libraries_static.used); + memcpy(build_libraries + fake_build_parameter_library_link_path_s_length, main->path_build_libraries_static.string, main->path_build_libraries_static.used); } build_libraries[build_libraries_length] = 0; - f_array_length_t build_includes_length = fake_build_parameter_library_include_s_length + main.path_build_includes.used; + f_array_length_t build_includes_length = fake_build_parameter_library_include_s_length + main->path_build_includes.used; char build_includes[build_includes_length + 1]; memcpy(build_includes, fake_build_parameter_library_include_s, fake_build_parameter_library_include_s_length); - memcpy(build_includes + fake_build_parameter_library_include_s_length, main.path_build_includes.string, main.path_build_includes.used); + memcpy(build_includes + fake_build_parameter_library_include_s_length, main->path_build_includes.string, main->path_build_includes.used); const f_string_t values[] = { build_libraries, @@ -54,16 +54,16 @@ extern "C" { if (F_status_is_error(*status)) break; } // for - if (main.path_work.used) { + if (main->path_work.used) { f_array_length_t length = 0; if (F_status_is_error_not(*status)) { - length = fake_build_parameter_library_include_s_length + main.path_work_includes.used; + length = fake_build_parameter_library_include_s_length + main->path_work_includes.used; char string[length + 1]; memcpy(string, fake_build_parameter_library_include_s, fake_build_parameter_library_include_s_length); - memcpy(string + fake_build_parameter_library_include_s_length, main.path_work_includes.string, main.path_work_includes.used); + memcpy(string + fake_build_parameter_library_include_s_length, main->path_work_includes.string, main->path_work_includes.used); string[length] = 0; @@ -71,12 +71,12 @@ extern "C" { } if (data_build.setting.search_shared && (is_shared || !data_build.setting.search_exclusive) && F_status_is_error_not(*status)) { - length = fake_build_parameter_library_link_path_s_length + main.path_work_libraries_shared.used; + length = fake_build_parameter_library_link_path_s_length + main->path_work_libraries_shared.used; char string[length + 1]; memcpy(string, fake_build_parameter_library_link_path_s, fake_build_parameter_library_link_path_s_length); - memcpy(string + fake_build_parameter_library_link_path_s_length, main.path_work_libraries_shared.string, main.path_work_libraries_shared.used); + memcpy(string + fake_build_parameter_library_link_path_s_length, main->path_work_libraries_shared.string, main->path_work_libraries_shared.used); string[length] = 0; @@ -84,12 +84,12 @@ extern "C" { } if (data_build.setting.search_static && (!is_shared || !data_build.setting.search_exclusive) && F_status_is_error_not(*status)) { - length = fake_build_parameter_library_link_path_s_length + main.path_work_libraries_static.used; + length = fake_build_parameter_library_link_path_s_length + main->path_work_libraries_static.used; char string[length + 1]; memcpy(string, fake_build_parameter_library_link_path_s, fake_build_parameter_library_link_path_s_length); - memcpy(string + fake_build_parameter_library_link_path_s_length, main.path_work_libraries_static.string, main.path_work_libraries_static.used); + memcpy(string + fake_build_parameter_library_link_path_s_length, main->path_work_libraries_static.string, main->path_work_libraries_static.used); string[length] = 0; @@ -273,22 +273,22 @@ extern "C" { } } - for (i = 0; i < main.define.used && F_status_is_error_not(*status); ++i) { + for (i = 0; i < main->define.used && F_status_is_error_not(*status); ++i) { - if (!main.define.array[i].used) continue; + if (!main->define.array[i].used) continue; - *status = fll_execute_arguments_add(main.define.array[i].string, main.define.array[i].used, arguments); + *status = fll_execute_arguments_add(main->define.array[i].string, main->define.array[i].used, arguments); } // for } #endif // _di_fake_build_arguments_standard_add_ #ifndef _di_fake_build_copy_ - void fake_build_copy(const fake_main_t main, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_array_length_t preserve, f_status_t *status) { + void fake_build_copy(fake_main_t * const main, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_array_length_t preserve, f_status_t *status) { if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return; } @@ -298,14 +298,14 @@ extern "C" { f_string_dynamic_t destination_file = f_string_dynamic_t_initialize; f_string_dynamic_t destination_directory = f_string_dynamic_t_initialize; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Copying %S.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, label, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Copying %S.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, label, main->context.set.important, f_string_eol_s[0]); } macro_f_string_dynamic_t_resize(*status, path_source, source.used); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), " macro_f_string_dynamic_t_resize", F_true); + fll_error_print(main->error, F_status_set_fine(*status), " macro_f_string_dynamic_t_resize", F_true); macro_f_string_dynamic_t_delete_simple(path_source); return; @@ -315,12 +315,12 @@ extern "C" { fl_directory_recurse_t recurse = fl_directory_recurse_t_initialize; - if (main.error.verbosity == f_console_verbosity_verbose) { - recurse.output.stream = main.output.to.stream; - recurse.output.id = main.output.to.id; - recurse.output.flag = main.output.to.flag; - recurse.output.size_read = main.output.to.size_read; - recurse.output.size_write = main.output.to.size_write; + if (main->error.verbosity == f_console_verbosity_verbose) { + recurse.output.stream = main->output.to.stream; + recurse.output.id = main->output.to.id; + recurse.output.flag = main->output.to.flag; + recurse.output.size_read = main->output.to.size_read; + recurse.output.size_write = main->output.to.size_write; recurse.verbose = fake_verbose_print_copy; } @@ -335,68 +335,63 @@ extern "C" { *status = f_string_dynamic_append_nulless(files.array[i], &path_source); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } *status = f_string_dynamic_terminate_after(&path_source); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } *status = f_directory_is(path_source.string); - if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - break; - } - if (*status == F_true) { destination_directory.used = 0; *status = f_string_dynamic_append(destination, &destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); break; } *status = f_file_name_base(path_source.string, path_source.used, &destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_base", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_base", F_true); break; } *status = f_string_dynamic_terminate_after(&destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } *status = fl_directory_copy(path_source.string, destination_directory.string, path_source.used, destination_directory.used, mode, recurse); if (F_status_is_error(*status)) { - if (main.error.verbosity == f_console_verbosity_verbose) { + if (main->error.verbosity == f_console_verbosity_verbose) { for (f_array_length_t j = 0; j < failures.used; ++j) { fake_print_error_build_operation_file(main, F_status_set_fine(*status), "fl_directory_copy", "copy directory", "to", path_source.string, destination_directory.string, F_true); } // for if (F_status_set_fine(*status) != F_failure) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_directory_copy", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_directory_copy", F_true); } break; } - else if (main.error.verbosity != f_console_verbosity_quiet) { + else if (main->error.verbosity != f_console_verbosity_quiet) { fake_print_error_build_operation_file(main, F_status_set_fine(*status), "fl_directory_copy", "copy directory", "to", path_source.string, destination_directory.string, F_true); } @@ -410,7 +405,7 @@ extern "C" { *status = f_string_dynamic_append_nulless(destination, &destination_file); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } @@ -418,35 +413,35 @@ extern "C" { *status = f_string_dynamic_append_nulless(destination, &destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } *status = f_file_name_directory(path_source.string + preserve, path_source.used - preserve, &destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_directory", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_directory", F_true); break; } *status = f_string_dynamic_terminate_after(&destination_directory); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } *status = fl_directory_create(destination_directory.string, destination_directory.used, F_file_mode_all_rwx_d); if (F_status_is_error(*status)) { - fll_error_file_print(main.error, F_status_set_fine(*status), "fl_directory_create", F_true, destination_directory.string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(*status), "fl_directory_create", F_true, destination_directory.string, "create", fll_error_file_type_directory); break; } *status = f_string_append(path_source.string + preserve, path_source.used - preserve, &destination_file); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } } @@ -454,7 +449,7 @@ extern "C" { *status = f_file_name_base(path_source.string, path_source.used, &destination_file); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_base", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_base", F_true); break; } } @@ -462,12 +457,12 @@ extern "C" { *status = f_string_dynamic_terminate_after(&destination_file); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } @@ -478,12 +473,12 @@ extern "C" { break; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Copied file '%Q' to '%Q'.%c", main.output.to.stream, path_source, destination_file, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Copied file '%Q' to '%Q'.%c", main->output.to.stream, path_source, destination_file, f_string_eol_s[0]); } } else if (F_status_is_error(*status)) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_directory_is", F_true, path_source.string, "create", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_directory_is", F_true, path_source.string, "create", fll_error_file_type_file); break; } @@ -502,23 +497,18 @@ extern "C" { #endif // _di_fake_build_copy_ #ifndef _di_fake_build_skeleton_ - void fake_build_skeleton(const fake_main_t main, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + void fake_build_skeleton(fake_main_t * const main, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) { if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return; - if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - return; - } - f_string_static_t path_headers = f_string_static_t_initialize; - f_array_length_t directory_headers_length = main.path_build_includes.used + data_build.setting.path_headers.used; + f_array_length_t directory_headers_length = main->path_build_includes.used + data_build.setting.path_headers.used; char directory_headers[directory_headers_length + 1]; if (data_build.setting.path_headers.used) { - memcpy(directory_headers, main.path_build_includes.string, main.path_build_includes.used); - memcpy(directory_headers + main.path_build_includes.used, data_build.setting.path_headers.string, data_build.setting.path_headers.used); + memcpy(directory_headers, main->path_build_includes.string, main->path_build_includes.used); + memcpy(directory_headers + main->path_build_includes.used, data_build.setting.path_headers.string, data_build.setting.path_headers.used); directory_headers[directory_headers_length] = 0; @@ -535,25 +525,25 @@ extern "C" { } const f_string_static_t *directorys[] = { - &main.path_build, - &main.path_build_documents, - &main.path_build_includes, - &main.path_build_libraries, - &main.path_build_libraries_script, - &main.path_build_libraries_shared, - &main.path_build_libraries_static, - &main.path_build_objects, - &main.path_build_programs, - &main.path_build_programs_script, - &main.path_build_programs_shared, - &main.path_build_programs_static, - &main.path_build_settings, - &main.path_build_stage, + &main->path_build, + &main->path_build_documents, + &main->path_build_includes, + &main->path_build_libraries, + &main->path_build_libraries_script, + &main->path_build_libraries_shared, + &main->path_build_libraries_static, + &main->path_build_objects, + &main->path_build_programs, + &main->path_build_programs_script, + &main->path_build_programs_shared, + &main->path_build_programs_static, + &main->path_build_settings, + &main->path_build_stage, &path_headers, }; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Creating base build directories.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Creating base build directories.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } for (uint8_t i = 0; i < 15; ++i) { @@ -561,7 +551,7 @@ extern "C" { if (!directorys[i]->used) continue; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return; } @@ -600,12 +590,12 @@ extern "C" { continue; } - fll_error_file_print(main.error, F_status_set_fine(*status), "f_directory_create", F_true, directorys[i]->string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_directory_create", F_true, directorys[i]->string, "create", fll_error_file_type_directory); return; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Created directory '%Q'.%c", main.output.to.stream, directorys[i], f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Created directory '%Q'.%c", main->output.to.stream, directorys[i], f_string_eol_s[0]); } } // for @@ -614,32 +604,26 @@ extern "C" { #endif // _di_fake_build_skeleton_ #ifndef _di_fake_build_execute_process_script_ - int fake_build_execute_process_script(const fake_main_t main, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_execute_process_script(fake_main_t * const main, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!process_script.used) return 0; - if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - - return 0; - } - f_string_dynamics_t arguments = f_string_dynamics_t_initialize; *status = fll_execute_arguments_add(fake_other_operation_build_s, fake_other_operation_build_s_length, &arguments); // ensure console color mode is passed to the scripts so that they can also react to color mode. - if (F_status_is_error_not(*status) && main.context.mode != F_color_mode_none_d) { + if (F_status_is_error_not(*status) && main->context.mode != F_color_mode_none_d) { char argument[3] = { f_console_symbol_short_disable_s[0], 0, 0 }; - if (main.context.mode == F_color_mode_dark_d) { + if (main->context.mode == F_color_mode_dark_d) { argument[1] = f_console_standard_short_dark_s[0]; } - else if (main.context.mode == F_color_mode_light_d) { + else if (main->context.mode == F_color_mode_light_d) { argument[1] = f_console_standard_short_light_s[0]; } - else if (main.context.mode == F_color_mode_no_color_d) { + else if (main->context.mode == F_color_mode_no_color_d) { argument[1] = f_console_standard_short_no_color_s[0]; } @@ -647,16 +631,16 @@ extern "C" { } // ensure verbosity level is passed to the scripts so that they can also react to requested verbosity. - if (F_status_is_error_not(*status) && main.error.verbosity != f_console_verbosity_normal) { + if (F_status_is_error_not(*status) && main->error.verbosity != f_console_verbosity_normal) { char argument[3] = { f_console_symbol_short_disable_s[0], 0, 0 }; - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { argument[1] = f_console_standard_short_quiet_s[0]; } - else if (main.error.verbosity == f_console_verbosity_verbose) { + else if (main->error.verbosity == f_console_verbosity_verbose) { argument[1] = f_console_standard_short_verbose_s[0]; } - else if (main.error.verbosity == f_console_verbosity_debug) { + else if (main->error.verbosity == f_console_verbosity_debug) { argument[1] = f_console_standard_short_debug_s[0]; } @@ -664,7 +648,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); macro_f_string_dynamics_t_delete_simple(arguments); return 0; @@ -673,10 +657,10 @@ extern "C" { { f_string_dynamic_t defines = f_string_dynamic_t_initialize; - if (main.define.used) { - for (f_array_length_t i = 0; i < main.define.used; ++i) { + if (main->define.used) { + for (f_array_length_t i = 0; i < main->define.used; ++i) { - *status = f_string_dynamic_mash(f_string_space_s, 1, main.define.array[i], &defines); + *status = f_string_dynamic_mash(f_string_space_s, 1, main->define.array[i], &defines); if (F_status_is_error(*status)) { break; @@ -684,7 +668,7 @@ extern "C" { } // for if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_mash", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_mash", F_true); macro_f_string_dynamic_t_delete_simple(defines); macro_f_string_dynamics_t_delete_simple(arguments); @@ -694,7 +678,7 @@ extern "C" { *status = f_string_dynamic_terminate_after(&defines); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); macro_f_string_dynamic_t_delete_simple(defines); macro_f_string_dynamics_t_delete_simple(arguments); @@ -744,22 +728,22 @@ extern "C" { const f_string_t parameters_value[] = { defines.string, - main.process.string, - main.settings.string, - main.path_build.string, - main.path_data.string, - main.path_sources.string, - main.path_work.string, + main->process.string, + main->settings.string, + main->path_build.string, + main->path_data.string, + main->path_sources.string, + main->path_work.string, }; const f_array_length_t parameters_value_length[] = { defines.used, - main.process.used, - main.settings.used, - main.path_build.used, - main.path_data.used, - main.path_sources.used, - main.path_work.used, + main->process.used, + main->settings.used, + main->path_build.used, + main->path_data.used, + main->path_sources.used, + main->path_work.used, }; *status = fll_execute_arguments_add_parameter_set(parameters_prefix, parameters_prefix_length, parameters_name, parameters_name_length, parameters_value, parameters_value_length, 7, &arguments); @@ -767,7 +751,7 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(defines); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add_parameter_set", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add_parameter_set", F_true); macro_f_string_dynamics_t_delete_simple(arguments); return 0; @@ -781,7 +765,7 @@ extern "C" { function = "f_string_dynamic_append_nulless"; if (process_script.string[0] != '/') { - *status = f_string_dynamic_append_nulless(main.path_data_build, &path); + *status = f_string_dynamic_append_nulless(main->path_data_build, &path); } if (F_status_is_error_not(*status)) { @@ -794,7 +778,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), function, F_true); + fll_error_print(main->error, F_status_set_fine(*status), function, F_true); macro_f_string_dynamic_t_delete_simple(path); macro_f_string_dynamics_t_delete_simple(arguments); @@ -805,7 +789,7 @@ extern "C" { int return_code = 0; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); macro_f_string_dynamic_t_delete_simple(path); macro_f_string_dynamics_t_delete_simple(arguments); @@ -823,23 +807,23 @@ extern "C" { macro_f_string_dynamics_t_delete_simple(arguments); if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } else if (*status != F_child) { if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_failure) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SFailed to execute script: '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SFailed to execute script: '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } else { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_program", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_program", F_true); } } else { @@ -855,7 +839,7 @@ extern "C" { #endif // _di_fake_build_execute_process_script_ #ifndef _di_fake_build_get_file_name_without_extension_ - f_status_t fake_build_get_file_name_without_extension(const fake_main_t main, const f_string_static_t path, f_string_dynamic_t *name) { + f_status_t fake_build_get_file_name_without_extension(fake_main_t * const main, const f_string_static_t path, f_string_dynamic_t *name) { name->used = 0; @@ -864,7 +848,7 @@ extern "C" { f_status_t status = f_file_name_base(path.string, path.used, name); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_file_name_base", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_file_name_base", F_true); return status; } @@ -882,7 +866,7 @@ extern "C" { status = f_string_dynamic_terminate_after(name); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); return status; } @@ -892,8 +876,8 @@ extern "C" { #endif // _di_fake_build_get_file_name_without_extension_ #ifndef _di_fake_build_libraries_script_ - int fake_build_libraries_script(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + int fake_build_libraries_script(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; // @todo needs to perform some sort of regex replace on the library scripts. @@ -904,28 +888,28 @@ extern "C" { #endif // _di_fake_build_libraries_script_ #ifndef _di_fake_build_library_shared_ - int fake_build_library_shared(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_library_shared(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!data_build.setting.build_sources_library.used) return 0; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Compiling shared library.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Compiling shared library.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } f_string_dynamics_t arguments = f_string_dynamics_t_initialize; { - const f_string_static_t *path_sources = &main.path_sources; + const f_string_static_t *path_sources = &main->path_sources; if (data_build.setting.path_standard) { - path_sources = &main.path_sources_c; + path_sources = &main->path_sources_c; if (data_build.setting.build_language == fake_build_language_type_cpp) { - path_sources = &main.path_sources_cpp; + path_sources = &main->path_sources_cpp; } } - else if (main.parameters[fake_parameter_path_sources].result != f_console_result_additional) { + else if (main->parameters[fake_parameter_path_sources].result != f_console_result_additional) { path_sources = &data_build.setting.path_sources; } @@ -960,7 +944,7 @@ extern "C" { } // for if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); macro_f_string_dynamics_t_delete_simple(arguments); return 0; @@ -1138,7 +1122,7 @@ extern "C" { { f_array_length_t parameter_linker_length = fake_build_parameter_library_shared_prefix_s_length; - f_array_length_t parameter_file_path_length = main.path_build_libraries_shared.used; + f_array_length_t parameter_file_path_length = main->path_build_libraries_shared.used; if (data_build.setting.version_file == fake_build_version_type_major) { parameter_file_path_length += parameter_file_name_major_length; @@ -1170,19 +1154,19 @@ extern "C" { char parameter_file_path[parameter_file_path_length + 1]; memcpy(parameter_linker, fake_build_parameter_library_shared_prefix_s, fake_build_parameter_library_shared_prefix_s_length); - memcpy(parameter_file_path, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); + memcpy(parameter_file_path, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); if (data_build.setting.version_file == fake_build_version_type_major) { - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_major, parameter_file_name_major_length); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_major, parameter_file_name_major_length); } else if (data_build.setting.version_file == fake_build_version_type_minor) { - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_minor, parameter_file_name_minor_length); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_minor, parameter_file_name_minor_length); } else if (data_build.setting.version_file == fake_build_version_type_micro) { - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_micro, parameter_file_name_micro_length); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_micro, parameter_file_name_micro_length); } else if (data_build.setting.version_file == fake_build_version_type_nano) { - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_nano, parameter_file_name_nano_length); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_nano, parameter_file_name_nano_length); } if (data_build.setting.version_target == fake_build_version_type_major) { @@ -1226,7 +1210,7 @@ extern "C" { fake_build_arguments_standard_add(main, data_build, F_true, F_true, &arguments, status); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); macro_f_string_dynamics_t_delete_simple(arguments); @@ -1249,34 +1233,34 @@ extern "C" { } if (parameter_file_name_major_length) { - f_array_length_t parameter_file_path_length = main.path_build_libraries_shared.used + parameter_file_name_length; + f_array_length_t parameter_file_path_length = main->path_build_libraries_shared.used + parameter_file_name_length; char parameter_file_path[parameter_file_path_length + 1]; - memcpy(parameter_file_path, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name, parameter_file_name_length); + memcpy(parameter_file_path, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name, parameter_file_name_length); parameter_file_path[parameter_file_path_length] = 0; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } *status = f_file_link(parameter_file_name_major, parameter_file_path); - if (F_status_is_error_not(*status) && main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Linked file '%S' to '%S'.%c", main.output.to.stream, parameter_file_path, parameter_file_name_major, f_string_eol_s[0]); + if (F_status_is_error_not(*status) && main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Linked file '%S' to '%S'.%c", main->output.to.stream, parameter_file_path, parameter_file_name_major, f_string_eol_s[0]); } else if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); return 0; } - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_major, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_major, "link", fll_error_file_type_file); return 0; } @@ -1284,102 +1268,102 @@ extern "C" { if (data_build.setting.version_file != fake_build_version_type_major && parameter_file_name_major_length) { - f_array_length_t parameter_file_path_length = main.path_build_libraries_shared.used + parameter_file_name_major_length; + f_array_length_t parameter_file_path_length = main->path_build_libraries_shared.used + parameter_file_name_major_length; char parameter_file_path[parameter_file_path_length + 1]; - memcpy(parameter_file_path, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_major, parameter_file_name_major_length); + memcpy(parameter_file_path, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_major, parameter_file_name_major_length); parameter_file_path[parameter_file_path_length] = 0; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } *status = f_file_link(parameter_file_name_minor, parameter_file_path); - if (F_status_is_error_not(*status) && main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Linked file '%S' to '%S'.%c", main.output.to.stream, parameter_file_path, parameter_file_name_minor, f_string_eol_s[0]); + if (F_status_is_error_not(*status) && main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Linked file '%S' to '%S'.%c", main->output.to.stream, parameter_file_path, parameter_file_name_minor, f_string_eol_s[0]); } else if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); return 0; } - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_minor, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_minor, "link", fll_error_file_type_file); return 0; } if (data_build.setting.version_file != fake_build_version_type_minor && parameter_file_name_minor_length) { - f_array_length_t parameter_file_path_length = main.path_build_libraries_shared.used + parameter_file_name_minor_length; + f_array_length_t parameter_file_path_length = main->path_build_libraries_shared.used + parameter_file_name_minor_length; char parameter_file_path[parameter_file_path_length + 1]; - memcpy(parameter_file_path, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_minor, parameter_file_name_minor_length); + memcpy(parameter_file_path, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_minor, parameter_file_name_minor_length); parameter_file_path[parameter_file_path_length] = 0; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } *status = f_file_link(parameter_file_name_micro, parameter_file_path); - if (F_status_is_error_not(*status) && main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Linked file '%S' to '%S'.%c", main.output.to.stream, parameter_file_path, parameter_file_name_micro, f_string_eol_s[0]); + if (F_status_is_error_not(*status) && main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Linked file '%S' to '%S'.%c", main->output.to.stream, parameter_file_path, parameter_file_name_micro, f_string_eol_s[0]); } else if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); return 0; } - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_micro, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_micro, "link", fll_error_file_type_file); return 0; } if (data_build.setting.version_file != fake_build_version_type_micro && parameter_file_name_micro_length) { - f_array_length_t parameter_file_path_length = main.path_build_libraries_shared.used + parameter_file_name_micro_length; + f_array_length_t parameter_file_path_length = main->path_build_libraries_shared.used + parameter_file_name_micro_length; char parameter_file_path[parameter_file_path_length + 1]; - memcpy(parameter_file_path, main.path_build_libraries_shared.string, main.path_build_libraries_shared.used); - memcpy(parameter_file_path + main.path_build_libraries_shared.used, parameter_file_name_micro, parameter_file_name_micro_length); + memcpy(parameter_file_path, main->path_build_libraries_shared.string, main->path_build_libraries_shared.used); + memcpy(parameter_file_path + main->path_build_libraries_shared.used, parameter_file_name_micro, parameter_file_name_micro_length); parameter_file_path[parameter_file_path_length] = 0; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } *status = f_file_link(parameter_file_name_nano, parameter_file_path); - if (F_status_is_error_not(*status) && main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Linked file '%S' to '%S'.%c", main.output.to.stream, parameter_file_path, parameter_file_name_nano, f_string_eol_s[0]); + if (F_status_is_error_not(*status) && main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Linked file '%S' to '%S'.%c", main->output.to.stream, parameter_file_path, parameter_file_name_nano, f_string_eol_s[0]); } else if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); return 0; } - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_nano, "link", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_nano, "link", fll_error_file_type_file); return 0; } @@ -1394,13 +1378,13 @@ extern "C" { #endif // _di_fake_build_library_shared_ #ifndef _di_fake_build_library_static_ - int fake_build_library_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_library_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!data_build.setting.build_sources_library.used) return 0; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Compiling static library.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Compiling static library.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } f_string_dynamic_t file_name = f_string_dynamic_t_initialize; @@ -1418,15 +1402,15 @@ extern "C" { } // for if (F_status_is_error_not(*status)) { - f_array_length_t destination_length = main.path_build_libraries_static.used + fake_build_parameter_library_name_prefix_s_length; + f_array_length_t destination_length = main->path_build_libraries_static.used + fake_build_parameter_library_name_prefix_s_length; destination_length += data_build.setting.project_name.used + fake_build_parameter_library_name_suffix_static_s_length; char destination[destination_length + 1]; destination_length = 0; - memcpy(destination, main.path_build_libraries_static.string, main.path_build_libraries_static.used); - destination_length += main.path_build_libraries_static.used; + memcpy(destination, main->path_build_libraries_static.string, main->path_build_libraries_static.used); + destination_length += main->path_build_libraries_static.used; memcpy(destination + destination_length, fake_build_parameter_library_name_prefix_s, fake_build_parameter_library_name_prefix_s_length); destination_length += fake_build_parameter_library_name_prefix_s_length; @@ -1460,48 +1444,48 @@ extern "C" { *status = fake_build_get_file_name_without_extension(main, sources[i]->array[j], &file_name); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } *status = f_file_name_directory(sources[i]->array[j].string, sources[i]->array[j].used, &source_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_directory", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_directory", F_true); break; } if (source_path.used) { - *status = f_string_dynamic_prepend(main.path_build_objects, &source_path); + *status = f_string_dynamic_prepend(main->path_build_objects, &source_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_prepend", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_prepend", F_true); break; } *status = f_string_append_assure(f_path_separator_s, F_path_separator_s_length, &source_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append_assure", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append_assure", F_true); break; } *status = f_string_dynamic_terminate_after(&source_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } source_length = source_path.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; } else { - source_length = main.path_build_objects.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; + source_length = main->path_build_objects.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; } char source[source_length + 1]; @@ -1512,9 +1496,9 @@ extern "C" { memcpy(source + source_path.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); } else { - memcpy(source, main.path_build_objects.string, main.path_build_objects.used); - memcpy(source + main.path_build_objects.used, file_name.string, file_name.used); - memcpy(source + main.path_build_objects.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); + memcpy(source, main->path_build_objects.string, main->path_build_objects.used); + memcpy(source + main->path_build_objects.used, file_name.string, file_name.used); + memcpy(source + main->path_build_objects.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); } source[source_length] = 0; @@ -1522,14 +1506,14 @@ extern "C" { *status = fll_execute_arguments_add(source, source_length, &arguments); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); break; } } // for } // for } - int result = main.child; + int result = main->child; if (F_status_is_error_not(*status)) { result = fake_execute(main, data_build.environment, data_build.setting.build_indexer, arguments, status); @@ -1548,7 +1532,7 @@ extern "C" { #endif // _di_fake_build_library_static_ #ifndef _di_fake_build_load_environment_ - void fake_build_load_environment(const fake_main_t main, const fake_build_data_t data_build, f_string_maps_t *environment, f_status_t *status) { + void fake_build_load_environment(fake_main_t * const main, const fake_build_data_t data_build, f_string_maps_t *environment, f_status_t *status) { if (F_status_is_error(*status)) return; @@ -1577,7 +1561,7 @@ extern "C" { *status = fl_environment_load_name(variables_name[i], variables_length[i], environment); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_environment_load_name", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_environment_load_name", F_true); break; } } // for @@ -1589,16 +1573,16 @@ extern "C" { if (environment->used + data_build.setting.environment.used > environment->size) { if (environment->used + data_build.setting.environment.used > f_environment_max_length) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe values for the setting '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, fake_build_setting_name_environment_s, main.error.notable); - fl_print_format("%[' of setting file '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, fake_build_setting_name_environment_s, main.error.notable); - fl_print_format("%[' is too large.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe values for the setting '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, fake_build_setting_name_environment_s, main->error.notable); + fl_print_format("%[' of setting file '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, fake_build_setting_name_environment_s, main->error.notable); + fl_print_format("%[' is too large.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); } *status = F_status_set_error(F_array_too_large); @@ -1609,22 +1593,23 @@ extern "C" { *status = fl_environment_load_names(data_build.setting.environment, environment); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_environment_load_names", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_environment_load_names", F_true); } } #endif // _di_fake_build_load_environment_ #ifndef _di_fake_build_load_setting_ - void fake_build_load_setting(const fake_main_t main, const f_string_static_t setting_file, fake_build_setting_t *setting, f_status_t *status) { + void fake_build_load_setting(fake_main_t * const main, const f_string_static_t setting_file, fake_build_setting_t *setting, f_status_t *status) { if (F_status_is_error(*status)) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); + return; } - char path_file[main.path_data_build.used + setting_file.used + 1]; + char path_file[main->path_data_build.used + setting_file.used + 1]; { f_string_dynamic_t buffer = f_string_dynamic_t_initialize; @@ -1633,19 +1618,19 @@ extern "C" { f_fss_contents_t contents = f_fss_contents_t_initialize; if (setting_file.used) { - memcpy(path_file, main.path_data_build.string, main.path_data_build.used); - memcpy(path_file + main.path_data_build.used, setting_file.string, setting_file.used); + memcpy(path_file, main->path_data_build.string, main->path_data_build.used); + memcpy(path_file + main->path_data_build.used, setting_file.string, setting_file.used); - path_file[main.path_data_build.used + setting_file.used] = 0; + path_file[main->path_data_build.used + setting_file.used] = 0; *status = fake_file_buffer(main, path_file, &buffer); } else { - *status = fake_file_buffer(main, main.file_data_build_settings.string, &buffer); + *status = fake_file_buffer(main, main->file_data_build_settings.string, &buffer); } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } else if (F_status_is_error_not(*status)) { f_string_range_t range = macro_f_string_range_t_initialize(buffer.used); @@ -1658,16 +1643,16 @@ extern "C" { } if (F_status_is_error(*status)) { - fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main.file_data_build_settings.string, range, F_true); + fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main->file_data_build_settings.string, range, F_true); } else { *status = fl_fss_apply_delimit(delimits, &buffer); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); } else { - fake_build_load_setting_process(main, F_true, setting_file.used ? path_file : main.file_data_build_settings.string, buffer, objects, contents, setting, status); + fake_build_load_setting_process(main, F_true, setting_file.used ? path_file : main->file_data_build_settings.string, buffer, objects, contents, setting, status); } } @@ -1694,15 +1679,15 @@ extern "C" { for (uint8_t i = 0; i < 1; ++i) { if (!settings[i]->used) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe setting '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, names[i], main.error.notable); - fl_print_format("%[' is required but is not specified in the settings file '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, setting_file.used ? path_file : main.file_data_build_settings.string, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe setting '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, names[i], main->error.notable); + fl_print_format("%[' is required but is not specified in the settings file '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, setting_file.used ? path_file : main->file_data_build_settings.string, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); failed = F_true; } @@ -1720,12 +1705,12 @@ extern "C" { #endif // _di_fake_build_load_setting_ #ifndef _di_fake_build_load_setting_process_ - void fake_build_load_setting_process(const fake_main_t main, const bool checks, const f_string_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t *setting, f_status_t *status) { + void fake_build_load_setting_process(fake_main_t * const main, const bool checks, const f_string_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t *setting, f_status_t *status) { if (F_status_is_error(*status) && buffer.used) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return; } @@ -2072,8 +2057,8 @@ extern "C" { f_array_length_t j = 0; // if any mode is specified, the entire defaults is replaced. - if (main.mode.used) { - modes = &main.mode; + if (main->mode.used) { + modes = &main->mode; } for (; i < modes->used; ++i) { @@ -2089,16 +2074,16 @@ extern "C" { } // for if (found == F_false) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe specified mode '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, modes->array[i], main.error.notable); - fl_print_format("%[' is not a valid mode, according to '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path_file, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe specified mode '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, modes->array[i], main->error.notable); + fl_print_format("%[' is not a valid mode, according to '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path_file, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } error_printed = F_true; @@ -2172,18 +2157,18 @@ extern "C" { if (F_status_is_error(*status)) { if (*status == F_status_set_error(F_string_too_large)) { - if (main.error.verbosity != f_console_verbosity_quiet) { - funlockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + funlockfile(main->error.to.stream); - fl_print_format("%c%[%SA setting in the file '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path_file, main.error.notable); - fl_print_format("%[' is too long.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SA setting in the file '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path_file, main->error.notable); + fl_print_format("%[' is too long.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } else if (!error_printed) { - fll_error_print(main.error, F_status_set_fine(*status), function, F_true); + fll_error_print(main->error, F_status_set_fine(*status), function, F_true); } } else if (!fake_signal_received(main)) { @@ -2476,18 +2461,18 @@ extern "C" { if (!settings_single_source[i]->used) continue; if (settings_single_source[i]->used > 1) { - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_single_name[i], main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may only have a single property, only using the first: '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%Q%]", main.warning.to.stream, main.warning.notable, settings_single_source[i]->array[0], main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_single_name[i], main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may only have a single property, only using the first: '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%Q%]", main->warning.to.stream, main->warning.notable, settings_single_source[i]->array[0], main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } } @@ -2501,22 +2486,22 @@ extern "C" { else { *settings_single_bool[i] = F_true; - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); - - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_single_name[i], main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may be either '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_common_setting_bool_yes_s, main.warning.notable); - fl_print_format("%[' or '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_common_setting_bool_no_s, main.warning.notable); - fl_print_format("%[', defaulting to '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_common_setting_bool_yes_s, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); - - funlockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); + + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_single_name[i], main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may be either '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_common_setting_bool_yes_s, main->warning.notable); + fl_print_format("%[' or '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_common_setting_bool_no_s, main->warning.notable); + fl_print_format("%[', defaulting to '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_common_setting_bool_yes_s, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); } } } @@ -2533,24 +2518,24 @@ extern "C" { else { *settings_single_language[i] = fake_build_language_type_c; - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); - - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_single_name[i], main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may only be one of '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_language_bash_s, main.warning.notable); - fl_print_format("%[', '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_language_c_s, main.warning.notable); - fl_print_format("%[', or '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_language_cpp_s, main.warning.notable); - fl_print_format("%[', defaulting to '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_language_c_s, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); - - funlockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); + + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_single_name[i], main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may only be one of '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_language_bash_s, main->warning.notable); + fl_print_format("%[', '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_language_c_s, main->warning.notable); + fl_print_format("%[', or '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_language_cpp_s, main->warning.notable); + fl_print_format("%[', defaulting to '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_language_c_s, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); } } } @@ -2570,26 +2555,26 @@ extern "C" { else { *settings_single_version[i] = settings_single_version_default[i]; - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); - - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_single_name[i], main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may only be one of '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_major_s, main.warning.notable); - fl_print_format("%[', '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_minor_s, main.warning.notable); - fl_print_format("%[', '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_micro_s, main.warning.notable); - fl_print_format("%[', or '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_nano_s, main.warning.notable); - fl_print_format("%[', defaulting to '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, settings_single_version_default_name[i], main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); - - funlockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); + + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_single_name[i], main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may only be one of '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_major_s, main->warning.notable); + fl_print_format("%[', '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_minor_s, main->warning.notable); + fl_print_format("%[', '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_micro_s, main->warning.notable); + fl_print_format("%[', or '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_nano_s, main->warning.notable); + fl_print_format("%[', defaulting to '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, settings_single_version_default_name[i], main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); } } } @@ -2601,7 +2586,7 @@ extern "C" { *status = f_string_dynamic_append_nulless(settings_single_source[i]->array[0], settings_single_destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } @@ -2609,14 +2594,14 @@ extern "C" { *status = f_string_append_assure(f_path_separator_s, F_path_separator_s_length, settings_single_destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append_assure", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append_assure", F_true); break; } } *status = f_string_dynamic_terminate_after(settings_single_destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } } @@ -2626,36 +2611,36 @@ extern "C" { if (checks && !setting->version_file) { setting->version_file = fake_build_version_type_micro; - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, fake_build_setting_name_version_file_s, main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' is required, defaulting to '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_micro_s, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, fake_build_setting_name_version_file_s, main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' is required, defaulting to '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_micro_s, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } } if (checks && !setting->version_target) { setting->version_target = fake_build_version_type_major; - if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe setting '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, fake_build_setting_name_version_target_s, main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' is required, defaulting to '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%s%]", main.warning.to.stream, main.warning.notable, fake_build_version_major_s, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe setting '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, fake_build_setting_name_version_target_s, main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' is required, defaulting to '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%s%]", main->warning.to.stream, main->warning.notable, fake_build_version_major_s, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } } } @@ -2720,7 +2705,7 @@ extern "C" { *status = f_string_append(fake_build_setting_default_version_prefix_s, fake_build_setting_default_version_prefix_s_length, prefix[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } } @@ -2731,18 +2716,18 @@ extern "C" { for (j = 0; j < 2; ++j) { if (setting_target[j] && i + 1 <= setting_target[j]) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); - - fl_print_format("%c%[%SWhen the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, setting_name[j], main.error.notable); - fl_print_format("%[' is set to '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, name_target[setting_target[j] - 1], main.error.notable); - fl_print_format("%[' then the '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, name_object[i], main.error.notable); - fl_print_format("%[' Object must have Content.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); - - funlockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); + + fl_print_format("%c%[%SWhen the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, setting_name[j], main->error.notable); + fl_print_format("%[' is set to '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, name_target[setting_target[j] - 1], main->error.notable); + fl_print_format("%[' then the '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, name_object[i], main->error.notable); + fl_print_format("%[' Object must have Content.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); + + funlockfile(main->error.to.stream); } *status = F_status_set_error(F_failure); @@ -2793,12 +2778,12 @@ extern "C" { #endif // _di_fake_build_load_setting_process_ #ifndef _di_fake_build_load_setting_defaults_ - void fake_build_load_setting_defaults(const fake_main_t main, fake_build_setting_t *setting, f_status_t *status) { + void fake_build_load_setting_defaults(fake_main_t * const main, fake_build_setting_t *setting, f_status_t *status) { if (F_status_is_error(*status)) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return; } @@ -2829,14 +2814,14 @@ extern "C" { *status = f_string_append_assure(sources[i], lengths[i], destinations[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append_assure", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append_assure", F_true); break; } *status = f_string_dynamic_terminate_after(destinations[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } } // for @@ -2845,9 +2830,9 @@ extern "C" { if (F_status_is_error(*status)) return; // Override setting file when any of these are specified in the command line. - if (main.parameters[fake_parameter_shared_disabled].result == f_console_result_found) { - if (main.parameters[fake_parameter_shared_enabled].result == f_console_result_found) { - if (main.parameters[fake_parameter_shared_enabled].location > main.parameters[fake_parameter_shared_disabled].location) { + if (main->parameters[fake_parameter_shared_disabled].result == f_console_result_found) { + if (main->parameters[fake_parameter_shared_enabled].result == f_console_result_found) { + if (main->parameters[fake_parameter_shared_enabled].location > main->parameters[fake_parameter_shared_disabled].location) { setting->build_shared = F_true; setting->search_shared = F_true; } @@ -2856,18 +2841,18 @@ extern "C" { setting->search_shared = F_false; } - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe parameters '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fake_long_shared_disabled_s, main.error.notable); - fl_print_format("%[' and '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fake_long_shared_enabled_s, main.error.notable); - fl_print_format("%[' contradict, defaulting to '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, setting->build_shared ? fake_long_shared_enabled_s : fake_long_shared_disabled_s, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe parameters '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fake_long_shared_disabled_s, main->error.notable); + fl_print_format("%[' and '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fake_long_shared_enabled_s, main->error.notable); + fl_print_format("%[' contradict, defaulting to '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, setting->build_shared ? fake_long_shared_enabled_s : fake_long_shared_disabled_s, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } else { @@ -2875,14 +2860,14 @@ extern "C" { setting->search_shared = F_false; } } - else if (main.parameters[fake_parameter_shared_enabled].result == f_console_result_found) { + else if (main->parameters[fake_parameter_shared_enabled].result == f_console_result_found) { setting->build_shared = F_true; setting->search_shared = F_true; } - if (main.parameters[fake_parameter_static_disabled].result == f_console_result_found) { - if (main.parameters[fake_parameter_static_enabled].result == f_console_result_found) { - if (main.parameters[fake_parameter_static_enabled].location > main.parameters[fake_parameter_static_disabled].location) { + if (main->parameters[fake_parameter_static_disabled].result == f_console_result_found) { + if (main->parameters[fake_parameter_static_enabled].result == f_console_result_found) { + if (main->parameters[fake_parameter_static_enabled].location > main->parameters[fake_parameter_static_disabled].location) { setting->build_static = F_true; setting->search_static = F_true; } @@ -2891,18 +2876,18 @@ extern "C" { setting->search_static = F_false; } - if (main.error.verbosity == f_console_verbosity_verbose) { - flockfile(main.error.to.stream); + if (main->error.verbosity == f_console_verbosity_verbose) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe parameters '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fake_long_static_disabled_s, main.error.notable); - fl_print_format("%[' and '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fake_long_static_enabled_s, main.error.notable); - fl_print_format("%[' contradict, defaulting to '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, setting->build_static ? fake_long_static_enabled_s : fake_long_static_disabled_s, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe parameters '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fake_long_static_disabled_s, main->error.notable); + fl_print_format("%[' and '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fake_long_static_enabled_s, main->error.notable); + fl_print_format("%[' contradict, defaulting to '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, setting->build_static ? fake_long_static_enabled_s : fake_long_static_disabled_s, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } else { @@ -2910,25 +2895,25 @@ extern "C" { setting->search_static = F_false; } } - else if (main.parameters[fake_parameter_static_enabled].result == f_console_result_found) { + else if (main->parameters[fake_parameter_static_enabled].result == f_console_result_found) { setting->build_static = F_true; setting->search_static = F_true; } if (setting->build_language == fake_build_language_type_c || setting->build_language == fake_build_language_type_cpp) { if (setting->build_shared == F_false && setting->build_static == F_false) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe build settings '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, fake_build_setting_name_build_shared_s, main.error.notable); - fl_print_format("%[' and '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, fake_build_setting_name_build_static_s, main.error.notable); - fl_print_format("%[' cannot both be false when using the language '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, setting->build_language == fake_build_language_type_c ? fake_build_language_c_s : fake_build_language_cpp_s, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe build settings '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, fake_build_setting_name_build_shared_s, main->error.notable); + fl_print_format("%[' and '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, fake_build_setting_name_build_static_s, main->error.notable); + fl_print_format("%[' cannot both be false when using the language '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, setting->build_language == fake_build_language_type_c ? fake_build_language_c_s : fake_build_language_cpp_s, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } *status = F_status_set_error(F_failure); @@ -2936,18 +2921,18 @@ extern "C" { } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } } #endif // _di_fake_build_load_setting_defaults_ #ifndef _di_fake_build_load_stage_ - void fake_build_load_stage(const fake_main_t main, const f_string_static_t settings_file, fake_build_stage_t *stage, f_status_t *status) { + void fake_build_load_stage(fake_main_t * const main, const f_string_static_t settings_file, fake_build_stage_t *stage, f_status_t *status) { if (F_status_is_error(*status)) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } const f_string_t names[] = { @@ -3006,36 +2991,36 @@ extern "C" { *status = f_file_name_base(settings_file.string, settings_file.used, &settings_file_base); } else { - *status = f_file_name_base(main.file_data_build_settings.string, main.file_data_build_settings.used, &settings_file_base); + *status = f_file_name_base(main->file_data_build_settings.string, main->file_data_build_settings.used, &settings_file_base); } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_base", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_base", F_true); return; } for (uint8_t i = 0; i < fake_build_stage_total_d; ++i) { - *status = f_string_dynamic_append_nulless(main.path_build_stage, values[i]); + *status = f_string_dynamic_append_nulless(main->path_build_stage, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } - if (main.process.used) { - *status = f_string_append(main.process.string, main.process.used, values[i]); + if (main->process.used) { + *status = f_string_append(main->process.string, main->process.used, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } *status = f_string_append(fake_build_stage_separate_s, fake_build_stage_separate_s_length, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } } @@ -3043,35 +3028,35 @@ extern "C" { *status = f_string_append_nulless(names[i], lengths[i], values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append_nulless", F_true); break; } *status = f_string_append(fake_build_stage_separate_s, fake_build_stage_separate_s_length, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } *status = f_string_dynamic_append(settings_file_base, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); break; } *status = f_string_append(fake_build_stage_built_s, fake_build_stage_built_s_length, values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); break; } *status = f_string_dynamic_terminate_after(values[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } } // for @@ -3081,13 +3066,13 @@ extern "C" { #endif // _di_fake_build_load_stage_ #ifndef _di_fake_build_objects_static_ - int fake_build_objects_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_objects_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!data_build.setting.build_sources_library.used) return 0; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Compiling static objects.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Compiling static objects.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } f_string_dynamic_t file_name = f_string_dynamic_t_initialize; @@ -3096,18 +3081,18 @@ extern "C" { f_array_length_t source_length = 0; f_array_length_t destination_length = 0; - const f_string_static_t *path_sources = &main.path_sources; + const f_string_static_t *path_sources = &main->path_sources; - int result = main.child; + int result = main->child; if (data_build.setting.path_standard) { - path_sources = &main.path_sources_c; + path_sources = &main->path_sources_c; if (data_build.setting.build_language == fake_build_language_type_cpp) { - path_sources = &main.path_sources_cpp; + path_sources = &main->path_sources_cpp; } } - else if (main.parameters[fake_parameter_path_sources].result != f_console_result_additional) { + else if (main->parameters[fake_parameter_path_sources].result != f_console_result_additional) { path_sources = &data_build.setting.path_sources; } @@ -3138,60 +3123,60 @@ extern "C" { *status = fake_build_get_file_name_without_extension(main, sources[i]->array[j], &file_name); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } *status = f_file_name_directory(sources[i]->array[j].string, sources[i]->array[j].used, &destination_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_file_name_directory", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_file_name_directory", F_true); break; } if (destination_path.used) { - *status = f_string_dynamic_prepend(main.path_build_objects, &destination_path); + *status = f_string_dynamic_prepend(main->path_build_objects, &destination_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_prepend", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_prepend", F_true); break; } *status = f_string_append_assure(f_path_separator_s, F_path_separator_s_length, &destination_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append_assure", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append_assure", F_true); break; } *status = f_string_dynamic_terminate_after(&destination_path); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } *status = f_directory_exists(destination_path.string); if (*status == F_false) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, destination_path, main.error.notable); - fl_print_format("%[' exists but is not a directory.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, destination_path, main->error.notable); + fl_print_format("%[' exists but is not a directory.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } *status = F_status_set_error(F_failure); @@ -3202,34 +3187,34 @@ extern "C" { if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found_not) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, destination_path, main.error.notable); - fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, destination_path, main->error.notable); + fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } else { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_directory_create", F_true, destination_path.string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_directory_create", F_true, destination_path.string, "create", fll_error_file_type_directory); } break; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Directory '%Q' created.%c", main.output.to.stream, destination_path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Directory '%Q' created.%c", main->output.to.stream, destination_path, f_string_eol_s[0]); } } else if (F_status_is_error(*status)) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_directory_exists", F_true, destination_path.string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_directory_exists", F_true, destination_path.string, "create", fll_error_file_type_directory); break; } destination_length = destination_path.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; } else { - destination_length = main.path_build_objects.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; + destination_length = main->path_build_objects.used + file_name.used + fake_build_parameter_object_name_suffix_s_length; } char destination[destination_length + 1]; @@ -3240,9 +3225,9 @@ extern "C" { memcpy(destination + destination_path.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); } else { - memcpy(destination, main.path_build_objects.string, main.path_build_objects.used); - memcpy(destination + main.path_build_objects.used, file_name.string, file_name.used); - memcpy(destination + main.path_build_objects.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); + memcpy(destination, main->path_build_objects.string, main->path_build_objects.used); + memcpy(destination + main->path_build_objects.used, file_name.string, file_name.used); + memcpy(destination + main->path_build_objects.used + file_name.used, fake_build_parameter_object_name_suffix_s, fake_build_parameter_object_name_suffix_s_length); } destination[destination_length] = 0; @@ -3274,7 +3259,7 @@ extern "C" { fake_build_arguments_standard_add(main, data_build, F_false, F_true, &arguments, status); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); break; } @@ -3303,8 +3288,8 @@ extern "C" { #ifndef _di_fake_build_operate_ f_status_t fake_build_operate(const f_string_static_t setting_file, fake_main_t *main) { - if (fake_signal_received(*main)) { - return F_signal; + if (fake_signal_received(main)) { + return F_status_set_error(F_interrupt); } f_status_t status = F_none; @@ -3315,7 +3300,7 @@ extern "C" { macro_f_mode_t_set_default_umask(mode, main->umask); - fake_build_load_setting(*main, setting_file, &data_build.setting, &status); + fake_build_load_setting(main, setting_file, &data_build.setting, &status); if (F_status_is_fine(status)) { if (main->output.verbosity != f_console_verbosity_quiet) { @@ -3329,23 +3314,23 @@ extern "C" { } } - fake_build_load_stage(*main, setting_file, &stage, &status); + fake_build_load_stage(main, setting_file, &stage, &status); - fake_build_load_environment(*main, data_build, &data_build.environment, &status); + fake_build_load_environment(main, data_build, &data_build.environment, &status); - fake_build_skeleton(*main, data_build, mode.directory, stage.file_skeleton, &status); + fake_build_skeleton(main, data_build, mode.directory, stage.file_skeleton, &status); - main->child = fake_build_execute_process_script(*main, data_build, data_build.setting.process_pre, stage.file_process_pre, &status); + main->child = fake_build_execute_process_script(main, data_build, data_build.setting.process_pre, stage.file_process_pre, &status); - fake_build_copy(*main, mode, "setting files", main->path_data_settings, main->path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, 0, &status); + fake_build_copy(main, mode, "setting files", main->path_data_settings, main->path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, 0, &status); if (data_build.setting.build_language == fake_build_language_type_bash) { - fake_build_libraries_script(*main, data_build, mode, stage.file_libraries_script, &status); + fake_build_libraries_script(main, data_build, mode, stage.file_libraries_script, &status); - fake_build_programs_script(*main, data_build, mode, stage.file_programs_script, &status); + fake_build_programs_script(main, data_build, mode, stage.file_programs_script, &status); if (data_build.setting.build_script) { - fake_build_copy(*main, mode, "scripts", main->path_sources_script, main->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); + fake_build_copy(main, mode, "scripts", main->path_sources_script, main->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); } } else { @@ -3382,53 +3367,48 @@ extern "C" { path_headers.used = directory_headers_length; path_headers.size = directory_headers_length + 1; - fake_build_copy(*main, mode, "header files", *path_sources, path_headers, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); + fake_build_copy(main, mode, "header files", *path_sources, path_headers, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); if (data_build.setting.build_shared) { - fake_build_copy(*main, mode, "shared header files", *path_sources, path_headers, data_build.setting.build_sources_headers_shared, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); + fake_build_copy(main, mode, "shared header files", *path_sources, path_headers, data_build.setting.build_sources_headers_shared, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); } if (data_build.setting.build_static) { - fake_build_copy(*main, mode, "static header files", *path_sources, path_headers, data_build.setting.build_sources_headers_static, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); + fake_build_copy(main, mode, "static header files", *path_sources, path_headers, data_build.setting.build_sources_headers_static, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); } } if (data_build.setting.build_shared) { - main->child = fake_build_library_shared(*main, data_build, mode, stage.file_libraries_shared, &status); + main->child = fake_build_library_shared(main, data_build, mode, stage.file_libraries_shared, &status); - main->child = fake_build_program_shared(*main, data_build, mode, stage.file_programs_shared, &status); + main->child = fake_build_program_shared(main, data_build, mode, stage.file_programs_shared, &status); } if (data_build.setting.build_static) { - main->child = fake_build_objects_static(*main, data_build, mode, stage.file_objects_static, &status); + main->child = fake_build_objects_static(main, data_build, mode, stage.file_objects_static, &status); - main->child = fake_build_library_static(*main, data_build, mode, stage.file_libraries_static, &status); + main->child = fake_build_library_static(main, data_build, mode, stage.file_libraries_static, &status); - main->child = fake_build_program_static(*main, data_build, mode, stage.file_programs_static, &status); + main->child = fake_build_program_static(main, data_build, mode, stage.file_programs_static, &status); } if (data_build.setting.build_script) { - fake_build_copy(*main, mode, "scripts", main->path_sources_script, main->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); + fake_build_copy(main, mode, "scripts", main->path_sources_script, main->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); } } - fake_build_execute_process_script(*main, data_build, data_build.setting.process_post, stage.file_process_post, &status); + fake_build_execute_process_script(main, data_build, data_build.setting.process_post, stage.file_process_post, &status); macro_fake_build_main_delete_simple(data_build); macro_fake_build_stage_t_delete_simple(stage); - // signal is set with error code only to prevent further execution above, return without the error bit set. - if (status == F_status_set_error(F_signal)) { - return F_signal; - } - return status; } #endif // _di_fake_build_operate_ #ifndef _di_fake_build_programs_script_ - int fake_build_programs_script(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + int fake_build_programs_script(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; // @todo needs to perform some sort of regex replace on the program scripts. @@ -3439,28 +3419,28 @@ extern "C" { #endif // _di_fake_build_programs_script_ #ifndef _di_fake_build_program_shared_ - int fake_build_program_shared(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_program_shared(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!data_build.setting.build_sources_program.used) return 0; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Compiling shared program.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Compiling shared program.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } f_string_dynamics_t arguments = f_string_dynamics_t_initialize; { - const f_string_static_t *path_sources = &main.path_sources; + const f_string_static_t *path_sources = &main->path_sources; if (data_build.setting.path_standard) { - path_sources = &main.path_sources_c; + path_sources = &main->path_sources_c; if (data_build.setting.build_language == fake_build_language_type_cpp) { - path_sources = &main.path_sources_cpp; + path_sources = &main->path_sources_cpp; } } - else if (main.parameters[fake_parameter_path_sources].result != f_console_result_additional) { + else if (main->parameters[fake_parameter_path_sources].result != f_console_result_additional) { path_sources = &data_build.setting.path_sources; } @@ -3495,12 +3475,12 @@ extern "C" { } if (F_status_is_error_not(*status)) { - f_array_length_t parameter_file_name_path_length = main.path_build_programs_shared.used + data_build.setting.project_name.used; + f_array_length_t parameter_file_name_path_length = main->path_build_programs_shared.used + data_build.setting.project_name.used; char parameter_file_name_path[parameter_file_name_path_length + 1]; - memcpy(parameter_file_name_path, main.path_build_programs_shared.string, main.path_build_programs_shared.used); - memcpy(parameter_file_name_path + main.path_build_programs_shared.used, data_build.setting.project_name.string, data_build.setting.project_name.used); + memcpy(parameter_file_name_path, main->path_build_programs_shared.string, main->path_build_programs_shared.used); + memcpy(parameter_file_name_path + main->path_build_programs_shared.used, data_build.setting.project_name.string, data_build.setting.project_name.used); parameter_file_name_path[parameter_file_name_path_length] = 0; const f_string_t values[] = { @@ -3538,7 +3518,7 @@ extern "C" { fake_build_arguments_standard_add(main, data_build, F_true, F_false, &arguments, status); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); macro_f_string_dynamics_t_delete_simple(arguments); return 0; @@ -3557,28 +3537,28 @@ extern "C" { #endif // _di_fake_build_program_shared_ #ifndef _di_fake_build_program_static_ - int fake_build_program_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + int fake_build_program_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main.child; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return main->child; if (!data_build.setting.build_sources_program.used) return 0; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[Compiling static program.%]%c", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important, f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[Compiling static program.%]%c", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important, f_string_eol_s[0]); } f_string_dynamics_t arguments = f_string_dynamics_t_initialize; { - const f_string_static_t *path_sources = &main.path_sources; + const f_string_static_t *path_sources = &main->path_sources; if (data_build.setting.path_standard) { - path_sources = &main.path_sources_c; + path_sources = &main->path_sources_c; if (data_build.setting.build_language == fake_build_language_type_cpp) { - path_sources = &main.path_sources_cpp; + path_sources = &main->path_sources_cpp; } } - else if (main.parameters[fake_parameter_path_sources].result != f_console_result_additional) { + else if (main->parameters[fake_parameter_path_sources].result != f_console_result_additional) { path_sources = &data_build.setting.path_sources; } @@ -3615,7 +3595,7 @@ extern "C" { } if (F_status_is_error_not(*status)) { - f_array_length_t source_library_length = main.path_build_libraries_static.used + fake_build_parameter_library_name_prefix_s_length + data_build.setting.project_name.used + fake_build_parameter_library_name_suffix_static_s_length; + f_array_length_t source_library_length = main->path_build_libraries_static.used + fake_build_parameter_library_name_prefix_s_length + data_build.setting.project_name.used + fake_build_parameter_library_name_suffix_static_s_length; char source_library[source_library_length + 1]; @@ -3623,8 +3603,8 @@ extern "C" { // only include the library if there are sources that would result in it being built. if (data_build.setting.build_sources_library.used) { - memcpy(source_library, main.path_build_libraries_static.string, main.path_build_libraries_static.used); - source_library_length += main.path_build_libraries_static.used; + memcpy(source_library, main->path_build_libraries_static.string, main->path_build_libraries_static.used); + source_library_length += main->path_build_libraries_static.used; memcpy(source_library + source_library_length, fake_build_parameter_library_name_prefix_s, fake_build_parameter_library_name_prefix_s_length); source_library_length += fake_build_parameter_library_name_prefix_s_length; @@ -3638,12 +3618,12 @@ extern "C" { source_library[source_library_length] = 0; - f_array_length_t parameter_file_name_path_length = main.path_build_programs_static.used + data_build.setting.project_name.used; + f_array_length_t parameter_file_name_path_length = main->path_build_programs_static.used + data_build.setting.project_name.used; char parameter_file_name_path[parameter_file_name_path_length + 1]; - memcpy(parameter_file_name_path, main.path_build_programs_static.string, main.path_build_programs_static.used); - memcpy(parameter_file_name_path + main.path_build_programs_static.used, data_build.setting.project_name.string, data_build.setting.project_name.used); + memcpy(parameter_file_name_path, main->path_build_programs_static.string, main->path_build_programs_static.used); + memcpy(parameter_file_name_path + main->path_build_programs_static.used, data_build.setting.project_name.string, data_build.setting.project_name.used); parameter_file_name_path[parameter_file_name_path_length] = 0; const f_string_t values[] = { @@ -3672,7 +3652,7 @@ extern "C" { fake_build_arguments_standard_add(main, data_build, F_false, F_false, &arguments, status); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); macro_f_string_dynamics_t_delete_simple(arguments); return 0; @@ -3691,24 +3671,23 @@ extern "C" { #endif // _di_fake_build_program_static_ #ifndef _di_fake_build_touch_ - void fake_build_touch(const fake_main_t main, const f_string_dynamic_t file, f_status_t *status) { + void fake_build_touch(fake_main_t * const main, const f_string_dynamic_t file, f_status_t *status) { if (F_status_is_error(*status)) return; f_mode_t mode = f_mode_t_initialize; - macro_f_mode_t_set_default_umask(mode, main.umask); + macro_f_mode_t_set_default_umask(mode, main->umask); if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - + *status = F_status_set_error(F_interrupt); return; } *status = f_file_touch(file.string, mode.regular, F_false); if (F_status_is_error(*status)) { - fll_error_file_print(main.error, F_status_set_fine(*status), "f_file_touch", F_true, file.string, "touch", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(*status), "f_file_touch", F_true, file.string, "touch", fll_error_file_type_file); } } #endif // _di_fake_build_touch_ diff --git a/level_3/fake/c/private-build.h b/level_3/fake/c/private-build.h index c8f8025..92fe666 100644 --- a/level_3/fake/c/private-build.h +++ b/level_3/fake/c/private-build.h @@ -16,7 +16,7 @@ extern "C" { * Add the standard arguments for building a library/program. * * @param main - * The main data. + * The main program data. * @param data_build * The build data. * @param is_shared @@ -33,14 +33,14 @@ extern "C" { * @see fll_execute_arguments_add() */ #ifndef _di_fake_build_arguments_standard_add_ - extern void fake_build_arguments_standard_add(const fake_main_t main, const fake_build_data_t data_build, const bool is_shared, const bool is_library, f_string_dynamics_t *arguments, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_arguments_standard_add(fake_main_t * const main, const fake_build_data_t data_build, const bool is_shared, const bool is_library, f_string_dynamics_t *arguments, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_arguments_standard_add_ /** * Copy over the main setting files. * * @param main - * The main data. + * The main program data. * @param mode * The modes for each file type. * @param label @@ -71,14 +71,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_copy_ - extern void fake_build_copy(const fake_main_t main, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_array_length_t preserve, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_copy(fake_main_t * const main, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_array_length_t preserve, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_copy_ /** * Create all of the base directories inside the build directory. * * @param main - * The main data. + * The main program data. * @param data_build * The build data. * @param mode @@ -94,14 +94,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_skeleton_ - extern void fake_build_skeleton(const fake_main_t main, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_skeleton(fake_main_t * const main, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_skeleton_ /** * Execute the Pre-Process or Post-pocess build script. * * @param main - * The main data. + * The main program data. * @param data_build * All build related main. * @param process_script @@ -119,14 +119,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_execute_process_script_ - extern int fake_build_execute_process_script(const fake_main_t main, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_execute_process_script(fake_main_t * const main, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_execute_process_script_ /** * Get the file name without the extension and without the path parts. * * @param main - * The main data. + * The main program data. * @param path * The file path to get the file name from. * @param name @@ -138,14 +138,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_get_file_name_without_extension_ - extern f_status_t fake_build_get_file_name_without_extension(const fake_main_t main, const f_string_static_t path, f_string_dynamic_t *name); + extern f_status_t fake_build_get_file_name_without_extension(fake_main_t * const main, const f_string_static_t path, f_string_dynamic_t *name); #endif // _di_fake_build_get_file_name_without_extension_ /** * Build the script libraries. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -162,14 +162,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_libraries_script_ - extern int fake_build_libraries_script(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_libraries_script(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_libraries_script_ /** * Build the shared libraries. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -186,14 +186,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_library_shared_ - extern int fake_build_library_shared(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_library_shared(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_library_shared_ /** * Build the static libraries. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -210,14 +210,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_library_static_ - extern int fake_build_library_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_library_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_library_static_ /** * Find the build setting file, load it, validate it, and process it. * * @param main - * The main data. + * The main program data. * @param setting_file * The name of the settings file to use. * If setting_file.used is 0, then the default or program parameter supplied file is used. @@ -233,14 +233,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_setting_ - extern void fake_build_load_setting(const fake_main_t main, const f_string_static_t setting_file, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_load_setting(fake_main_t * const main, const f_string_static_t setting_file, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_setting_ /** * Assign build setting defaults. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the buffer. * @param buffer @@ -257,14 +257,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_setting_defaults_ - extern void fake_build_load_setting_defaults(const fake_main_t main, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_load_setting_defaults(fake_main_t * const main, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_setting_defaults_ /** * Load and process the setting buffer. * * @param main - * The main data. + * The main program data. * @param checks * If TRUE, perform certain "required" sanity checks. * If FALSE, do not perform certain "required" sanity checks (intended for a fakefile rather than a build settings file). @@ -288,14 +288,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_setting_process_ - extern void fake_build_load_setting_process(const fake_main_t main, const bool checks, const f_string_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_load_setting_process(fake_main_t * const main, const bool checks, const f_string_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t *setting, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_setting_process_ /** * Load the environment used when executing commands. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param environment @@ -309,14 +309,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_environment_ - extern void fake_build_load_environment(const fake_main_t main, const fake_build_data_t data_build, f_string_maps_t *environment, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_load_environment(fake_main_t * const main, const fake_build_data_t data_build, f_string_maps_t *environment, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_environment_ /** * Load the stage file paths. * * @param main - * The main data. + * The main program data. * @param settings_file * The path to the settings file. * @param stage @@ -330,14 +330,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_stage_ - extern void fake_build_load_stage(const fake_main_t main, const f_string_static_t settings_file, fake_build_stage_t *stage, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_load_stage(fake_main_t * const main, const f_string_static_t settings_file, fake_build_stage_t *stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_stage_ /** * Build the static objects. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -354,7 +354,7 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_objects_static_ - extern int fake_build_objects_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_objects_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_objects_static_ /** @@ -364,7 +364,7 @@ extern "C" { * The name of the settings file to use. * If setting_file.used is 0, then the default or program parameter supplied file is used. * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -379,7 +379,7 @@ extern "C" { * Build the script programs. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -396,14 +396,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_programs_script_ - extern int fake_build_programs_script(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_programs_script(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_programs_script_ /** * Build the shared programs. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -420,14 +420,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_program_shared_ - extern int fake_build_program_shared(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_program_shared(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_program_shared_ /** * Build the static programs. * * @param main - * The main data. + * The main program data. * @param data_build * All build related data. * @param mode @@ -444,14 +444,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_program_static_ - extern int fake_build_program_static(const fake_main_t main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_build_program_static(fake_main_t * const main, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_program_static_ /** * Touch the given build stage file, but only if there are no current errors in status. * * @param main - * The main data. + * The main program data. * @param file * The file path to touch. * @param status @@ -460,7 +460,7 @@ extern "C" { * @see f_file_touch() */ #ifndef _di_fake_build_touch_ - extern void fake_build_touch(const fake_main_t main, const f_string_dynamic_t file, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_build_touch(fake_main_t * const main, const f_string_dynamic_t file, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_build_touch_ #ifdef __cplusplus diff --git a/level_3/fake/c/private-clean.c b/level_3/fake/c/private-clean.c index 974ce99..294856a 100644 --- a/level_3/fake/c/private-clean.c +++ b/level_3/fake/c/private-clean.c @@ -11,47 +11,47 @@ extern "C" { #endif #ifndef _di_fake_clean_operate_ - f_status_t fake_clean_operate(const fake_main_t main) { + f_status_t fake_clean_operate(fake_main_t * const main) { f_status_t status = F_none; - if (main.output.verbosity != f_console_verbosity_quiet) { - flockfile(main.output.to.stream); + if (main->output.verbosity != f_console_verbosity_quiet) { + flockfile(main->output.to.stream); - fl_print_format("%c%[Deleting all files within build directory '%]", main.output.to.stream, f_string_eol_s[0], main.context.set.important, main.context.set.important); - fl_print_format("%[%Q%]", main.output.to.stream, main.context.set.notable, main.path_build, main.context.set.notable); - fl_print_format("%[.%]%c", main.output.to.stream, main.context.set.important, main.context.set.important, f_string_eol_s[0]); + fl_print_format("%c%[Deleting all files within build directory '%]", main->output.to.stream, f_string_eol_s[0], main->context.set.important, main->context.set.important); + fl_print_format("%[%Q%]", main->output.to.stream, main->context.set.notable, main->path_build, main->context.set.notable); + fl_print_format("%[.%]%c", main->output.to.stream, main->context.set.important, main->context.set.important, f_string_eol_s[0]); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); } if (fake_signal_received(main)) { - return F_signal; + return F_status_set_error(F_interrupt); } - if (main.error.verbosity == f_console_verbosity_verbose) { - status = f_directory_remove_custom(main.path_build.string, F_directory_descriptors_max_d, F_true, fake_clean_remove_recursively_verbosely); + if (main->error.verbosity == f_console_verbosity_verbose) { + status = f_directory_remove_custom(main->path_build.string, F_directory_descriptors_max_d, F_true, fake_clean_remove_recursively_verbosely); } else { - status = f_directory_remove(main.path_build.string, F_directory_descriptors_max_d, F_true); + status = f_directory_remove(main->path_build.string, F_directory_descriptors_max_d, F_true); } if (F_status_set_fine(status) == F_file_found_not) { - if (main.error.verbosity == f_console_verbosity_verbose) { - flockfile(main.output.to.stream); + if (main->error.verbosity == f_console_verbosity_verbose) { + flockfile(main->output.to.stream); - f_print_terminated("The build directory '", main.output.to.stream); - fl_print_format("%[%Q%]", main.output.to.stream, main.context.set.notable, main.path_build, main.context.set.notable); - fl_print_format("' does not exist.%c", main.output.to.stream, f_string_eol_s[0]); + f_print_terminated("The build directory '", main->output.to.stream); + fl_print_format("%[%Q%]", main->output.to.stream, main->context.set.notable, main->path_build, main->context.set.notable); + fl_print_format("' does not exist.%c", main->output.to.stream, f_string_eol_s[0]); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); } status = F_none; } if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_directory_remove", F_true, main.path_build.string, "remove", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(status), "f_directory_remove", F_true, main->path_build.string, "remove", fll_error_file_type_directory); return status; } diff --git a/level_3/fake/c/private-clean.h b/level_3/fake/c/private-clean.h index df483b3..69eb65f 100644 --- a/level_3/fake/c/private-clean.h +++ b/level_3/fake/c/private-clean.h @@ -16,15 +16,17 @@ extern "C" { * Execute the clean operation. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_clean_operate_ - extern f_status_t fake_clean_operate(const fake_main_t main) F_attribute_visibility_internal_d; + extern f_status_t fake_clean_operate(fake_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fake_clean_operate_ /** diff --git a/level_3/fake/c/private-common.c b/level_3/fake/c/private-common.c index b6c8072..1a53785 100644 --- a/level_3/fake/c/private-common.c +++ b/level_3/fake/c/private-common.c @@ -1,5 +1,6 @@ #include "fake.h" #include "private-common.h" +#include "private-print.h" #ifdef __cplusplus extern "C" { @@ -226,6 +227,35 @@ extern "C" { const f_string_t fake_make_skeleton_content_settings_s = FAKE_make_skeleton_content_settings_s; #endif // _di_fake_skeleton_content_ +#ifndef _di_fake_signal_received_ + f_status_t fake_signal_received(fake_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fake_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fake_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fake/c/private-common.h b/level_3/fake/c/private-common.h index 15d3455..e15d01a 100644 --- a/level_3/fake/c/private-common.h +++ b/level_3/fake/c/private-common.h @@ -1133,6 +1133,24 @@ extern "C" { extern const f_string_t fake_make_skeleton_content_settings_s; #endif // _di_fake_skeleton_content_ +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fake_signal_received_ + extern f_status_t fake_signal_received(fake_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fake_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index 8b2b735..d50cdd8 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -10,32 +10,32 @@ extern "C" { #endif #ifndef _di_fake_execute_ - int fake_execute(const fake_main_t main, const f_string_maps_t environment, const f_string_static_t program, const f_string_statics_t arguments, f_status_t *status) { + int fake_execute(fake_main_t * const main, const f_string_maps_t environment, const f_string_static_t program, const f_string_statics_t arguments, f_status_t *status) { if (F_status_is_error(*status)) return 1; - if (main.error.verbosity == f_console_verbosity_verbose) { - flockfile(main.output.to.stream); + if (main->error.verbosity == f_console_verbosity_verbose) { + flockfile(main->output.to.stream); - f_print_dynamic(program, main.output.to.stream); + f_print_dynamic(program, main->output.to.stream); for (f_array_length_t i = 0; i < arguments.used; ++i) { if (!arguments.array[i].used) continue; - fl_print_format(" %Q", main.output.to.stream, arguments.array[i]); + fl_print_format(" %Q", main->output.to.stream, arguments.array[i]); } // for - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); - // flush to stdout before executing command. - fflush(main.output.to.stream); + // Flush to stdout before executing command. + fflush(main->output.to.stream); } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } @@ -44,7 +44,7 @@ extern "C" { if (program.used) { - // child processes should receive all signals, without blocking. + // Child processes should receive all signals, without blocking. f_signal_how_t signals = f_signal_how_t_initialize; f_signal_set_empty(&signals.block); f_signal_set_fill(&signals.block_not); @@ -54,7 +54,7 @@ extern "C" { *status = fll_execute_program(program.string, arguments, ¶meter, 0, (void *) &return_code); if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return 0; } @@ -74,18 +74,18 @@ extern "C" { return_code = 1; if (F_status_set_fine(*status) == F_file_found_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SFailed to find program '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, program, main.error.notable); - fl_print_format("%[' for executing.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SFailed to find program '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, program, main->error.notable); + fl_print_format("%[' for executing.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } else { - fll_error_print(main.error, F_status_set_fine(*status), "fll_execute_program", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_execute_program", F_true); } } @@ -94,14 +94,14 @@ extern "C" { #endif // _di_fake_execute_ #ifndef _di_fake_file_buffer_ - f_status_t fake_file_buffer(const fake_main_t main, const f_string_t path_file, f_string_dynamic_t *buffer) { + f_status_t fake_file_buffer(fake_main_t * const main, const f_string_t path_file, f_string_dynamic_t *buffer) { f_file_t file = f_file_t_initialize; f_string_t name_function = "f_file_exists"; f_status_t status = F_none; if (fake_signal_received(main)) { - return F_status_set_error(F_signal); + return F_status_set_error(F_interrupt); } status = f_file_exists(path_file); @@ -121,9 +121,10 @@ extern "C" { macro_f_string_dynamic_t_resize((status), (*buffer), size_file); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), name_function, F_true, path_file, "allocate buffer size for", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), name_function, F_true, path_file, "allocate buffer size for", fll_error_file_type_file); macro_f_string_dynamic_t_delete_simple((*buffer)); + return status; } } @@ -134,14 +135,6 @@ extern "C" { name_function = "f_file_open"; status = f_file_stream_open(path_file, 0, &file); - if (fake_signal_received(main)) { - if (file.id) { - f_file_stream_close(F_true, &file); - } - - return F_status_set_error(F_signal); - } - if (F_status_is_error_not(status)) { name_function = "f_file_read"; status = f_file_read(file, buffer); @@ -154,7 +147,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), name_function, F_true, path_file, "read", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), name_function, F_true, path_file, "read", fll_error_file_type_file); macro_f_string_dynamic_t_delete_simple((*buffer)); } @@ -614,7 +607,8 @@ extern "C" { #endif // _di_fake_path_generate_string_dynamic_ #ifndef _di_fake_process_console_parameters_ - f_status_t fake_process_console_parameters(const f_console_arguments_t arguments, fake_main_t *main) { + f_status_t fake_process_console_parameters(const f_console_arguments_t *arguments, fake_main_t *main) { + f_status_t status = F_none; // @todo move as many of the inline error printing code into more general functions where possible to provide more accurate error reporting. @@ -659,19 +653,19 @@ extern "C" { for (uint8_t i = 0; i < 3; ++i) { if (main->parameters[parameters_id[i]].result == f_console_result_found) { - fake_print_error_parameter_missing_value(*main, parameters_name[i]); + fake_print_error_parameter_missing_value(main, parameters_name[i]); return F_status_set_error(F_parameter); } else if (main->parameters[parameters_id[i]].result == f_console_result_additional) { if (main->parameters[parameters_id[i]].locations.used > 1) { - fake_print_error_parameter_too_many(*main, parameters_name[i]); + fake_print_error_parameter_too_many(main, parameters_name[i]); return F_status_set_error(F_parameter); } f_array_length_t location = main->parameters[parameters_id[i]].values.array[0]; - f_array_length_t length = strnlen(arguments.argv[location], f_console_parameter_size); + f_array_length_t length = strnlen(arguments->argv[location], f_console_parameter_size); if (length > 0) { if (parameters_validate_word[i]) { @@ -682,7 +676,7 @@ extern "C" { width_max = length - j; - status = f_utf_is_word_dash_plus(arguments.argv[location] + j, width_max, F_false); + status = f_utf_is_word_dash_plus(arguments->argv[location] + j, width_max, F_false); if (F_status_is_error(status)) { if (fll_error_print(main->error, F_status_set_fine(status), "f_utf_is_word_dash_plus", F_false) == F_known_not && main->error.verbosity != f_console_verbosity_quiet) { @@ -705,7 +699,7 @@ extern "C" { fl_print_format("%c%[%SThe '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fake_long_process_s, main->error.notable); fl_print_format("%[' parameters value '%]", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, arguments.argv[location], main->error.notable); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, arguments->argv[location], main->error.notable); fl_print_format("%[' contains non-word, non-dash, and non-plus characters.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); funlockfile(main->error.to.stream); @@ -716,7 +710,7 @@ extern "C" { } // for } - status = f_string_append(arguments.argv[location], length, parameters_value[i]); + status = f_string_append(arguments->argv[location], length, parameters_value[i]); if (F_status_is_error(status)) { if (status == F_status_set_error(F_string_too_large)) { @@ -769,7 +763,7 @@ extern "C" { } if (main->parameters[fake_parameter_define].result == f_console_result_found) { - fake_print_error_parameter_missing_value(*main, fake_long_define_s); + fake_print_error_parameter_missing_value(main, fake_long_define_s); return F_status_set_error(F_parameter); } @@ -813,16 +807,18 @@ extern "C" { for (uint8_t i = 0; i < 4; ++i) { if (main->parameters[parameters_id[i]].result == f_console_result_found) { - fake_print_error_parameter_missing_value(*main, parameters_name[i]); + fake_print_error_parameter_missing_value(main, parameters_name[i]); + return F_status_set_error(F_parameter); } else if (main->parameters[parameters_id[i]].result == f_console_result_additional) { if (main->parameters[parameters_id[i]].values.used > 1) { - fake_print_error_parameter_too_many(*main, parameters_name[i]); + fake_print_error_parameter_too_many(main, parameters_name[i]); + return F_status_set_error(F_parameter); } - status = fl_console_parameter_to_string_dynamic_directory(arguments.argv[main->parameters[parameters_id[i]].values.array[0]], parameters_value[i]); + status = fl_console_parameter_to_string_dynamic_directory(arguments->argv[main->parameters[parameters_id[i]].values.array[0]], parameters_value[i]); if (F_status_is_error(status)) { if (fll_error_print(main->error, F_status_set_fine(status), "fl_console_parameter_to_string_dynamic_directory", F_false) == F_known_not && main->error.verbosity != f_console_verbosity_quiet) { @@ -862,7 +858,7 @@ extern "C" { } if (main->parameters[fake_parameter_define].result == f_console_result_additional) { - status = fll_program_parameter_additional_rip(arguments.argv, main->parameters[fake_parameter_define].values, &main->define); + status = fll_program_parameter_additional_rip(arguments->argv, main->parameters[fake_parameter_define].values, &main->define); if (F_status_is_error(status)) { if (fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_additional_rip", F_false) == F_known_not && main->error.verbosity != f_console_verbosity_quiet) { @@ -880,11 +876,11 @@ extern "C" { } if (main->parameters[fake_parameter_mode].result == f_console_result_found) { - fake_print_error_parameter_missing_value(*main, fake_long_mode_s); + fake_print_error_parameter_missing_value(main, fake_long_mode_s); return F_status_set_error(F_parameter); } else if (main->parameters[fake_parameter_mode].result == f_console_result_additional) { - status = fll_program_parameter_additional_rip(arguments.argv, main->parameters[fake_parameter_mode].values, &main->mode); + status = fll_program_parameter_additional_rip(arguments->argv, main->parameters[fake_parameter_mode].values, &main->mode); if (F_status_is_error(status)) { if (fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_additional_rip", F_false) == F_known_not && main->error.verbosity != f_console_verbosity_quiet) { @@ -949,41 +945,6 @@ extern "C" { } #endif // _di_fake_process_console_parameters_ -#ifndef _di_fake_signal_read_ - f_status_t fake_signal_received(const fake_main_t main) { - - if (!main.signal.id) { - return F_false; - } - - f_status_t status = F_none; - - struct signalfd_siginfo information; - - memset(&information, 0, sizeof(struct signalfd_siginfo)); - - status = f_signal_read(main.signal, &information); - - if (status == F_signal) { - switch (information.ssi_signo) { - case F_signal_abort: - case F_signal_hangup: - case F_signal_interrupt: - case F_signal_quit: - case F_signal_termination: - - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[ALERT: An appropriate exit signal has been received, now aborting.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.context, f_string_eol_s[0]); - } - - return F_true; - } - } - - return F_false; - } -#endif // _di_fake_signal_read_ - #ifndef _di_fake_signal_state_interrupt_fss_ f_status_t fake_signal_state_interrupt_fss(void *state, void *internal) { @@ -999,7 +960,7 @@ extern "C" { fake_main_t *main = (fake_main_t *) state_ptr->custom; - if (fake_signal_received(*main)) { + if (fake_signal_received(main)) { return F_status_set_error(F_interrupt); } @@ -1022,7 +983,7 @@ extern "C" { fake_main_t *main = (fake_main_t *) state_ptr->custom; - if (fake_signal_received(*main)) { + if (fake_signal_received(main)) { return F_status_set_error(F_interrupt); } @@ -1031,10 +992,10 @@ extern "C" { #endif // _di_fake_signal_state_interrupt_iki_ #ifndef _di_fake_validate_directories_ - f_status_t fake_validate_parameter_directories(const f_console_arguments_t arguments, const fake_main_t main) { + f_status_t fake_validate_parameter_directories(const f_console_arguments_t *arguments, fake_main_t * const main) { if (fake_signal_received(main)) { - return F_signal; + return F_status_set_error(F_interrupt); } const f_string_t parameters_name[] = { @@ -1056,9 +1017,9 @@ extern "C" { }; const f_string_dynamic_t *parameters_value[] = { - &main.path_build, - &main.path_data, - &main.path_work, + &main->path_build, + &main->path_data, + &main->path_work, }; const bool parameters_required[] = { @@ -1073,7 +1034,7 @@ extern "C" { for (uint8_t i = 0; i < 3; ++i) { if (fake_signal_received(main)) { - return F_status_set_error(F_signal); + return F_status_set_error(F_interrupt); } if (parameters_value[i]->used) { @@ -1085,20 +1046,20 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) != F_directory_found_not || parameters_required[i]) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_stat", F_true, parameters_value[i]->string, "access", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stat", F_true, parameters_value[i]->string, "access", fll_error_file_type_directory); return status; } } } else if (parameters_required[i]) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SNo valid path for the (required) directory parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, parameters_name[i], main.error.notable); - fl_print_format("%[' was found.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SNo valid path for the (required) directory parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, parameters_name[i], main->error.notable); + fl_print_format("%[' was found.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); return F_status_set_error(F_directory_found_not); } diff --git a/level_3/fake/c/private-fake.h b/level_3/fake/c/private-fake.h index 47844d9..fdfd5a5 100644 --- a/level_3/fake/c/private-fake.h +++ b/level_3/fake/c/private-fake.h @@ -18,7 +18,7 @@ extern "C" { * Will print the command if in verbose mode. * * @param main - * The main data. + * The main program data. * @param environment * The environment variable data. * @param program @@ -31,16 +31,18 @@ extern "C" { * @return * The return code result from execution. * A value of 1 is returned if status has the error bit set. + * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. */ #ifndef _di_fake_execute_ - extern int fake_execute(const fake_main_t main, const f_string_maps_t environment, const f_string_static_t program, const f_string_statics_t arguments, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_execute(fake_main_t * const main, const f_string_maps_t environment, const f_string_static_t program, const f_string_statics_t arguments, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_execute_ /** * Load the contents of a file into the given buffer, handling all potential errors. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the file to load. * @param buffer @@ -49,17 +51,19 @@ extern "C" { * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_file_buffer_ - extern f_status_t fake_file_buffer(const fake_main_t main, const f_string_t path_file, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fake_file_buffer(fake_main_t * const main, const f_string_t path_file, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fake_file_buffer_ /** * Generate all appropriate paths based on runtime information. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -74,7 +78,7 @@ extern "C" { * Generate all appropriate paths based on runtime information from dynamic strings. * * @param main - * The main data. + * The main program data. * @param source * The string to copy from. * @param destination @@ -97,7 +101,7 @@ extern "C" { * @param arguments * The parameters passed to the process. * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -105,26 +109,10 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_process_console_parameters_ - extern f_status_t fake_process_console_parameters(const f_console_arguments_t arguments, fake_main_t *main) F_attribute_visibility_internal_d; + extern f_status_t fake_process_console_parameters(const f_console_arguments_t *arguments, fake_main_t *main) F_attribute_visibility_internal_d; #endif // _di_validate_console_parameters_ /** - * Check to see if a termination signal has been received. - * - * @param main - * The main data. - * - * @return - * F_true if a termination signal is received. - * F_false if no termination signal is received. - * - * Status codes (with error bit) are returned on any problem. - */ -#ifndef _di_fake_signal_read_ - extern f_status_t fake_signal_received(const fake_main_t main) F_attribute_visibility_internal_d; -#endif // _di_fake_signal_read_ - -/** * Callback passed to FSS functions for checking for interrupts. * * @param state @@ -135,7 +123,7 @@ extern "C" { * @return * F_interrupt_not if not interrupted. * - * F_interrupt (with error bit) if interrupted. + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. */ #ifndef _di_fake_signal_state_interrupt_fss_ extern f_status_t fake_signal_state_interrupt_fss(void *state, void *internal) F_attribute_visibility_internal_d; @@ -152,7 +140,7 @@ extern "C" { * @return * F_interrupt_not if not interrupted. * - * F_interrupt (with error bit) if interrupted. + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. */ #ifndef _di_fake_signal_state_interrupt_iki_ extern f_status_t fake_signal_state_interrupt_iki(void *state, void *internal) F_attribute_visibility_internal_d; @@ -166,15 +154,17 @@ extern "C" { * @param arguments * The parameters passed to the process. * @param main - * The main data. + * The main program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_validate_parameter_directories_ - extern f_status_t fake_validate_parameter_directories(const f_console_arguments_t arguments, const fake_main_t main) F_attribute_visibility_internal_d; + extern f_status_t fake_validate_parameter_directories(const f_console_arguments_t *arguments, fake_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fake_validate_parameter_directories_ /** diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 6433a2c..478a084 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -12,7 +12,7 @@ extern "C" { #endif #ifndef _di_fake_make_assure_inside_project_ - f_status_t fake_make_assure_inside_project(const fake_main_t main, const f_string_static_t path, fake_make_data_t *data_make) { + f_status_t fake_make_assure_inside_project(fake_main_t * const main, const f_string_static_t path, fake_make_data_t *data_make) { data_make->path_cache.used = 0; @@ -45,7 +45,7 @@ extern "C" { #endif // _di_fake_make_assure_inside_project_ #ifndef _di_fake_make_get_id_group_ - f_status_t fake_make_get_id_group(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, gid_t *id) { + f_status_t fake_make_get_id_group(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, gid_t *id) { const f_string_range_t range = macro_f_string_range_t_initialize(buffer.used); @@ -65,14 +65,14 @@ extern "C" { return F_status_set_error(status); } else if (status == F_exist_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe group name '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, buffer, main.error.notable); - fl_print_format("%[' was not found.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe group name '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, buffer, main->error.notable); + fl_print_format("%[' was not found.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_status_set_error(F_failure); @@ -85,14 +85,14 @@ extern "C" { return F_status_set_error(status); } else if (number > F_type_size_32_unsigned_d) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe number '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, number, main.error.notable); - fl_print_format("%[' is too large.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe number '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, number, main->error.notable); + fl_print_format("%[' is too large.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } @@ -102,7 +102,7 @@ extern "C" { #endif // _di_fake_make_get_id_group_ #ifndef _di_fake_make_get_id_mode_ - f_status_t fake_make_get_id_mode(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, f_file_mode_t *mode, uint8_t *replace) { + f_status_t fake_make_get_id_mode(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, f_file_mode_t *mode, uint8_t *replace) { if (!buffer.used) { fll_error_print(print, F_parameter, "fake_make_get_id_mode", F_true); @@ -110,18 +110,18 @@ extern "C" { return F_status_set_error(F_parameter); } - f_status_t status = f_file_mode_from_string(buffer.string, main.umask, mode, replace); + f_status_t status = f_file_mode_from_string(buffer.string, main->umask, mode, replace); if (F_status_is_error(status)) { - if (main.error.verbosity != f_console_verbosity_quiet) { + if (main->error.verbosity != f_console_verbosity_quiet) { if (F_status_set_fine(status) == F_syntax) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe mode '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, buffer, main.error.notable); - fl_print_format("%[' is invalid.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe mode '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, buffer, main->error.notable); + fl_print_format("%[' is invalid.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } else { fll_error_print(print, status, "f_file_mode_from_string", F_true); @@ -136,7 +136,7 @@ extern "C" { #endif // _di_fake_make_get_id_mode_ #ifndef _di_fake_make_get_id_owner_ - f_status_t fake_make_get_id_owner(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, uid_t *id) { + f_status_t fake_make_get_id_owner(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, uid_t *id) { const f_string_range_t range = macro_f_string_range_t_initialize(buffer.used); @@ -156,14 +156,14 @@ extern "C" { return F_status_set_error(status); } else if (status == F_exist_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe user '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, buffer, main.error.notable); - fl_print_format("%[' was not found.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe user '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, buffer, main->error.notable); + fl_print_format("%[' was not found.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_status_set_error(F_failure); @@ -176,14 +176,14 @@ extern "C" { return F_status_set_error(status); } else if (number > F_type_size_32_unsigned_d) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe number '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, number, main.error.notable); - fl_print_format("%[' is too large.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe number '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, number, main->error.notable); + fl_print_format("%[' is too large.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } } @@ -193,34 +193,28 @@ extern "C" { #endif // _di_fake_make_get_id_owner_ #ifndef _di_fake_make_load_fakefile_ - void fake_make_load_fakefile(const fake_main_t main, fake_make_data_t *data_make, f_status_t *status) { + void fake_make_load_fakefile(fake_main_t * const main, fake_make_data_t *data_make, f_status_t *status) { if (F_status_is_error(*status)) return; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); return; } - *status = fake_file_buffer(main, main.file_data_build_fakefile.string, &data_make->buffer); + *status = fake_file_buffer(main, main->file_data_build_fakefile.string, &data_make->buffer); if (F_status_is_error(*status)) return; - if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - - return; - } - if (!data_make->buffer.used) { - if (main.error.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + if (main->error.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe fakefile '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%Q%]", main.warning.to.stream, main.warning.notable, main.file_data_build_fakefile, main.warning.notable); - fl_print_format("%[' is empty.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe fakefile '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%Q%]", main->warning.to.stream, main->warning.notable, main->file_data_build_fakefile, main->warning.notable); + fl_print_format("%[' is empty.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } return; @@ -241,13 +235,13 @@ extern "C" { } if (F_status_is_error(*status)) { - fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_basic_list_read", main.file_data_build_fakefile.string, range, F_true); + fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_basic_list_read", main->file_data_build_fakefile.string, range, F_true); } else { *status = fl_fss_apply_delimit(delimits, &data_make->buffer); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); } } @@ -256,6 +250,7 @@ extern "C" { macro_f_fss_comments_t_delete_simple(comments); macro_f_fss_objects_t_delete_simple(list_objects); macro_f_fss_contents_t_delete_simple(list_contents); + return; } } @@ -277,7 +272,7 @@ extern "C" { macro_f_fss_nameds_t_resize((*status), data_make->fakefile, list_objects.used); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "macro_f_fss_nameds_t_resize", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "macro_f_fss_nameds_t_resize", F_true); macro_f_fss_set_t_delete_simple(settings); macro_f_fss_objects_t_delete_simple(list_objects); @@ -292,14 +287,14 @@ extern "C" { for (f_array_length_t i = 0; i < list_objects.used; ++i) { if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } if (fl_string_dynamic_partial_compare(name_settings, data_make->buffer, name_settings_range, list_objects.array[i]) == F_equal_to) { if (!missing_settings) { - fake_print_warning_settings_object_multiple(main, main.file_data_build_fakefile.string, "list", name_settings.string); + fake_print_warning_settings_object_multiple(main, main->file_data_build_fakefile.string, "list", name_settings.string); continue; } @@ -309,14 +304,14 @@ extern "C" { *status = fll_fss_extended_read(data_make->buffer, state, &content_range, &settings.objects, &settings.contents, 0, 0, &delimits, 0); if (F_status_is_error(*status)) { - fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main.file_data_build_fakefile.string, content_range, F_true); + fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main->file_data_build_fakefile.string, content_range, F_true); break; } *status = fl_fss_apply_delimit(delimits, &data_make->buffer); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); break; } @@ -325,7 +320,7 @@ extern "C" { } else if (fl_string_dynamic_partial_compare(name_main, data_make->buffer, name_main_range, list_objects.array[i]) == F_equal_to) { if (!missing_main) { - fake_print_warning_settings_object_multiple(main, main.file_data_build_fakefile.string, "list", name_main.string); + fake_print_warning_settings_object_multiple(main, main->file_data_build_fakefile.string, "list", name_main.string); continue; } @@ -341,14 +336,14 @@ extern "C" { *status = fll_fss_extended_read(data_make->buffer, state, &content_range, &data_make->fakefile.array[data_make->fakefile.used].objects, &data_make->fakefile.array[data_make->fakefile.used].contents, 0, &data_make->fakefile.array[data_make->fakefile.used].quotess, &delimits, 0); if (F_status_is_error(*status)) { - fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main.file_data_build_fakefile.string, content_range, F_true); + fake_print_error_fss(main, F_status_set_fine(*status), "fll_fss_extended_read", main->file_data_build_fakefile.string, content_range, F_true); break; } *status = fl_fss_apply_delimit(delimits, &data_make->buffer); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fl_fss_apply_delimit", F_true); break; } @@ -368,16 +363,16 @@ extern "C" { } if (missing_main) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe fakefile '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, main.file_data_build_fakefile, main.error.notable); - fl_print_format("%[' is missing the required '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%s%]", main.error.to.stream, main.error.notable, fake_make_section_main_s, main.error.notable); - fl_print_format("%[' object.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe fakefile '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, main->file_data_build_fakefile, main->error.notable); + fl_print_format("%[' is missing the required '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%s%]", main->error.to.stream, main->error.notable, fake_make_section_main_s, main->error.notable); + fl_print_format("%[' object.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } *status = F_status_set_error(F_failure); @@ -415,7 +410,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), function_name, F_true); + fll_error_print(main->error, F_status_set_fine(*status), function_name, F_true); macro_f_fss_set_t_delete_simple(settings); return; @@ -437,18 +432,18 @@ extern "C" { if (fl_string_dynamic_partial_compare_string(fake_make_setting_compiler_s, data_make->buffer, fake_make_setting_compiler_s_length, settings.objects.array[i]) == F_equal_to) { if (range_compiler) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_compiler_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_compiler_s); } else { if (settings.contents.array[i].used) { range_compiler = &settings.contents.array[i].array[0]; if (settings.contents.array[i].used > 1) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_compiler_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_compiler_s); } } else { - fake_print_warning_settings_content_empty(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); + fake_print_warning_settings_content_empty(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); } } } @@ -463,14 +458,14 @@ extern "C" { *status = f_string_dynamic_partial_append_nulless(data_make->buffer, settings.contents.array[i].array[j], &name_define); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_partial_append_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_partial_append_nulless", F_true); break; } *status = f_string_dynamic_terminate_after(&name_define); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } @@ -486,7 +481,7 @@ extern "C" { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, &data_make->setting_build.environment); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); break; } } @@ -497,31 +492,31 @@ extern "C" { *status = f_string_dynamic_append(name_define, &data_make->setting_build.environment.array[data_make->setting_build.environment.used]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); break; } // Ensure that the terminating NULL is after the end of the string used size. --data_make->setting_build.environment.array[data_make->setting_build.environment.used++].used; } - else if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + else if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe environment name '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%Q%]", main.warning.to.stream, main.warning.notable, name_define, main.warning.notable); - fl_print_format("%[' is already added.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe environment name '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%Q%]", main->warning.to.stream, main->warning.notable, name_define, main->warning.notable); + fl_print_format("%[' is already added.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } } - else if (main.warning.verbosity == f_console_verbosity_verbose) { - flockfile(main.warning.to.stream); + else if (main->warning.verbosity == f_console_verbosity_verbose) { + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe environment name '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%Q%]", main.warning.to.stream, main.warning.notable, name_define, main.warning.notable); - fl_print_format("%[' is invalid, ignoring.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe environment name '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%Q%]", main->warning.to.stream, main->warning.notable, name_define, main->warning.notable); + fl_print_format("%[' is invalid, ignoring.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } name_define.used = 0; @@ -548,37 +543,37 @@ extern "C" { data_make->setting_make.fail = fake_make_operation_fail_type_ignore; } else { - fake_print_warning_settings_content_invalid(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings_s); + fake_print_warning_settings_content_invalid(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings_s); } if (settings.contents.array[i].used > 1) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_fail_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_fail_s); } unmatched_fail = F_false; } else { - fake_print_warning_settings_content_empty(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); + fake_print_warning_settings_content_empty(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); } } else { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_fail_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_fail_s); } } else if (fl_string_dynamic_partial_compare_string(fake_make_setting_indexer_s, data_make->buffer, fake_make_setting_indexer_s_length, settings.objects.array[i]) == F_equal_to) { if (range_indexer) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_indexer_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_indexer_s); } else { if (settings.contents.array[i].used) { range_indexer = &settings.contents.array[i].array[0]; if (settings.contents.array[i].used > 1) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_indexer_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_indexer_s); } } else { - fake_print_warning_settings_content_empty(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); + fake_print_warning_settings_content_empty(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); } } } @@ -592,21 +587,21 @@ extern "C" { data_make->setting_make.load_build = F_false; } else { - fake_print_warning_settings_content_invalid(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings_s); + fake_print_warning_settings_content_invalid(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings_s); } unmatched_load = F_false; if (settings.contents.array[i].used > 1) { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_load_build_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_load_build_s); } } else { - fake_print_warning_settings_content_empty(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); + fake_print_warning_settings_content_empty(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); } } else { - fake_print_warning_settings_content_multiple(main, main.file_data_build_fakefile.string, fake_make_setting_load_build_s); + fake_print_warning_settings_content_multiple(main, main->file_data_build_fakefile.string, fake_make_setting_load_build_s); } } else if (fl_string_dynamic_partial_compare_string(fake_make_setting_parameter_s, data_make->buffer, fake_make_setting_parameter_s_length, settings.objects.array[i]) == F_equal_to) { @@ -634,7 +629,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), function_name, F_true); + fll_error_print(main->error, F_status_set_fine(*status), function_name, F_true); break; } } // for @@ -646,7 +641,7 @@ extern "C" { } } else { - fake_print_warning_settings_content_empty(main, main.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); + fake_print_warning_settings_content_empty(main, main->file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings_s); } } } // for @@ -659,7 +654,7 @@ extern "C" { } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } if (F_status_is_error_not(*status) && data_make->setting_make.load_build) { @@ -667,8 +662,8 @@ extern "C" { fake_build_load_setting(main, stub, &data_make->setting_build, status); - if (F_status_is_error(*status) && *status != F_status_set_error(F_signal)) { - fll_error_print(main.error, F_status_set_fine(*status), "fake_build_load_setting", F_true); + if (F_status_is_error(*status) && *status != F_status_set_error(F_interrupt)) { + fll_error_print(main->error, F_status_set_fine(*status), "fake_build_load_setting", F_true); } } @@ -681,16 +676,20 @@ extern "C" { // if either compiler or indexer is specified, each will replace any existing build_compiler or build_indexer, respectively. if (range_compiler) { data_make->setting_build.build_compiler.used = 0; + *status = f_string_dynamic_partial_append(data_make->buffer, *range_compiler, &data_make->setting_build.build_compiler); } if (F_status_is_error_not(*status) && range_indexer) { data_make->setting_build.build_indexer.used = 0; + *status = f_string_dynamic_partial_append(data_make->buffer, *range_indexer, &data_make->setting_build.build_indexer); } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_partial_append", F_true); + if (F_status_set_fine(*status) != F_interrupt) { + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_partial_append", F_true); + } macro_f_fss_set_t_delete_simple(settings); return; @@ -699,12 +698,12 @@ extern "C" { f_string_map_multis_t define = f_string_map_multis_t_initialize; if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); } else { // load the fakefile "settings" as if they are build "settings". - fake_build_load_setting_process(main, F_false, main.file_data_build_fakefile.string, data_make->buffer, settings.objects, settings.contents, &data_make->setting_build, status); + fake_build_load_setting_process(main, F_false, main->file_data_build_fakefile.string, data_make->buffer, settings.objects, settings.contents, &data_make->setting_build, status); } if (F_status_is_error_not(*status) && settings.objects.used) { @@ -726,7 +725,7 @@ extern "C" { *status = fll_fss_snatch_map_apart(data_make->buffer, settings.objects, settings.contents, settings_name, settings_length, 2, settings_value, 0, 0); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "fll_fss_snatch_map_apart", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "fll_fss_snatch_map_apart", F_true); macro_f_string_map_multis_t_delete_simple(define); macro_f_fss_set_t_delete_simple(settings); @@ -753,7 +752,7 @@ extern "C" { *status = f_string_dynamic_mash(f_string_space_s, 1, define.array[i].value.array[j], &combined); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_mash_nulless", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_mash_nulless", F_true); break; } } // for @@ -761,34 +760,37 @@ extern "C" { if (F_status_is_error(*status)) break; *status = f_string_dynamic_terminate_after(&combined); + if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_terminate_after", F_true); break; } if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); + *status = F_status_set_error(F_interrupt); break; } *status = f_environment_set(define.array[i].name.string, combined.string, F_true); + if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_environment_set", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_environment_set", F_true); break; } } else { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SInvalid characters in the define setting name '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, define.array[i].name, main.error.notable); - fl_print_format("%[', only alpha-numeric ASCII characters and underscore (without a leading digit) are allowed.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SInvalid characters in the define setting name '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, define.array[i].name, main->error.notable); + fl_print_format("%[', only alpha-numeric ASCII characters and underscore (without a leading digit) are allowed.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } *status = F_status_set_error(F_failure); + break; } } // for @@ -802,32 +804,26 @@ extern "C" { #endif // _di_fake_make_load_fakefile_ #ifndef _di_fake_make_load_parameters_ - void fake_make_load_parameters(const fake_main_t main, fake_make_data_t *data_make, f_status_t *status) { + void fake_make_load_parameters(fake_main_t * const main, fake_make_data_t *data_make, f_status_t *status) { if (F_status_is_error(*status)) return; - if (fake_signal_received(main)) { - *status = F_status_set_error(F_signal); - - return; - } - - if (main.context.mode != F_color_mode_none_d) { + if (main->context.mode != F_color_mode_none_d) { if (data_make->parameter.color.used >= data_make->parameter.color.size) { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, &data_make->parameter.color); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); return; } } - if (main.context.mode == F_color_mode_no_color_d) { - if (main.parameters[fake_parameter_no_color].type == f_console_type_normal) { + if (main->context.mode == F_color_mode_no_color_d) { + if (main->parameters[fake_parameter_no_color].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } - else if (main.parameters[fake_parameter_no_color].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_no_color].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } @@ -835,11 +831,11 @@ extern "C" { *status = f_string_append(f_console_standard_short_no_color_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } } - else if (main.context.mode == F_color_mode_dark_d) { - if (main.parameters[fake_parameter_dark].type == f_console_type_normal) { + else if (main->context.mode == F_color_mode_dark_d) { + if (main->parameters[fake_parameter_dark].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } - else if (main.parameters[fake_parameter_dark].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_dark].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } @@ -847,11 +843,11 @@ extern "C" { *status = f_string_append(f_console_standard_short_dark_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } } - else if (main.context.mode == F_color_mode_light_d) { - if (main.parameters[fake_parameter_light].type == f_console_type_normal) { + else if (main->context.mode == F_color_mode_light_d) { + if (main->parameters[fake_parameter_light].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } - else if (main.parameters[fake_parameter_light].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_light].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.color.array[data_make->parameter.color.used]); } @@ -861,7 +857,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); return; } @@ -870,22 +866,22 @@ extern "C" { } } - if (main.error.verbosity != f_console_verbosity_normal) { + if (main->error.verbosity != f_console_verbosity_normal) { if (data_make->parameter.verbosity.used >= data_make->parameter.verbosity.size) { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, &data_make->parameter.verbosity); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); return; } } - if (main.error.verbosity == f_console_verbosity_quiet) { - if (main.parameters[fake_parameter_verbosity_quiet].type == f_console_type_normal) { + if (main->error.verbosity == f_console_verbosity_quiet) { + if (main->parameters[fake_parameter_verbosity_quiet].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } - else if (main.parameters[fake_parameter_verbosity_quiet].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_verbosity_quiet].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } @@ -893,11 +889,11 @@ extern "C" { *status = f_string_append(f_console_standard_short_quiet_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } } - else if (main.error.verbosity == f_console_verbosity_verbose) { - if (main.parameters[fake_parameter_verbosity_verbose].type == f_console_type_normal) { + else if (main->error.verbosity == f_console_verbosity_verbose) { + if (main->parameters[fake_parameter_verbosity_verbose].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } - else if (main.parameters[fake_parameter_verbosity_verbose].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_verbosity_verbose].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } @@ -905,11 +901,11 @@ extern "C" { *status = f_string_append(f_console_standard_short_verbose_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } } - else if (main.error.verbosity == f_console_verbosity_debug) { - if (main.parameters[fake_parameter_verbosity_debug].type == f_console_type_normal) { + else if (main->error.verbosity == f_console_verbosity_debug) { + if (main->parameters[fake_parameter_verbosity_debug].type == f_console_type_normal) { *status = f_string_append(f_console_symbol_short_enable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } - else if (main.parameters[fake_parameter_verbosity_debug].type == f_console_type_inverse) { + else if (main->parameters[fake_parameter_verbosity_debug].type == f_console_type_inverse) { *status = f_string_append(f_console_symbol_short_disable_s, 1, &data_make->parameter.verbosity.array[data_make->parameter.verbosity.used]); } @@ -919,7 +915,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); return; } @@ -935,13 +931,13 @@ extern "C" { }; const f_console_parameter_t *console[] = { - &main.parameters[fake_parameter_define], - &main.parameters[fake_parameter_mode], + &main->parameters[fake_parameter_define], + &main->parameters[fake_parameter_mode], }; const f_string_dynamics_t *source[] = { - &main.define, - &main.mode, + &main->define, + &main->mode, }; f_string_dynamics_t * const destination[] = { @@ -960,7 +956,8 @@ extern "C" { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + return; } } @@ -977,7 +974,8 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); + return; } else { @@ -988,7 +986,8 @@ extern "C" { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + return; } } @@ -996,7 +995,8 @@ extern "C" { *status = f_string_dynamic_append(source[i]->array[j], &destination[i]->array[destination[i]->used]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + return; } else { @@ -1018,23 +1018,23 @@ extern "C" { }; const f_console_parameter_t *console[] = { - &main.parameters[fake_parameter_fakefile], - &main.parameters[fake_parameter_path_build], - &main.parameters[fake_parameter_path_data], - &main.parameters[fake_parameter_path_sources], - &main.parameters[fake_parameter_path_work], - &main.parameters[fake_parameter_process], - &main.parameters[fake_parameter_settings], + &main->parameters[fake_parameter_fakefile], + &main->parameters[fake_parameter_path_build], + &main->parameters[fake_parameter_path_data], + &main->parameters[fake_parameter_path_sources], + &main->parameters[fake_parameter_path_work], + &main->parameters[fake_parameter_process], + &main->parameters[fake_parameter_settings], }; const f_string_dynamic_t *source[] = { - &main.fakefile, - &main.path_build, - &main.path_data, - &main.path_sources, - &main.path_work, - &main.process, - &main.settings, + &main->fakefile, + &main->path_build, + &main->path_data, + &main->path_sources, + &main->path_work, + &main->process, + &main->settings, }; f_string_dynamics_t * const destination[] = { @@ -1053,7 +1053,7 @@ extern "C" { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); return; } @@ -1071,7 +1071,7 @@ extern "C" { } if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_append", F_true); return; } @@ -1083,7 +1083,7 @@ extern "C" { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, destination[i]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); return; } @@ -1092,7 +1092,7 @@ extern "C" { *status = f_string_dynamic_append(*source[i], &destination[i]->array[destination[i]->used]); if (F_status_is_error(*status)) { - fll_error_print(main.error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); + fll_error_print(main->error, F_status_set_fine(*status), "f_string_dynamic_append", F_true); return; } @@ -1105,10 +1105,10 @@ extern "C" { #endif // _di_fake_make_load_parameters_ #ifndef _di_fake_make_operate_ - f_status_t fake_make_operate(fake_main_t *main) { + f_status_t fake_make_operate(fake_main_t * const main) { - if (fake_signal_received(*main)) { - return F_signal; + if (fake_signal_received(main)) { + return F_status_set_error(F_interrupt); } if (main->output.verbosity != f_console_verbosity_quiet) { @@ -1129,10 +1129,10 @@ extern "C" { return status; } - if (fake_signal_received(*main)) { + if (fake_signal_received(main)) { macro_fake_make_data_t_delete_simple(data_make); - return F_signal; + return F_status_set_error(F_interrupt); } status = f_path_current(F_true, &data_make.path.stack.array[0]); @@ -1141,6 +1141,7 @@ extern "C" { fll_error_print(main->error, F_status_set_fine(status), "f_path_current", F_true); macro_fake_make_data_t_delete_simple(data_make); + return status; } @@ -1150,6 +1151,7 @@ extern "C" { fll_error_print(main->error, F_status_set_fine(status), "f_directory_open", F_true); macro_fake_make_data_t_delete_simple(data_make); + return status; } @@ -1157,18 +1159,13 @@ extern "C" { macro_f_mode_t_set_default_umask(mode, main->umask); - fake_make_load_parameters(*main, &data_make, &status); + fake_make_load_parameters(main, &data_make, &status); - fake_make_load_fakefile(*main, &data_make, &status); + fake_make_load_fakefile(main, &data_make, &status); if (F_status_is_error(status)) { macro_fake_make_data_t_delete_simple(data_make); - // signal is set with print code only to prevent further execution above, return without the print bit set. - if (F_status_set_fine(status) == F_signal) { - return F_signal; - } - return status; } @@ -1199,7 +1196,7 @@ extern "C" { } { - const int result = fake_make_operate_section(data_make.main, main, &data_make, §ion_stack, &status); + const int result = fake_make_operate_section(main, data_make.main, &data_make, §ion_stack, &status); if (status == F_child) { main->child = result; @@ -1231,17 +1228,12 @@ extern "C" { macro_f_array_lengths_t_delete_simple(section_stack); macro_fake_make_data_t_delete_simple(data_make); - // signal is set with error code only to prevent further execution above, return without the error bit set. - if (status == F_status_set_error(F_signal)) { - return F_signal; - } - return status; } #endif // _di_fake_make_operate_ #ifndef _di_fake_make_operate_expand_ - void fake_make_operate_expand(const fake_main_t main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_fss_content_t content, const f_fss_quotes_t quotes, fake_make_data_t *data_make, f_string_dynamics_t *arguments, f_status_t *status) { + void fake_make_operate_expand(fake_main_t * const main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_fss_content_t content, const f_fss_quotes_t quotes, fake_make_data_t *data_make, f_string_dynamics_t *arguments, f_status_t *status) { if (F_status_is_error(*status)) return; if (!content.used) return; @@ -1339,7 +1331,10 @@ extern "C" { *status = fl_iki_read(state, &data_make->buffer, &range, &iki_variable, &iki_vocabulary, &iki_content); if (F_status_is_error(*status)) { - fll_error_print(data_make->error, F_status_set_fine(*status), "fl_iki_read", F_true); + if (F_status_set_fine(*status) != F_interrupt) { + fll_error_print(data_make->error, F_status_set_fine(*status), "fl_iki_read", F_true); + } + break; } @@ -1348,7 +1343,7 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "f_string_dynamics_increase_by", F_true); - return; + break; } } @@ -1568,7 +1563,7 @@ extern "C" { range.start = iki_variable.array[iki_variable.used - 1].stop + 1; range.stop = content.array[i].stop; - // if arguments.used was not incremented, then use the value, otherwise arguments.used is past the value to append to, so subtract 1. + // if arguments->used was not incremented, then use the value, otherwise arguments->used is past the value to append to, so subtract 1. if (used_arguments == arguments->used) { *status = f_string_dynamic_partial_append_nulless(data_make->buffer, range, &arguments->array[arguments->used]); } @@ -1624,7 +1619,7 @@ extern "C" { #endif // _di_fake_make_operate_expand_ #ifndef _di_fake_make_operate_expand_build_ - f_status_t fake_make_operate_expand_build(const fake_main_t main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) { + f_status_t fake_make_operate_expand_build(fake_main_t * const main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) { f_status_t status = F_none; f_string_dynamic_t value = f_string_dynamic_t_initialize; @@ -1965,7 +1960,7 @@ extern "C" { #endif // _di_fake_make_operate_expand_build_ #ifndef _di_fake_make_operate_expand_environment_ - f_status_t fake_make_operate_expand_environment(const fake_main_t main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) { + f_status_t fake_make_operate_expand_environment(fake_main_t * const main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) { f_status_t status = F_none; f_string_dynamic_t value = f_string_dynamic_t_initialize; @@ -2024,15 +2019,10 @@ extern "C" { #endif // _di_fake_make_operate_expand_environment_ #ifndef _di_fake_make_operate_section_ - int fake_make_operate_section(const f_array_length_t id_section, fake_main_t *main, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { + int fake_make_operate_section(fake_main_t * const main, const f_array_length_t id_section, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { if (F_status_is_error(*status) || *status == F_child) return main->child; - if (fake_signal_received(*main)) { - *status = F_status_set_error(F_signal); - return 0; - } - if (id_section > data_make->fakefile.used) { *status = F_status_set_error(F_parameter); @@ -2193,8 +2183,8 @@ extern "C" { operation = 0; operation_name = 0; - if (fake_signal_received(*main)) { - *status = F_status_set_error(F_signal); + if (fake_signal_received(main)) { + *status = F_status_set_error(F_interrupt); break; } @@ -2208,13 +2198,13 @@ extern "C" { } // for if (!operation) { - fake_print_message_section_operation_unknown(*main, data_make->error, data_make->buffer, section->name, section->objects.array[i]); + fake_print_message_section_operation_unknown(main, data_make->error, data_make->buffer, section->name, section->objects.array[i]); *status = F_status_set_error(F_valid_not); } else if (operation == fake_make_operation_type_operate) { if (section_stack->used == fake_make_section_stack_max_d) { - fake_print_message_section_operation_stack_max(*main, data_make->error, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max_d); + fake_print_message_section_operation_stack_max(main, data_make->error, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max_d); *status = F_status_set_error(F_recurse); } @@ -2223,7 +2213,7 @@ extern "C" { if (F_status_is_error_not(*status)) { operations[i] = operation; - fake_make_operate_expand(*main, section->name, operation, *operation_name, section->contents.array[i], section->quotess.array[i], data_make, &arguments[i], status); + fake_make_operate_expand(main, section->name, operation, *operation_name, section->contents.array[i], section->quotess.array[i], data_make, &arguments[i], status); } if (operation_if == fake_make_operation_if_type_true_next) { @@ -2236,7 +2226,7 @@ extern "C" { operation_if = fake_make_operation_if_type_false_always; } - fake_make_operate_validate(*main, section->name, operation, *operation_name, arguments[i], &operation_if, data_make, section_stack, status); + fake_make_operate_validate(main, section->name, operation, *operation_name, arguments[i], &operation_if, data_make, section_stack, status); if (F_status_is_error_not(*status)) { @@ -2253,7 +2243,7 @@ extern "C" { continue; } - const int result = fake_make_operate_process(section->name, operation, *operation_name, arguments[i], success, &operation_if, main, data_make, section_stack, status); + const int result = fake_make_operate_process(main, section->name, operation, *operation_name, arguments[i], success, &operation_if, data_make, section_stack, status); if (*status == F_child) { return result; @@ -2293,7 +2283,7 @@ extern "C" { } } - if (*status == F_status_set_error(F_signal)) { + if (F_status_set_fine(*status) == F_interrupt) { break; } @@ -2325,7 +2315,7 @@ extern "C" { data_make->error.set = &main->context.set; } - fake_print_message_section_operation_failed(*main, data_make->error, data_make->buffer, section->name, section->objects.array[i]); + fake_print_message_section_operation_failed(main, data_make->error, data_make->buffer, section->name, section->objects.array[i]); // F_signal_abort is used by the break section operation. if (F_status_set_fine(*status) == F_signal_abort) { @@ -2367,7 +2357,7 @@ extern "C" { } } // for - if (*status == F_status_set_error(F_signal)) { + if (F_status_set_error(*status) == F_interrupt) { for (i = 0; i < section->objects.used; ++i) { macro_f_string_dynamics_t_delete_simple(arguments[i]); } // for @@ -2387,7 +2377,7 @@ extern "C" { funlockfile(data_make->error.to.stream); } - fake_print_message_section_operation_failed(*main, data_make->error, data_make->buffer, section->name, section->objects.array[section->objects.used - 1]); + fake_print_message_section_operation_failed(main, data_make->error, data_make->buffer, section->name, section->objects.array[section->objects.used - 1]); *status = F_status_set_error(F_failure); } @@ -2408,12 +2398,12 @@ extern "C" { #endif // _di_fake_make_operate_section_ #ifndef _di_fake_make_operate_process_ - int fake_make_operate_process(const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_main_t *main, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { + int fake_make_operate_process(fake_main_t * const main, const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { if (*status == F_child) return main->child; if (operation == fake_make_operation_type_index) { - const f_status_t result = fake_execute(*main, data_make->environment, data_make->setting_build.build_indexer, arguments, status); + const f_status_t result = fake_execute(main, data_make->environment, data_make->setting_build.build_indexer, arguments, status); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_execute", F_true); @@ -2423,7 +2413,7 @@ extern "C" { return result; } - fake_make_operate_process_return(*main, result, data_make, status); + fake_make_operate_process_return(main, result, data_make, status); return 0; } @@ -2458,36 +2448,32 @@ extern "C" { *status = fake_build_operate(arguments.used ? arguments.array[0] : stub, main); - if (F_status_set_fine(*status) == F_signal) { - *status = F_status_set_error(F_signal); - + if (F_status_set_fine(*status) == F_interrupt) { return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(*main, 1, data_make, status); + fake_make_operate_process_return(main, 1, data_make, status); } else { - fake_make_operate_process_return(*main, 0, data_make, status); + fake_make_operate_process_return(main, 0, data_make, status); } return 0; } if (operation == fake_make_operation_type_clean) { - *status = fake_clean_operate(*main); - - if (F_status_set_fine(*status) == F_signal) { - *status = F_status_set_error(F_signal); + *status = fake_clean_operate(main); + if (F_status_set_fine(*status) == F_interrupt) { return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(*main, 1, data_make, status); + fake_make_operate_process_return(main, 1, data_make, status); } else { - fake_make_operate_process_return(*main, 0, data_make, status); + fake_make_operate_process_return(main, 0, data_make, status); } return 0; @@ -2580,7 +2566,7 @@ extern "C" { } if (operation == fake_make_operation_type_compile) { - const int result = fake_execute(*main, data_make->environment, data_make->setting_build.build_compiler, arguments, status); + const int result = fake_execute(main, data_make->environment, data_make->setting_build.build_compiler, arguments, status); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_execute", F_true); @@ -2590,7 +2576,7 @@ extern "C" { return result; } - fake_make_operate_process_return(*main, result, data_make, status); + fake_make_operate_process_return(main, result, data_make, status); return 0; } @@ -2876,19 +2862,19 @@ extern "C" { if (operation == fake_make_operation_type_group) { gid_t id = 0; - *status = fake_make_get_id_group(*main, data_make->error, arguments.array[0], &id); + *status = fake_make_get_id_group(main, data_make->error, arguments.array[0], &id); if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; ++i) { - status_file = fake_make_assure_inside_project(*main, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(main, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(*main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -2916,19 +2902,19 @@ extern "C" { if (operation == fake_make_operation_type_groups) { gid_t id = 0; - *status = fake_make_get_id_group(*main, data_make->error, arguments.array[0], &id); + *status = fake_make_get_id_group(main, data_make->error, arguments.array[0], &id); if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; ++i) { - status_file = fake_make_assure_inside_project(*main, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(main, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(*main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -2980,7 +2966,7 @@ extern "C" { if (*operation_if == fake_make_operation_if_type_if_group) { uid_t id = 0; - *status = fake_make_get_id_group(*main, data_make->error, arguments.array[1], &id); + *status = fake_make_get_id_group(main, data_make->error, arguments.array[1], &id); if (F_status_is_error(*status)) return 0; uid_t id_file = 0; @@ -3018,7 +3004,7 @@ extern "C" { { uint8_t mode_replace = 0; - *status = fake_make_get_id_mode(*main, data_make->error, arguments.array[2], &mode_rule, &mode_replace); + *status = fake_make_get_id_mode(main, data_make->error, arguments.array[2], &mode_rule, &mode_replace); if (F_status_is_error(*status)) { *operation_if = fake_make_operation_if_type_false_always_next; @@ -3068,7 +3054,7 @@ extern "C" { if (*operation_if == fake_make_operation_if_type_if_owner) { uid_t id = 0; - *status = fake_make_get_id_owner(*main, data_make->error, arguments.array[1], &id); + *status = fake_make_get_id_owner(main, data_make->error, arguments.array[1], &id); if (F_status_is_error(*status)) return 0; uid_t id_file = 0; @@ -3458,7 +3444,7 @@ extern "C" { f_file_mode_t mode_rule = 0; uint8_t replace = 0; - *status = fake_make_get_id_mode(*main, data_make->error, arguments.array[0], &mode_rule, &replace); + *status = fake_make_get_id_mode(main, data_make->error, arguments.array[0], &mode_rule, &replace); if (F_status_is_error(*status)) return 0; mode_t mode = 0; @@ -3501,7 +3487,7 @@ extern "C" { f_file_mode_t mode_rule = 0; uint8_t replace = 0; - *status = fake_make_get_id_mode(*main, data_make->error, arguments.array[0], &mode_rule, &replace); + *status = fake_make_get_id_mode(main, data_make->error, arguments.array[0], &mode_rule, &replace); if (F_status_is_error(*status)) return 0; mode_t mode = 0; @@ -3614,7 +3600,7 @@ extern "C" { return 0; } - const int result = fake_make_operate_section(id_section, main, data_make, section_stack, status); + const int result = fake_make_operate_section(main, id_section, data_make, section_stack, status); // Ensure that a break only happens within its active operation stack. if (*status == F_signal_abort) { @@ -3630,19 +3616,19 @@ extern "C" { if (operation == fake_make_operation_type_owner) { uid_t id = 0; - *status = fake_make_get_id_owner(*main, data_make->error, arguments.array[0], &id); + *status = fake_make_get_id_owner(main, data_make->error, arguments.array[0], &id); if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; ++i) { - status_file = fake_make_assure_inside_project(*main, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(main, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(*main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -3666,19 +3652,19 @@ extern "C" { if (operation == fake_make_operation_type_owners) { uid_t id = 0; - *status = fake_make_get_id_owner(*main, data_make->error, arguments.array[0], &id); + *status = fake_make_get_id_owner(main, data_make->error, arguments.array[0], &id); if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; ++i) { - status_file = fake_make_assure_inside_project(*main, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(main, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(*main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -3706,13 +3692,13 @@ extern "C" { *status = f_path_change(data_make->path.stack.array[data_make->path.stack.used - 1].string); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(*main, data_make->error, F_status_set_fine(*status), "f_path_change", data_make->path.stack.array[data_make->path.stack.used - 1].string); + fake_print_message_section_operation_path_stack_max(main, data_make->error, F_status_set_fine(*status), "f_path_change", data_make->path.stack.array[data_make->path.stack.used - 1].string); return 0; } if (main->error.verbosity == f_console_verbosity_verbose) { - *status = fake_make_path_relative(*main, data_make->path.stack.array[data_make->path.stack.used - 1], data_make); + *status = fake_make_path_relative(main, data_make->path.stack.array[data_make->path.stack.used - 1], data_make); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_make_path_relative", F_true); @@ -3747,41 +3733,39 @@ extern "C" { } if (operation == fake_make_operation_type_run) { - *status = fake_make_operate_process_run(*main, arguments, F_false, data_make); + *status = fake_make_operate_process_run(main, arguments, F_false, data_make); return 0; } if (operation == fake_make_operation_type_shell) { - *status = fake_make_operate_process_run(*main, arguments, F_true, data_make); + *status = fake_make_operate_process_run(main, arguments, F_true, data_make); return 0; } if (operation == fake_make_operation_type_skeleton) { - *status = fake_skeleton_operate(*main); - - if (F_status_set_fine(*status) == F_signal) { - *status = F_status_set_error(F_signal); + *status = fake_skeleton_operate(main); + if (F_status_set_fine(*status) == F_interrupt) { return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(*main, 1, data_make, status); + fake_make_operate_process_return(main, 1, data_make, status); } else { - fake_make_operate_process_return(*main, 0, data_make, status); + fake_make_operate_process_return(main, 0, data_make, status); } return 0; } if (operation == fake_make_operation_type_to) { - *status = fake_make_assure_inside_project(*main, arguments.array[0], data_make); + *status = fake_make_assure_inside_project(main, arguments.array[0], data_make); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_outside(*main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[0].string); + fake_print_message_section_operation_path_outside(main, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[0].string); if (F_status_set_fine(*status) == F_false) { *status = F_status_set_error(F_failure); @@ -3793,14 +3777,14 @@ extern "C" { *status = f_path_change(arguments.array[0].string); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(*main, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); + fake_print_message_section_operation_path_stack_max(main, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); } else { if (data_make->path.stack.used == data_make->path.stack.size) { *status = f_string_dynamics_increase_by(F_memory_default_allocation_small_d, &data_make->path.stack); if (F_status_set_fine(*status) == F_array_too_large) { - fake_print_message_section_operation_path_stack_max(*main, data_make->error, F_array_too_large, "f_string_dynamics_increase_by", "path stack"); + fake_print_message_section_operation_path_stack_max(main, data_make->error, F_array_too_large, "f_string_dynamics_increase_by", "path stack"); return 0; } @@ -3823,7 +3807,7 @@ extern "C" { } if (main->error.verbosity == f_console_verbosity_verbose) { - *status = fake_make_path_relative(*main, data_make->path.stack.array[data_make->path.stack.used], data_make); + *status = fake_make_path_relative(main, data_make->path.stack.array[data_make->path.stack.used], data_make); if (F_status_is_error(*status)) { @@ -3845,7 +3829,7 @@ extern "C" { *status = f_path_change_at(data_make->path.top.id); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(*main, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); + fake_print_message_section_operation_path_stack_max(main, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); return 0; } @@ -3910,10 +3894,10 @@ extern "C" { #endif // _di_fake_make_operate_process_ #ifndef _di_fake_make_operate_process_execute_ - f_status_t fake_make_operate_process_execute(const fake_main_t main, const f_string_static_t program, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) { + f_status_t fake_make_operate_process_execute(fake_main_t * const main, const f_string_static_t program, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) { if (fake_signal_received(main)) { - return F_status_set_error(F_signal); + return F_status_set_error(F_interrupt); } f_status_t status = F_none; @@ -3935,24 +3919,24 @@ extern "C" { return status; } - if (main.error.verbosity == f_console_verbosity_verbose) { - flockfile(main.output.to.stream); + if (main->error.verbosity == f_console_verbosity_verbose) { + flockfile(main->output.to.stream); - f_print_dynamic_safely(program, main.output.to.stream); + f_print_dynamic_safely(program, main->output.to.stream); for (f_array_length_t i = 0; i < arguments.used; ++i) { if (arguments.array[i].used) { - fll_print_format(" %Q", main.output.to.stream, arguments.array[i]); + fll_print_format(" %Q", main->output.to.stream, arguments.array[i]); } } // for - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); // flush to stdout before executing command. - fflush(main.output.to.stream); + fflush(main->output.to.stream); } int return_code = 0; @@ -3966,11 +3950,15 @@ extern "C" { status = fll_execute_program(program.string, arguments, ¶meter, 0, (void *) &return_code); - if (status == F_status_set_error(F_signal)) { - return status; + if (fake_signal_received(main)) { + return F_status_set_error(F_interrupt); } if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_interrupt) { + return status; + } + if (F_status_set_fine(status) == F_file_found_not) { if (data_make->error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { flockfile(data_make->error.to.stream); @@ -3994,7 +3982,7 @@ extern "C" { #endif // _di_fake_make_operate_process_execute_ #ifndef _di_fake_make_operate_process_return_ - void fake_make_operate_process_return(const fake_main_t main, const int return_code, fake_make_data_t *data_make, f_status_t *status) { + void fake_make_operate_process_return(fake_main_t * const main, const int return_code, fake_make_data_t *data_make, f_status_t *status) { f_status_t status2 = F_none; @@ -4070,7 +4058,7 @@ extern "C" { #endif // _di_fake_make_operate_process_return_ #ifndef _di_fake_make_operate_process_run_ - f_status_t fake_make_operate_process_run(const fake_main_t main, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) { + f_status_t fake_make_operate_process_run(fake_main_t * const main, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) { const f_string_static_t *program = &arguments.array[0]; @@ -4117,7 +4105,7 @@ extern "C" { #endif // _di_fake_make_operate_process_run_ #ifndef _di_fake_make_operate_validate_ - void fake_make_operate_validate(const fake_main_t main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { + void fake_make_operate_validate(fake_main_t * const main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) { if (F_status_is_error(*status)) return; @@ -4188,12 +4176,12 @@ extern "C" { } else if (arguments.used) { if (arguments.array[0].used) { - char path_file[main.path_data_build.used + arguments.array[0].used + 1]; + char path_file[main->path_data_build.used + arguments.array[0].used + 1]; - memcpy(path_file, main.path_data_build.string, main.path_data_build.used); - memcpy(path_file + main.path_data_build.used, arguments.array[0].string, arguments.array[0].used); + memcpy(path_file, main->path_data_build.string, main->path_data_build.used); + memcpy(path_file + main->path_data_build.used, arguments.array[0].string, arguments.array[0].used); - path_file[main.path_data_build.used + arguments.array[0].used] = 0; + path_file[main->path_data_build.used + arguments.array[0].used] = 0; f_status_t status_file = f_file_is(path_file, F_file_type_regular_d, F_false); @@ -5295,7 +5283,7 @@ extern "C" { } else if (F_status_is_error(status_file)) { if (data_make->error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { - fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_is", F_true, main.file_data_build_fakefile.string, "find", fll_error_file_type_file); + fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_is", F_true, main->file_data_build_fakefile.string, "find", fll_error_file_type_file); } *status = status_file; @@ -5399,7 +5387,7 @@ extern "C" { #endif // _di_fake_make_operate_validate_define_name_ #ifndef _di_fake_make_path_relative_ - f_status_t fake_make_path_relative(const fake_main_t main, const f_string_static_t path, fake_make_data_t *data_make) { + f_status_t fake_make_path_relative(fake_main_t * const main, const f_string_static_t path, fake_make_data_t *data_make) { data_make->path_cache.used = 0; diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index 34671bc..53da9e7 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -16,7 +16,7 @@ extern "C" { * Assure that a path is within the project root path. * * @param main - * The main data. + * The main program data. * @param path * file path to get the real path of. * @param main_make @@ -30,14 +30,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_assure_inside_project_ - extern f_status_t fake_make_assure_inside_project(const fake_main_t main, const f_string_static_t path, fake_make_data_t *data_make) F_attribute_visibility_internal_d; + extern f_status_t fake_make_assure_inside_project(fake_main_t * const main, const f_string_static_t path, fake_make_data_t *data_make) F_attribute_visibility_internal_d; #endif // _di_fake_make_assure_inside_project_ /** * Get the group id from either a string representing the number or a string representing the name. * * @param main - * The main data. + * The main program data. * @param print * The error/warning print data. * @param buffer @@ -52,14 +52,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_get_id_group_ - f_status_t fake_make_get_id_group(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, gid_t *id) F_attribute_visibility_internal_d; + f_status_t fake_make_get_id_group(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, gid_t *id) F_attribute_visibility_internal_d; #endif // _di_fake_make_get_id_group_ /** * Get the mode id from either a string representing the number or a string representing the mode. * * @param main - * The main data. + * The main program data. * @param print * The error/warning print data. * @param buffer @@ -78,14 +78,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_get_id_mode_ - f_status_t fake_make_get_id_mode(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, f_file_mode_t *mode, uint8_t *replace) F_attribute_visibility_internal_d; + f_status_t fake_make_get_id_mode(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, f_file_mode_t *mode, uint8_t *replace) F_attribute_visibility_internal_d; #endif // _di_fake_make_get_id_mode_ /** * Get the user id from either a string representing the number or a string representing the name. * * @param main - * The main data. + * The main program data. * @param print * The error/warning print data. * @param buffer @@ -100,7 +100,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_get_id_owner_ - f_status_t fake_make_get_id_owner(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, uid_t *id) F_attribute_visibility_internal_d; + f_status_t fake_make_get_id_owner(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, uid_t *id) F_attribute_visibility_internal_d; #endif // _di_fake_make_get_id_owner_ /** @@ -109,7 +109,7 @@ extern "C" { * This will process any additional files as necessary, such as the build settings file. * * @param main - * The main data. + * The main program data. * @param main_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param status @@ -117,19 +117,21 @@ extern "C" { * * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. * * @see fake_build_load_setting() */ #ifndef _di_fake_make_load_fakefile_ - extern void fake_make_load_fakefile(const fake_main_t main, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_make_load_fakefile(fake_main_t * const main, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_load_fakefile_ /** * Load the environment variables into a structure more readily available for using in parameter expansion. * * @param main - * The main data. + * The main program data. * @param main_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param status @@ -137,10 +139,12 @@ extern "C" { * * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_load_parameters_ - extern void fake_make_load_parameters(const fake_main_t main, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_make_load_parameters(fake_main_t * const main, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_load_parameters_ /** @@ -150,15 +154,17 @@ extern "C" { * The 'settings' section is only loaded into settings and is never operated on. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_ - extern f_status_t fake_make_operate(fake_main_t *main) F_attribute_visibility_internal_d; + extern f_status_t fake_make_operate(fake_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_ /** @@ -167,7 +173,7 @@ extern "C" { * This prints errors via data_make.error. * * @param main - * The main data. + * The main program data. * @param section_name * The section name. * @param operation @@ -188,14 +194,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_expand_ - extern void fake_make_operate_expand(const fake_main_t main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_fss_content_t content, const f_fss_quotes_t quoteds, fake_make_data_t *data_make, f_string_dynamics_t *arguments, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_make_operate_expand(fake_main_t * const main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_fss_content_t content, const f_fss_quotes_t quoteds, fake_make_data_t *data_make, f_string_dynamics_t *arguments, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_expand_ /** * Perform the expand operation, specifically for the environment variables. * * @param main - * The main data. + * The main program data. * @param quoted * The quoted associated with the content. * @param range_name @@ -212,14 +218,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_expand_environment_ - extern f_status_t fake_make_operate_expand_environment(const fake_main_t main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) F_attribute_visibility_internal_d; + extern f_status_t fake_make_operate_expand_environment(fake_main_t * const main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_expand_environment_ /** * Perform the expand operation, specifically for the build settings. * * @param main - * The main data. + * The main program data. * @param quoted * The quoted associated with the content. * @param range_name @@ -236,24 +242,26 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_expand_build_ - extern f_status_t fake_make_operate_expand_build(const fake_main_t main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) F_attribute_visibility_internal_d; + extern f_status_t fake_make_operate_expand_build(fake_main_t * const main, const f_fss_quote_t quoted, const f_string_range_t range_name, fake_make_data_t *data_make, f_string_dynamics_t *arguments) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_expand_build_ /** * Perform the make operations within the given section. * + * @param main + * The main program data. * @param id_section * The array location id within the fakefile of the section to operate on. - * @param main - * The main data. * @param main_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_stack * The current operation stack. * @param status * F_none on success. - * F_valid_not (with error bit) is returned if any part of the section is invalid, such as an invalid operation name. + * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. * F_recurse (with error bit) is returned if unable to recurse to another operation section (usually max stack depth reached). + * F_valid_not (with error bit) is returned if any part of the section is invalid, such as an invalid operation name. * * Status codes (with error bit) are returned on any problem. * @@ -262,12 +270,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_make_operate_section_ - int fake_make_operate_section(const f_array_length_t id_section, fake_main_t *main, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; + int fake_make_operate_section(fake_main_t * const main, const f_array_length_t id_section, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_section_ /** * Perform a specific make operation within the given section. * + * @param main + * The main program data. * @param section_name * The section name. * @param operation @@ -280,8 +290,6 @@ extern "C" { * Whether or not a previous section operation succeeded or failed. * @param operation_if * The if-condition status for the current operation. - * @param main - * The main data. * @param main_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_stack @@ -289,6 +297,8 @@ extern "C" { * @param status * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. * * @return @@ -296,14 +306,14 @@ extern "C" { * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_make_operate_process_ - extern int fake_make_operate_process(const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_main_t *main, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; + extern int fake_make_operate_process(fake_main_t * const main, const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_process_ /** * Execute either the run operation or the shell operation. * * @param main - * The main data. + * The main program data. * @param program * The program to be executed. * @param arguments @@ -315,17 +325,21 @@ extern "C" { * All make related setting data, including data from the fakefile and optionally build settings file. * * @return + * F_none on success. + * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_process_execute_ - extern f_status_t fake_make_operate_process_execute(const fake_main_t main, const f_string_static_t program, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) F_attribute_visibility_internal_d; + extern f_status_t fake_make_operate_process_execute(fake_main_t * const main, const f_string_static_t program, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_process_execute_ /** * Handle the return code, converting it to a number. * * @param main - * The main data. + * The main program data. * @param return_code * The return code to process. * @param main_make @@ -333,17 +347,19 @@ extern "C" { * @param status * The return status. * + * F_none on success. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_process_return_ - extern void fake_make_operate_process_return(const fake_main_t main, const int return_code, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_make_operate_process_return(fake_main_t * const main, const int return_code, fake_make_data_t *data_make, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_process_return_ /** * Execute either the run operation or the shell operation. * * @param main - * The main data. + * The main program data. * @param arguments * The arguments for the run or shell operation. * @param as_shell @@ -356,7 +372,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_process_run_ - extern f_status_t fake_make_operate_process_run(const fake_main_t main, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) F_attribute_visibility_internal_d; + extern f_status_t fake_make_operate_process_run(fake_main_t * const main, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_process_run_ /** @@ -366,7 +382,7 @@ extern "C" { * Additional issues may occure when running operations that are not detected nor detectable by this. * * @param main - * The main data. + * The main program data. * @param section_name * The section name. * @param operation @@ -387,7 +403,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_validate_ - extern void fake_make_operate_validate(const fake_main_t main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; + extern void fake_make_operate_validate(fake_main_t * const main, const f_string_range_t section_name, const f_array_length_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, uint8_t *operation_if, fake_make_data_t *data_make, f_array_lengths_t *section_stack, f_status_t *status) F_attribute_visibility_internal_d; #endif // _di_fake_make_operate_validate_ /** @@ -415,7 +431,7 @@ extern "C" { * Get a path, relative to the project root. * * @param main - * The main data. + * The main program data. * @param path * The NULL terminated path to get the relative path of. * @param main_make @@ -426,7 +442,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_path_relative_ - extern f_status_t fake_make_path_relative(const fake_main_t main, const f_string_static_t path, fake_make_data_t *data_make) F_attribute_visibility_internal_d; + extern f_status_t fake_make_path_relative(fake_main_t * const main, const f_string_static_t path, fake_make_data_t *data_make) F_attribute_visibility_internal_d; #endif // _di_fake_make_path_relative_ #ifdef __cplusplus diff --git a/level_3/fake/c/private-print.c b/level_3/fake/c/private-print.c index c5b1b28..fdfea52 100644 --- a/level_3/fake/c/private-print.c +++ b/level_3/fake/c/private-print.c @@ -11,248 +11,248 @@ extern "C" { #endif #ifndef _di_fake_print_error_build_operation_file_ - bool fake_print_error_build_operation_file(const fake_main_t main, const f_status_t status, const f_string_t function, const f_string_t operation, const f_string_t how, const f_string_t source, const f_string_t destination, const bool fallback) { + bool fake_print_error_build_operation_file(fake_main_t * const main, const f_status_t status, const f_string_t function, const f_string_t operation, const f_string_t how, const f_string_t source, const f_string_t destination, const bool fallback) { if (status == F_file_found_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SFailed to find '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, f_file_exists(source) == F_true ? destination : source, main.error.notable); - fl_print_format("%[while trying to %S '%]", main.error.to.stream, main.error.context, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SFailed to find '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, f_file_exists(source) == F_true ? destination : source, main->error.notable); + fl_print_format("%[while trying to %S '%]", main->error.to.stream, main->error.context, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_parameter) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SInvalid parameter when calling '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, function, main.error.notable); - fl_print_format("%[() to %s '%]", main.error.to.stream, main.error.context, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SInvalid parameter when calling '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, function, main->error.notable); + fl_print_format("%[() to %s '%]", main->error.to.stream, main->error.context, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_name) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SInvalid name for '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SInvalid name for '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' or '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' or '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_memory_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SUnable to allocate memory, while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SUnable to allocate memory, while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_number_overflow) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SOverflow while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SOverflow while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_directory) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SInvalid directory while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SInvalid directory while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_access_denied) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SAccess denied while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SAccess denied while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_loop) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SLoop while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SLoop while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_prohibited) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SProhibited by system while trying to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SProhibited by system while trying to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_directory_found_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SFailed to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SFailed to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%[' due to an invalid directory in the path.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%[' due to an invalid directory in the path.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_failure) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SFailed to %S '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[%SFailed to %S '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } - if (fll_error_print(main.error, status, function, F_false) == F_known_not && fallback && main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (fll_error_print(main->error, status, function, F_false) == F_known_not && fallback && main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[UNKNOWN %s(%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, operation, main.error.context); - fl_print_format("%[%ui%]", main.error.to.stream, main.error.notable, status, main.error.notable); - fl_print_format("%[) occurred while trying to %S '%]", main.error.to.stream, main.error.context, operation, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, source, main.error.notable); + fl_print_format("%c%[UNKNOWN %s(%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, operation, main->error.context); + fl_print_format("%[%ui%]", main->error.to.stream, main->error.notable, status, main->error.notable); + fl_print_format("%[) occurred while trying to %S '%]", main->error.to.stream, main->error.context, operation, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, source, main->error.notable); if (destination) { - fl_print_format("%[' %S '%]", main.error.to.stream, main.error.context, how, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, destination, main.error.notable); + fl_print_format("%[' %S '%]", main->error.to.stream, main->error.context, how, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, destination, main->error.notable); } - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_true; @@ -260,66 +260,66 @@ extern "C" { #endif // _di_fake_print_error_build_operation_file_ #ifndef _di_fake_print_error_fss - bool fake_print_error_fss(const fake_main_t main, const f_status_t status, const f_string_t function, const f_string_t path_file, const f_string_range_t range, const bool fallback) { + bool fake_print_error_fss(fake_main_t * const main, const f_status_t status, const f_string_t function, const f_string_t path_file, const f_string_range_t range, const bool fallback) { if (status == F_file_found_not) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SOccurred on invalid UTF-8 character at stop position (at '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, range.start, main.error.notable); - fl_print_format("%[ of setting file '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path_file, main.error.notable); - fl_print_format("%[').%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SOccurred on invalid UTF-8 character at stop position (at '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, range.start, main->error.notable); + fl_print_format("%[ of setting file '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path_file, main->error.notable); + fl_print_format("%[').%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_complete_not_utf || status == F_complete_not_utf_eos || status == F_complete_not_utf_stop) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SOccurred on invalid UTF-8 character at %s (at '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, status == F_complete_not_utf_eos ? "end of string" : "stop point of string", main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, range.start, main.error.notable); - fl_print_format("%[ of setting file '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path_file, main.error.notable); - fl_print_format("%[').%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SOccurred on invalid UTF-8 character at %s (at '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, status == F_complete_not_utf_eos ? "end of string" : "stop point of string", main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, range.start, main->error.notable); + fl_print_format("%[ of setting file '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path_file, main->error.notable); + fl_print_format("%[').%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } if (status == F_complete_not_utf_stop) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SOccurred on invalid UTF-8 character at stop point of string (at '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, range.start, main.error.notable); - fl_print_format("%[ of setting file '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path_file, main.error.notable); - fl_print_format("%[').%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SOccurred on invalid UTF-8 character at stop point of string (at '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, range.start, main->error.notable); + fl_print_format("%[ of setting file '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path_file, main->error.notable); + fl_print_format("%[').%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_false; } - if (fll_error_print(main.error, status, function, F_false) == F_known_not && fallback && main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (fll_error_print(main->error, status, function, F_false) == F_known_not && fallback && main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[UNKNOWN %s(%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%ui%]", main.error.to.stream, main.error.notable, status, main.error.notable); - fl_print_format("%[) in function '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, function, main.error.notable); - fl_print_format("%[().%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[UNKNOWN %s(%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%ui%]", main->error.to.stream, main->error.notable, status, main->error.notable); + fl_print_format("%[) in function '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, function, main->error.notable); + fl_print_format("%[().%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_true; @@ -327,98 +327,98 @@ extern "C" { #endif // _di_fake_print_error_fss #ifndef _di_fake_print_error_parameter_missing_value_ - void fake_print_error_parameter_missing_value(const fake_main_t main, const f_string_t parameter) { + void fake_print_error_parameter_missing_value(fake_main_t * const main, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) return; + if (main->error.verbosity == f_console_verbosity_quiet) return; - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_error_parameter_missing_value_ #ifndef _di_fake_print_error_parameter_too_many_ - void fake_print_error_parameter_too_many(const fake_main_t main, const f_string_t parameter) { + void fake_print_error_parameter_too_many(fake_main_t * const main, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) return; + if (main->error.verbosity == f_console_verbosity_quiet) return; - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, parameter, main.error.notable); - fl_print_format("%[' was specified too many times.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, parameter, main->error.notable); + fl_print_format("%[' was specified too many times.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_error_parameter_too_many_ #ifndef _di_fake_print_message_section_operation_failed_ - void fake_print_message_section_operation_failed(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) { + void fake_print_message_section_operation_failed(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) { - if (main.error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; + if (main->error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; f_array_length_t line = 1; f_fss_count_lines(buffer, operation_name.start, &line); - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe section operation '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, operation_name, main.error.notable); - fl_print_format("%[' from section '%]", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, section_name, main.error.notable); - fl_print_format("%[' on line%] ", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%un%]", main.error.to.stream, main.error.notable, line, main.error.notable); - fl_print_format(" %[failed.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe section operation '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, operation_name, main->error.notable); + fl_print_format("%[' from section '%]", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, section_name, main->error.notable); + fl_print_format("%[' on line%] ", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%un%]", main->error.to.stream, main->error.notable, line, main->error.notable); + fl_print_format(" %[failed.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_message_section_operation_failed_ #ifndef _di_fake_print_message_section_operation_path_outside_ - void fake_print_message_section_operation_path_outside(const fake_main_t main, const fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) { + void fake_print_message_section_operation_path_outside(fake_main_t * const main, const fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) { - if (main.error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; + if (main->error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); if (F_status_set_fine(status) == F_false) { - fl_print_format("%c%[%SThe path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%[' is outside the project root.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%[' is outside the project root.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); } else { - fll_error_file_print(main.error, F_status_set_fine(status), function, F_true, path, "determine real path of", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), function, F_true, path, "determine real path of", fll_error_file_type_file); } - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_message_section_operation_path_outside_ #ifndef _di_fake_print_message_section_operation_path_stack_max_ - void fake_print_message_section_operation_path_stack_max(const fake_main_t main, fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) { + void fake_print_message_section_operation_path_stack_max(fake_main_t * const main, fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) { - if (main.error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; + if (main->error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; if (status == F_array_too_large) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SMaximum stack size reached while processing path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%['", main.error.to.stream, main.error.context); + fl_print_format("%c%[%SMaximum stack size reached while processing path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%['", main->error.to.stream, main->error.context); if (function) { - fl_print_format(" while calling%] %[%S%]", main.error.to.stream, main.error.context, main.error.notable, function, main.error.notable); - fl_print_format("%[()", main.error.to.stream, main.error.context); + fl_print_format(" while calling%] %[%S%]", main->error.to.stream, main->error.context, main->error.notable, function, main->error.notable); + fl_print_format("%[()", main->error.to.stream, main->error.context); } - fl_print_format(".%]%c", main.error.to.stream, main.error.context, f_string_eol_s[0]); + fl_print_format(".%]%c", main->error.to.stream, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } else { fll_error_file_print(print, status, function, F_true, path, "change path to", fll_error_file_type_directory); @@ -427,124 +427,142 @@ extern "C" { #endif // _di_fake_print_message_section_operation_path_stack_max_ #ifndef _di_fake_print_message_section_operation_stack_max_ - void fake_print_message_section_operation_stack_max(const fake_main_t main, fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name, const f_array_length_t stack_max) { + void fake_print_message_section_operation_stack_max(fake_main_t * const main, fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name, const f_array_length_t stack_max) { - if (main.error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; + if (main->error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; f_array_length_t line = 1; f_fss_count_lines(buffer, operation_name.start, &line); - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe section operation '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, operation_name, main.error.notable); - fl_print_format("%[' from section '%]", main.error.to.stream, main.error.context, buffer, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, section_name, main.error.notable); - fl_print_format("%[' on line%] ", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, line, main.error.notable); - fl_print_format("%[' cannot be processed because the max stack depth of%] ", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, stack_max, main.error.notable); - fl_print_format(" %[has been reached.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe section operation '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, operation_name, main->error.notable); + fl_print_format("%[' from section '%]", main->error.to.stream, main->error.context, buffer, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, section_name, main->error.notable); + fl_print_format("%[' on line%] ", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, line, main->error.notable); + fl_print_format("%[' cannot be processed because the max stack depth of%] ", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, stack_max, main->error.notable); + fl_print_format(" %[has been reached.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_message_section_operation_stack_max_ #ifndef _di_fake_print_message_section_operation_unknown_ - void fake_print_message_section_operation_unknown(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) { + void fake_print_message_section_operation_unknown(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) { - if (main.error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; + if (main->error.verbosity == f_console_verbosity_quiet || !print.to.stream) return; f_array_length_t line = 1; f_fss_count_lines(buffer, operation_name.start, &line); - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe section operation '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, operation_name, main.error.notable); - fl_print_format("%[' from section '%]", main.error.to.stream, main.error.context, buffer, main.error.context); - fl_print_format("%[%/Q%]", main.error.to.stream, main.error.notable, buffer, section_name, main.error.notable); - fl_print_format("%[' on line%] ", main.error.to.stream, main.error.context, main.error.context); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, line, main.error.notable); - fl_print_format(" %[is not a known operation name.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe section operation '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, operation_name, main->error.notable); + fl_print_format("%[' from section '%]", main->error.to.stream, main->error.context, buffer, main->error.context); + fl_print_format("%[%/Q%]", main->error.to.stream, main->error.notable, buffer, section_name, main->error.notable); + fl_print_format("%[' on line%] ", main->error.to.stream, main->error.context, main->error.context); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, line, main->error.notable); + fl_print_format(" %[is not a known operation name.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fake_print_message_section_operation_unknown_ +#ifndef _di_fake_print_signal_received_ + void fake_print_signal_received(fake_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fake_print_signal_received_ + #ifndef _di_fake_print_warning_settings_content_empty_ - void fake_print_warning_settings_content_empty(const fake_main_t main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_t settings_name) { + void fake_print_warning_settings_content_empty(fake_main_t * const main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_t settings_name) { - if (main.warning.verbosity == f_console_verbosity_quiet) return; + if (main->warning.verbosity == f_console_verbosity_quiet) return; - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe fakefile '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' has empty content for the '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_name, main.warning.notable); - fl_print_format("%[' object '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%/Q%]", main.warning.to.stream, main.warning.notable, buffer, range_object, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe fakefile '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' has empty content for the '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_name, main->warning.notable); + fl_print_format("%[' object '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%/Q%]", main->warning.to.stream, main->warning.notable, buffer, range_object, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } #endif // _di_fake_print_warning_settings_content_empty_ #ifndef _di_fake_print_warning_settings_content_invalid_ - void fake_print_warning_settings_content_invalid(const fake_main_t main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_range_t range_content, const f_string_t settings_name) { + void fake_print_warning_settings_content_invalid(fake_main_t * const main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_range_t range_content, const f_string_t settings_name) { - if (main.warning.verbosity == f_console_verbosity_quiet) return; + if (main->warning.verbosity == f_console_verbosity_quiet) return; - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe fakefile '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' has invalid content '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%/Q%]", main.warning.to.stream, main.warning.notable, buffer, range_content, main.warning.notable); - fl_print_format("%[' for the '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, settings_name, main.warning.notable); - fl_print_format("%[' object '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%/Q%]", main.warning.to.stream, main.warning.notable, buffer, range_object, main.warning.notable); - fl_print_format("%['.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe fakefile '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' has invalid content '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%/Q%]", main->warning.to.stream, main->warning.notable, buffer, range_content, main->warning.notable); + fl_print_format("%[' for the '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, settings_name, main->warning.notable); + fl_print_format("%[' object '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%/Q%]", main->warning.to.stream, main->warning.notable, buffer, range_object, main->warning.notable); + fl_print_format("%['.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } #endif // _di_fake_print_warning_settings_content_invalid_ #ifndef _di_fake_print_warning_settings_content_multiple_ - void fake_print_warning_settings_content_multiple(const fake_main_t main, const f_string_t path_file, const f_string_t name_object) { + void fake_print_warning_settings_content_multiple(fake_main_t * const main, const f_string_t path_file, const f_string_t name_object) { - if (main.warning.verbosity == f_console_verbosity_quiet) return; + if (main->warning.verbosity == f_console_verbosity_quiet) return; - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe fakefile '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, name_object, main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may only have a single property, only using the first.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe fakefile '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, name_object, main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may only have a single property, only using the first.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } #endif // _di_fake_print_warning_settings_content_multiple_ #ifndef _di_fake_print_warning_settings_object_multiple_ - void fake_print_warning_settings_object_multiple(const fake_main_t main, const f_string_t path_file, const f_string_t label, const f_string_t name_object) { + void fake_print_warning_settings_object_multiple(fake_main_t * const main, const f_string_t path_file, const f_string_t label, const f_string_t name_object) { - if (main.warning.verbosity == f_console_verbosity_quiet) return; + if (main->warning.verbosity == f_console_verbosity_quiet) return; - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%SThe object '%]", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, name_object, main.warning.notable); - fl_print_format("%[' in the file '%]", main.warning.to.stream, main.warning.context, main.warning.context); - fl_print_format("%[%S%]", main.warning.to.stream, main.warning.notable, path_file, main.warning.notable); - fl_print_format("%[' may only be specified once, only using the first.%]%c", main.warning.to.stream, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe object '%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, name_object, main->warning.notable); + fl_print_format("%[' in the file '%]", main->warning.to.stream, main->warning.context, main->warning.context); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, path_file, main->warning.notable); + fl_print_format("%[' may only be specified once, only using the first.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } #endif // _di_fake_print_warning_settings_object_multiple_ diff --git a/level_3/fake/c/private-print.h b/level_3/fake/c/private-print.h index 77d9204..d385b9a 100644 --- a/level_3/fake/c/private-print.h +++ b/level_3/fake/c/private-print.h @@ -16,7 +16,7 @@ extern "C" { * Print build operation file error messages. * * @param main - * The main data. + * The main program data. * @param status * The error status code to report on. * @param function @@ -41,14 +41,14 @@ extern "C" { * F_false is returned on successful print of known errors. */ #ifndef _di_fake_print_error_operation_file_ - extern bool fake_print_error_build_operation_file(const fake_main_t main, const f_status_t status, const f_string_t function, const f_string_t operation, const f_string_t source, const f_string_t destination, const f_string_t how, const bool fallback) F_attribute_visibility_internal_d; + extern bool fake_print_error_build_operation_file(fake_main_t * const main, const f_status_t status, const f_string_t function, const f_string_t operation, const f_string_t source, const f_string_t destination, const f_string_t how, const bool fallback) F_attribute_visibility_internal_d; #endif // _di_fake_print_error_operation_file_ /** * Print FSS error messages. * * @param main - * The main data. + * The main program data. * @param status * The error status code to report on. * @param function @@ -65,38 +65,38 @@ extern "C" { * F_false is returned on successful print of known errors. */ #ifndef _di_fake_print_error_fss_ - extern bool fake_print_error_fss(const fake_main_t main, const f_status_t status, const f_string_t function, const f_string_t path_file, const f_string_range_t range, const bool fallback) F_attribute_visibility_internal_d; + extern bool fake_print_error_fss(fake_main_t * const main, const f_status_t status, const f_string_t function, const f_string_t path_file, const f_string_range_t range, const bool fallback) F_attribute_visibility_internal_d; #endif // _di_fake_print_error_fss_ /** * Print an error message for when the parameter is missing its accompanying value. * * @param main - * The main data. + * The main program data. * @param parameter * The parameter name. */ #ifndef _di_fake_print_error_parameter_missing_value_ - extern void fake_print_error_parameter_missing_value(const fake_main_t main, const f_string_t parameter) F_attribute_visibility_internal_d; + extern void fake_print_error_parameter_missing_value(fake_main_t * const main, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fake_print_error_parameter_missing_value_ /** * Print an error message for when the parameter is specified too many times. * * @param main - * The main data. + * The main program data. * @param parameter * The parameter name. */ #ifndef _di_fake_print_error_parameter_too_many_ - extern void fake_print_error_parameter_too_many(const fake_main_t main, const f_string_t parameter) F_attribute_visibility_internal_d; + extern void fake_print_error_parameter_too_many(fake_main_t * const main, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fake_print_error_parameter_too_many_ /** * Print error messages when processing some fakefile section, for a specific line and operation, and that operation failed. * * @param main - * The main data. + * The main program data. * @param print * Designates how the section error/warning should be printed. * @param buffer @@ -107,14 +107,14 @@ extern "C" { * The range within the buffer representing the operation name within the section. */ #ifndef _di_fake_print_message_section_operation_failed_ - extern void fake_print_message_section_operation_failed(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) F_attribute_visibility_internal_d; + extern void fake_print_message_section_operation_failed(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) F_attribute_visibility_internal_d; #endif // _di_fake_print_message_section_operation_failed_ /** * Print error messages when processing some fakefile section, for a specific line and operation, and that operation has a path outside of the project root. * * @param main - * The main data. + * The main program data. * @param print * Designates how the section error/warning should be printed. * @param status @@ -125,14 +125,14 @@ extern "C" { * The path that is outside of the project path. */ #ifndef _di_fake_print_message_section_operation_path_outside_ - extern void fake_print_message_section_operation_path_outside(const fake_main_t main, const fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) F_attribute_visibility_internal_d; + extern void fake_print_message_section_operation_path_outside(fake_main_t * const main, const fl_print_t print, const f_status_t status, const f_string_t function, const f_string_t path) F_attribute_visibility_internal_d; #endif // _fake_print_message_section_operation_path_outside_ /** * Print error messages when processing some fakefile section, for a specific line and operation. * * @param main - * The main data. + * The main program data. * @param error * Designates how the section error/warning should be printed. * @param status @@ -144,14 +144,14 @@ extern "C" { * The path to the directory. */ #ifndef _di_fake_print_message_section_operation_path_stack_max_ - extern void fake_print_message_section_operation_path_stack_max(const fake_main_t main, fl_print_t error, const f_status_t status, const f_string_t function, const f_string_t path) F_attribute_visibility_internal_d; + extern void fake_print_message_section_operation_path_stack_max(fake_main_t * const main, fl_print_t error, const f_status_t status, const f_string_t function, const f_string_t path) F_attribute_visibility_internal_d; #endif // _di_fake_print_message_section_operation_path_stack_max_ /** * Print error messages when processing some fakefile section, for a specific line and operation, and that the max stack depth is reached. * * @param main - * The main data. + * The main program data. * @param print * Designates how the section error/warning should be printed. * @param buffer @@ -164,14 +164,14 @@ extern "C" { * The max stack depth. */ #ifndef _di_fake_print_message_section_operation_stack_max_ - extern void fake_print_message_section_operation_stack_max(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name, const f_array_length_t stack_max) F_attribute_visibility_internal_d; + extern void fake_print_message_section_operation_stack_max(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name, const f_array_length_t stack_max) F_attribute_visibility_internal_d; #endif // _di_fake_print_message_section_operation_stack_max_ /** * Print error messages when processing some fakefile section, for a specific line and operation, and that operation is invalid. * * @param main - * The main data. + * The main program data. * @param print * Designates how the section error/warning should be printed. * @param buffer @@ -182,14 +182,26 @@ extern "C" { * The range within the buffer representing the operation name within the section. */ #ifndef _di_fake_print_message_section_operation_unknown_ - extern void fake_print_message_section_operation_unknown(const fake_main_t main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) F_attribute_visibility_internal_d; + extern void fake_print_message_section_operation_unknown(fake_main_t * const main, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) F_attribute_visibility_internal_d; #endif // _di_fake_print_message_section_operation_unknown_ /** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fake_print_signal_received_ + extern void fake_print_signal_received(fake_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fake_print_signal_received_ + +/** * Print message when fake settings content is empty. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the fakefile. * @param buffer @@ -200,14 +212,14 @@ extern "C" { * The name of the setting that has an invalid value. */ #ifndef _di_fake_print_warning_settings_content_empty_ - extern void fake_print_warning_settings_content_empty(const fake_main_t main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_t settings_name) F_attribute_visibility_internal_d; + extern void fake_print_warning_settings_content_empty(fake_main_t * const main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_t settings_name) F_attribute_visibility_internal_d; #endif // _di_fake_print_warning_settings_content_empty_ /** * Print warning message when fake settings content is invalid. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the fakefile. * @param buffer @@ -220,14 +232,14 @@ extern "C" { * The name of the setting that has an invalid value. */ #ifndef _di_fake_print_warning_settings_content_invalid_ - extern void fake_print_warning_settings_content_invalid(const fake_main_t main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_range_t range_content, const f_string_t settings_name) F_attribute_visibility_internal_d; + extern void fake_print_warning_settings_content_invalid(fake_main_t * const main, const f_string_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_range_t range_content, const f_string_t settings_name) F_attribute_visibility_internal_d; #endif // _di_fake_print_warning_settings_content_invalid_ /** * Print warning message when settings content has too many values. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the fakefile. * @param buffer @@ -236,14 +248,14 @@ extern "C" { * The name of the object. */ #ifndef _di_fake_print_warning_settings_content_multiple_ - extern void fake_print_warning_settings_content_multiple(const fake_main_t main, const f_string_t path_file, const f_string_t name_object) F_attribute_visibility_internal_d; + extern void fake_print_warning_settings_content_multiple(fake_main_t * const main, const f_string_t path_file, const f_string_t name_object) F_attribute_visibility_internal_d; #endif // _di_fake_print_warning_settings_content_multiple_ /** * Print warning message when fakefile has too many objects with the same name. * * @param main - * The main data. + * The main program data. * @param path_file * The path to the fakefile. * @param buffer @@ -254,7 +266,7 @@ extern "C" { * The name of the object. */ #ifndef _di_fake_print_warning_settings_object_multiple_ - extern void fake_print_warning_settings_object_multiple(const fake_main_t main, const f_string_t path_file, const f_string_t label, const f_string_t name_object) F_attribute_visibility_internal_d; + extern void fake_print_warning_settings_object_multiple(fake_main_t * const main, const f_string_t path_file, const f_string_t label, const f_string_t name_object) F_attribute_visibility_internal_d; #endif // _di_fake_print_warning_settings_object_multiple_ #ifdef __cplusplus diff --git a/level_3/fake/c/private-skeleton.c b/level_3/fake/c/private-skeleton.c index 4c138fc..1a05d66 100644 --- a/level_3/fake/c/private-skeleton.c +++ b/level_3/fake/c/private-skeleton.c @@ -11,52 +11,49 @@ extern "C" { #endif #ifndef _di_fake_skeleton_operate_ - f_status_t fake_skeleton_operate(const fake_main_t main) { - - if (fake_signal_received(main)) { - return F_signal; - } + f_status_t fake_skeleton_operate(fake_main_t * const main) { f_status_t status = F_none; - if (main.output.verbosity != f_console_verbosity_quiet) { - fll_print_format("%cGenerating skeleton structure.%c", main.output.to.stream, f_string_eol_s[0], f_string_eol_s[0]); + if (main->output.verbosity != f_console_verbosity_quiet) { + fll_print_format("%cGenerating skeleton structure.%c", main->output.to.stream, f_string_eol_s[0], f_string_eol_s[0]); } { const f_string_dynamic_t *parameters_value[] = { - &main.path_build, - &main.path_data, - &main.path_data_build, - &main.path_data_settings, - &main.path_documents, - &main.path_licenses, - &main.path_sources, - &main.path_sources_bash, - &main.path_sources_c, - &main.path_sources_cpp, - &main.path_work, - &main.path_work_includes, - &main.path_work_libraries, - &main.path_work_libraries_script, - &main.path_work_libraries_shared, - &main.path_work_libraries_static, - &main.path_work_programs, - &main.path_work_programs_script, - &main.path_work_programs_shared, - &main.path_work_programs_static, + &main->path_build, + &main->path_data, + &main->path_data_build, + &main->path_data_settings, + &main->path_documents, + &main->path_licenses, + &main->path_sources, + &main->path_sources_bash, + &main->path_sources_c, + &main->path_sources_cpp, + &main->path_work, + &main->path_work_includes, + &main->path_work_libraries, + &main->path_work_libraries_script, + &main->path_work_libraries_shared, + &main->path_work_libraries_static, + &main->path_work_programs, + &main->path_work_programs_script, + &main->path_work_programs_shared, + &main->path_work_programs_static, }; for (uint8_t i = 0; i < 20; ++i) { if (fake_signal_received(main)) { - return F_status_set_error(F_signal); + return F_status_set_error(F_interrupt); } status = fake_skeleton_operate_directory_create(main, *parameters_value[i]); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fake_skeleton_operate_directory_create", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fake_skeleton_operate_directory_create", F_true); + return status; } } // for @@ -66,89 +63,90 @@ extern "C" { f_string_dynamic_t file_data_build_process_pre = f_string_dynamic_t_initialize; f_string_dynamic_t content = f_string_dynamic_t_initialize; - if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); - } - if (F_status_is_error_not(status)) { + if (fake_signal_received(main)) { + status = F_status_set_error(F_interrupt); + } + content.string = fake_make_skeleton_content_defines_s; content.used = fake_make_skeleton_content_defines_s_length; content.size = content.used; - status = fake_skeleton_operate_file_create(main, main.file_data_build_defines, F_false, content); + status = fake_skeleton_operate_file_create(main, main->file_data_build_defines, F_false, content); content.used = 0; } if (F_status_is_error_not(status)) { + if (fake_signal_received(main)) { + status = F_status_set_error(F_interrupt); + } + content.string = fake_make_skeleton_content_dependencies_s; content.used = fake_make_skeleton_content_dependencies_s_length; content.size = content.used; - status = fake_skeleton_operate_file_create(main, main.file_data_build_dependencies, F_false, content); + status = fake_skeleton_operate_file_create(main, main->file_data_build_dependencies, F_false, content); content.used = 0; + } + if (F_status_is_error_not(status)) { if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); + status = F_status_set_error(F_interrupt); } - } - if (F_status_is_error_not(status)) { status = fake_skeleton_operate_file_create(main, file_data_build_process_post, F_true, content); + } + if (F_status_is_error_not(status)) { if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); + status = F_status_set_error(F_interrupt); } - } - if (F_status_is_error_not(status)) { status = fake_skeleton_operate_file_create(main, file_data_build_process_pre, F_true, content); + } + if (F_status_is_error_not(status)) { if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); + status = F_status_set_error(F_interrupt); } - } - if (F_status_is_error_not(status)) { content.string = fake_make_skeleton_content_settings_s; content.used = fake_make_skeleton_content_settings_s_length; content.size = content.used; - status = fake_skeleton_operate_file_create(main, main.file_data_build_settings, F_false, content); + status = fake_skeleton_operate_file_create(main, main->file_data_build_settings, F_false, content); content.used = 0; + } + if (F_status_is_error_not(status)) { if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); + status = F_status_set_error(F_interrupt); } + + status = fake_skeleton_operate_file_create(main, main->file_documents_readme, F_false, content); } if (F_status_is_error_not(status)) { - status = fake_skeleton_operate_file_create(main, main.file_documents_readme, F_false, content); - if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); + status = F_status_set_error(F_interrupt); } - } - if (F_status_is_error_not(status)) { content.string = fake_make_skeleton_content_fakefile_s; content.used = fake_make_skeleton_content_fakefile_s_length; content.size = content.used; - status = fake_skeleton_operate_file_create(main, main.file_data_build_fakefile, F_false, content); + status = fake_skeleton_operate_file_create(main, main->file_data_build_fakefile, F_false, content); content.used = 0; - - if (fake_signal_received(main)) { - status = F_status_set_error(F_signal); - } } if (F_status_is_error(status)) { macro_f_string_dynamic_t_delete_simple(file_data_build_process_post); macro_f_string_dynamic_t_delete_simple(file_data_build_process_pre); + return status; } @@ -157,7 +155,7 @@ extern "C" { #endif // _di_fake_skeleton_operate_ #ifndef _di_fake_skeleton_operate_directory_create_ - f_status_t fake_skeleton_operate_directory_create(const fake_main_t main, const f_string_dynamic_t path) { + f_status_t fake_skeleton_operate_directory_create(fake_main_t * const main, const f_string_dynamic_t path) { f_status_t status = F_none; @@ -166,22 +164,22 @@ extern "C" { status = f_directory_exists(path.string); if (status == F_true) { - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Directory '%Q' already exists.%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Directory '%Q' already exists.%c", main->output.to.stream, path, f_string_eol_s[0]); } return F_none; } if (status == F_false) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%[' exists but is not a directory.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%[' exists but is not a directory.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_status_set_warning(F_failure); @@ -191,27 +189,27 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_file_found_not) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe path '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe path '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } else { - fll_error_file_print(main.error, F_status_set_fine(status), "f_directory_create", F_true, path.string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(status), "f_directory_create", F_true, path.string, "create", fll_error_file_type_directory); } return status; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("Directory '%Q' created.%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("Directory '%Q' created.%c", main->output.to.stream, path, f_string_eol_s[0]); } } else if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_directory_exists", F_true, path.string, "create", fll_error_file_type_directory); + fll_error_file_print(main->error, F_status_set_fine(status), "f_directory_exists", F_true, path.string, "create", fll_error_file_type_directory); return status; } @@ -221,7 +219,7 @@ extern "C" { #endif // _di_fake_skeleton_operate_directory_create_ #ifndef _di_fake_skeleton_operate_file_create_ - f_status_t fake_skeleton_operate_file_create(const fake_main_t main, const f_string_dynamic_t path, const bool executable, const f_string_static_t content) { + f_status_t fake_skeleton_operate_file_create(fake_main_t * const main, const f_string_dynamic_t path, const bool executable, const f_string_static_t content) { f_status_t status = F_none; @@ -230,8 +228,8 @@ extern "C" { status = f_file_is(path.string, F_file_type_regular_d, F_false); if (status == F_true) { - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("File '%Q' already exists.%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("File '%Q' already exists.%c", main->output.to.stream, path, f_string_eol_s[0]); } return F_none; @@ -242,8 +240,8 @@ extern "C" { status = f_file_is(path.string, F_file_type_link_d, F_false); if (status == F_true) { - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("File '%Q' already exists (as a symbolic link).%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("File '%Q' already exists (as a symbolic link).%c", main->output.to.stream, path, f_string_eol_s[0]); } return F_none; @@ -251,8 +249,8 @@ extern "C" { } if (status == F_false) { - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("File '%Q' already exists but is not a regular file (or symbolic link).%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("File '%Q' already exists but is not a regular file (or symbolic link).%c", main->output.to.stream, path, f_string_eol_s[0]); } return F_status_set_warning(F_none); @@ -268,23 +266,23 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_file_found_not) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%SThe file '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, path, main.error.notable); - fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%SThe file '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, path, main->error.notable); + fl_print_format("%[' could not be created, a parent directory does not exist.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } else { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_create", F_true, path.string, "create", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_create", F_true, path.string, "create", fll_error_file_type_file); } return status; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("File '%Q' created.%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("File '%Q' created.%c", main->output.to.stream, path, f_string_eol_s[0]); } if (content.used) { @@ -296,7 +294,7 @@ extern "C" { status = f_file_open(path.string, 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_open", F_true, path.string, "pre-populate", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, path.string, "pre-populate", fll_error_file_type_file); return status; } @@ -304,21 +302,21 @@ extern "C" { status = f_file_write(file, content, 0); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_write", F_true, path.string, "pre-populate", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_write", F_true, path.string, "pre-populate", fll_error_file_type_file); f_file_stream_close(F_true, &file); return status; } - if (main.error.verbosity == f_console_verbosity_verbose) { - fll_print_format("File '%Q' pre-populated.%c", main.output.to.stream, path, f_string_eol_s[0]); + if (main->error.verbosity == f_console_verbosity_verbose) { + fll_print_format("File '%Q' pre-populated.%c", main->output.to.stream, path, f_string_eol_s[0]); } f_file_stream_close(F_true, &file); } } else if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_is", F_true, path.string, "create", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_is", F_true, path.string, "create", fll_error_file_type_file); return status; } diff --git a/level_3/fake/c/private-skeleton.h b/level_3/fake/c/private-skeleton.h index c56ede7..b28af74 100644 --- a/level_3/fake/c/private-skeleton.h +++ b/level_3/fake/c/private-skeleton.h @@ -16,22 +16,24 @@ extern "C" { * Execute the skeleton operation. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_skeleton_operate_ - extern f_status_t fake_skeleton_operate(const fake_main_t main) F_attribute_visibility_internal_d; + extern f_status_t fake_skeleton_operate(fake_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fake_skeleton_operate_ /** * Create a directory if it does not exist, ignore it if it does, and warn if path exists but is not a directory. * * @param main - * The main data. + * The main program data. * @param path * The file path for the directory to create. * @@ -42,14 +44,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_skeleton_operate_directory_create_ - extern f_status_t fake_skeleton_operate_directory_create(const fake_main_t main, const f_string_dynamic_t path) F_attribute_visibility_internal_d; + extern f_status_t fake_skeleton_operate_directory_create(fake_main_t * const main, const f_string_dynamic_t path) F_attribute_visibility_internal_d; #endif // _di_fake_skeleton_operate_directory_create_ /** * Create a file if it does not exist, ignore it if it does, and warn if path exists but is not a file. * * @param main - * The main data. + * The main program data. * @param path * The file path for the directory to create. * @param executable @@ -65,7 +67,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_skeleton_operate_file_create_ - extern f_status_t fake_skeleton_operate_file_create(const fake_main_t main, const f_string_dynamic_t path, const bool executable, const f_string_static_t content) F_attribute_visibility_internal_d; + extern f_status_t fake_skeleton_operate_file_create(fake_main_t * const main, const f_string_dynamic_t path, const bool executable, const f_string_static_t content) F_attribute_visibility_internal_d; #endif // _di_fake_skeleton_operate_file_create_ #ifdef __cplusplus diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c index 53f8df0..aba852e 100644 --- a/level_3/firewall/c/firewall.c +++ b/level_3/firewall/c/firewall.c @@ -45,7 +45,8 @@ extern "C" { #endif // _di_firewall_print_help_ #ifndef _di_firewall_main_ - f_status_t firewall_main(const f_console_arguments_t arguments, firewall_main_t *main) { + f_status_t firewall_main(firewall_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -55,7 +56,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { firewall_parameter_no_color, firewall_parameter_light, firewall_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -79,6 +80,7 @@ extern "C" { if (F_status_is_error(status)) { firewall_main_delete(main); + return F_status_set_error(status); } } @@ -93,6 +95,7 @@ extern "C" { if (F_status_is_error(status)) { firewall_main_delete(main); + return status; } @@ -125,6 +128,7 @@ extern "C" { firewall_print_help(main->output.to, main->context); firewall_main_delete(main); + return F_none; } @@ -132,6 +136,7 @@ extern "C" { fll_program_print_version(main->output.to, firewall_version_s); firewall_main_delete(main); + return F_none; } @@ -216,13 +221,13 @@ extern "C" { for (; counter < main->remaining.used; ++counter) { - if (strncmp("nat", arguments.argv[main->remaining.array[counter]], 4) != 0) { - if (strncmp("mangle", arguments.argv[main->remaining.array[counter]], 7) != 0) { - if (strncmp("ports", arguments.argv[main->remaining.array[counter]], 6) != 0) { + if (strncmp("nat", arguments->argv[main->remaining.array[counter]], 4) != 0) { + if (strncmp("mangle", arguments->argv[main->remaining.array[counter]], 7) != 0) { + if (strncmp("ports", arguments->argv[main->remaining.array[counter]], 6) != 0) { flockfile(main->warning.to.stream); fl_print_format("%c%[%S'%]", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, main->warning.context); - fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, arguments.argv[main->remaining.array[counter]], main->warning.notable); + fl_print_format("%[%S%]", main->warning.to.stream, main->warning.notable, arguments->argv[main->remaining.array[counter]], main->warning.notable); fl_print_format("%[' is not a valid show option.%]%c", main->warning.to.stream, main->warning.context, main->warning.context, f_string_eol_s[0]); funlockfile(main->warning.to.stream); @@ -249,6 +254,7 @@ extern "C" { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -372,6 +378,7 @@ extern "C" { macro_f_string_dynamics_t_delete_simple( parameters); firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -395,6 +402,7 @@ extern "C" { firewall_delete_local_data(&local); firewall_main_delete(main); + return F_status_set_error(status); } @@ -419,11 +427,12 @@ extern "C" { } if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart || command == firewall_parameter_command_lock) { - status = firewall_buffer_rules(network_path_s firewall_file_other_s, F_false, &local, main); + status = firewall_buffer_rules(main, network_path_s firewall_file_other_s, F_false, &local); if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -447,15 +456,16 @@ extern "C" { if (command == firewall_parameter_command_lock) { if (reserved.has_lock) { - status = firewall_delete_chains(*main); + status = firewall_delete_chains(main); if (F_status_is_error_not(status)) { - status = firewall_default_lock(*main); + status = firewall_default_lock(main); } if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -467,10 +477,11 @@ extern "C" { input.start = local.chain_contents.array[reserved.lock_at].array[0].start; input.stop = local.chain_contents.array[reserved.lock_at].array[0].stop; - status = firewall_process_rules(&input, &local, main); + status = firewall_process_rules(main, &input, &local); firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } else { @@ -480,21 +491,23 @@ extern "C" { firewall_delete_local_data(&local); firewall_main_delete(main); + return F_status_set_error(F_data); } } if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart) { if (reserved.has_stop) { - status = firewall_delete_chains(*main); + status = firewall_delete_chains(main); if (F_status_is_error_not(status)) { - status = firewall_default_lock(*main); + status = firewall_default_lock(main); } if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -507,11 +520,12 @@ extern "C" { input.start = local.chain_contents.array[reserved.stop_at].array[0].start; input.stop = local.chain_contents.array[reserved.stop_at].array[0].stop; - status = firewall_process_rules(&input, &local, main); + status = firewall_process_rules(main, &input, &local); if (F_status_is_error(status) || command == firewall_parameter_command_stop) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } } @@ -522,6 +536,7 @@ extern "C" { firewall_delete_local_data(&local); firewall_main_delete(main); + return F_status_set_error(F_data); } } @@ -530,33 +545,36 @@ extern "C" { } if (command == firewall_parameter_command_start || command == firewall_parameter_command_restart) { - status = firewall_buffer_rules(network_path_s firewall_file_first_s, F_false, &local, main); + status = firewall_buffer_rules(main, network_path_s firewall_file_first_s, F_false, &local); if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } if (command == firewall_parameter_command_start) { - status = firewall_delete_chains(*main); + status = firewall_delete_chains(main); if (F_status_is_error_not(status)) { - status = firewall_default_lock(*main); + status = firewall_default_lock(main); } if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } } - status = firewall_create_custom_chains(&reserved, &local, main); + status = firewall_create_custom_chains(main, &reserved, &local); if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -574,11 +592,12 @@ extern "C" { local.is_main = reserved.has_main && i == reserved.main_at ? F_true : F_false; local.chain = i; - status = firewall_process_rules(&input, &local, main); + status = firewall_process_rules(main, &input, &local); if (F_status_is_error(status) || command == firewall_parameter_command_stop) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -600,6 +619,7 @@ extern "C" { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -610,7 +630,7 @@ extern "C" { file_path.used = network_path_s_length + main->devices.array[i].used + firewall_file_suffix_s_length; file_path.string[file_path.used] = 0; - status = firewall_buffer_rules(file_path.string, F_true, &local, main); + status = firewall_buffer_rules(main, file_path.string, F_true, &local); macro_f_string_dynamic_t_delete_simple(file_path); } @@ -626,14 +646,16 @@ extern "C" { } firewall_main_delete(main); + return F_status_set_error(status); } - status = firewall_create_custom_chains(&reserved, &local, main); + status = firewall_create_custom_chains(main, &reserved, &local); if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -651,11 +673,12 @@ extern "C" { local.is_main = reserved.has_main && j == reserved.main_at ? F_true : F_false; local.chain = j; - status = firewall_process_rules(&input, &local, main); + status = firewall_process_rules(main, &input, &local); if (F_status_is_error(status) || command == firewall_parameter_command_stop) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } } // for @@ -663,21 +686,23 @@ extern "C" { firewall_delete_local_data(&local); } // for - status = firewall_buffer_rules(network_path_s firewall_file_last_s, F_false, &local, main); + status = firewall_buffer_rules(main, network_path_s firewall_file_last_s, F_false, &local); if (F_status_is_error(status)) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } - status = firewall_create_custom_chains(&reserved, &local, main); + status = firewall_create_custom_chains(main, &reserved, &local); if (F_status_is_error(status)) { f_status_t status2 = F_none; macro_firewall_delete_fss_buffers(status2, local.buffer, local.chain_objects, local.chain_contents) firewall_main_delete(main); + return status; } @@ -695,11 +720,12 @@ extern "C" { local.is_main = reserved.has_main && i == reserved.main_at ? F_true : F_false; local.chain = i; - status = firewall_process_rules(&input, &local, main); + status = firewall_process_rules(main, &input, &local); if (F_status_is_error(status) || command == firewall_parameter_command_stop) { firewall_delete_local_data(&local); firewall_main_delete(main); + return status; } @@ -718,13 +744,22 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + firewall_main_delete(main); + return status; } #endif // _di_firewall_main_ #ifndef _di_firewall_main_delete_ - f_status_t firewall_main_delete(firewall_main_t *main) { + f_status_t firewall_main_delete(firewall_main_t * const main) { for (f_array_length_t i = 0; i < firewall_total_parameters_d; ++i) { diff --git a/level_3/firewall/c/firewall.h b/level_3/firewall/c/firewall.h index 7cfc095..c4e263d 100644 --- a/level_3/firewall/c/firewall.h +++ b/level_3/firewall/c/firewall.h @@ -31,6 +31,7 @@ #include #include #include +#include // fll-1 includes #include @@ -291,6 +292,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_string_dynamics_t chains; f_string_dynamics_t devices; @@ -305,6 +308,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_dynamics_t_initialize, \ f_string_dynamics_t_initialize, \ f_color_context_t_initialize, \ @@ -331,20 +335,30 @@ extern "C" { * * Be sure to call firewall_main_delete() after executing this. * + * 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 data + * The main program data. * @param arguments * The parameters passed to the process. - * @param data - * The main data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. * * @see firewall_main_delete() */ #ifndef _di_firewall_main_ - extern f_status_t firewall_main(const f_console_arguments_t arguments, firewall_main_t *data); + extern f_status_t firewall_main(firewall_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_firewall_main_ /** @@ -353,7 +367,7 @@ extern "C" { * Be sure to call this after executing firewall_main(). * * @param data - * The main data. + * The main program data. * * @return * F_none on success. @@ -363,7 +377,7 @@ extern "C" { * @see firewall_main() */ #ifndef _di_firewall_main_delete_ - extern f_status_t firewall_main_delete(firewall_main_t *data); + extern f_status_t firewall_main_delete(firewall_main_t * const data); #endif // _di_firewall_main_delete_ #ifdef __cplusplus diff --git a/level_3/firewall/c/main.c b/level_3/firewall/c/main.c index 6b3f60b..2d0568f 100644 --- a/level_3/firewall/c/main.c +++ b/level_3/firewall/c/main.c @@ -9,7 +9,43 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - if (F_status_is_error(firewall_main(arguments, &data))) { + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = firewall_main(&data, &arguments); + + // Flush output pipes before closing. + fflush(F_type_output_d); + fflush(F_type_error_d); + + // Close all open file descriptors. + close(F_type_descriptor_output_d); + close(F_type_descriptor_input_d); + close(F_type_descriptor_error_d); + + f_signal_close(&data.signal); + + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/firewall/c/private-common.c b/level_3/firewall/c/private-common.c index 1104364..07a4227 100644 --- a/level_3/firewall/c/private-common.c +++ b/level_3/firewall/c/private-common.c @@ -75,6 +75,53 @@ void firewall_print_error_on_unhandled_for_file(const fl_print_t output, const f fll_print_format("%c%[%sAn unhandled error (%ui) has occurred while calling %S() for the file '%S'.%]%c", output.to.stream, f_string_eol_s[0], output.context, output.prefix, status, function, filename, output.context, f_string_eol_s[0]); } +#ifndef _di_firewall_print_signal_received_ + void firewall_print_signal_received(firewall_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_firewall_print_signal_received_ + +#ifndef _di_firewall_signal_received_ + f_status_t firewall_signal_received(firewall_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + firewall_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_firewall_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/firewall/c/private-common.h b/level_3/firewall/c/private-common.h index 8b250ed..8b3327b 100644 --- a/level_3/firewall/c/private-common.h +++ b/level_3/firewall/c/private-common.h @@ -178,6 +178,36 @@ extern void firewall_print_error_on_unhandled(const fl_print_t output, const f_s */ extern void firewall_print_error_on_unhandled_for_file(const fl_print_t output, const f_string_t function, const f_status_t status, const f_string_t filename) F_attribute_visibility_internal_d; +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_firewall_print_signal_received_ + extern void firewall_print_signal_received(firewall_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_firewall_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_firewall_signal_received_ + extern f_status_t firewall_signal_received(firewall_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_firewall_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c index c67abb3..7f94ce6 100644 --- a/level_3/firewall/c/private-firewall.c +++ b/level_3/firewall/c/private-firewall.c @@ -6,7 +6,8 @@ extern "C" { #endif -f_status_t firewall_perform_commands(const firewall_local_data_t local, const firewall_main_t main) { +f_status_t firewall_perform_commands(firewall_main_t * const main, const firewall_local_data_t local) { + f_status_t status = F_none; f_array_length_t i = 0; @@ -41,8 +42,8 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi device_all = F_true; } else { - if (main.devices.array[local.device].used > 0) { - macro_f_string_dynamic_t_resize(status, device, main.devices.array[local.device].used); + if (main->devices.array[local.device].used > 0) { + macro_f_string_dynamic_t_resize(status, device, main->devices.array[local.device].used); if (F_status_is_error(status)) { macro_f_string_dynamic_t_delete_simple(device); @@ -50,8 +51,8 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi return status; } - macro_firewall_concat_string(device.string, main.devices.array[local.device].string, main.devices.array[local.device].used); - device.used = main.devices.array[local.device].used; + macro_firewall_concat_string(device.string, main->devices.array[local.device].string, main->devices.array[local.device].used); + device.used = main->devices.array[local.device].used; } } @@ -61,6 +62,19 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi } for (; i < local.rule_objects.used; ++i) { + + status = firewall_signal_received(main); + + if (status) { + macro_f_string_dynamic_t_delete_simple(ip_list); + macro_f_string_dynamic_t_delete_simple(argument); + macro_f_string_dynamics_t_delete_simple(arguments); + macro_f_string_dynamic_t_delete_simple(device); + macro_f_string_dynamic_t_delete_simple(protocol); + + return F_status_set_error(F_interrupt); + } + length = macro_firewall_structure_size(local.rule_objects, i); invalid = F_false; @@ -74,7 +88,7 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi if (chain == firewall_chain_custom_id) { // custom chains can only apply to themselves, so silently ignore chain commands specified within a custom chain. - fll_print_format("%c%[%sAt line %ul, the chain option is meaningless inside of a custom chain.%]%c", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, f_string_eol_s[0]); + fll_print_format("%c%[%sAt line %ul, the chain option is meaningless inside of a custom chain.%]%c", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, f_string_eol_s[0]); continue; } @@ -143,16 +157,16 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi continue; } else if (length >= firewall_device_this_s_length && fl_string_compare(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string_t) firewall_device_this_s, length, firewall_device_this_s_length) == F_equal_to) { - if (main.devices.array[local.device].used > 0) { - if (main.devices.array[local.device].used > device.size) { - macro_f_string_dynamic_t_resize(status, device, main.devices.array[local.device].used); + if (main->devices.array[local.device].used > 0) { + if (main->devices.array[local.device].used > device.size) { + macro_f_string_dynamic_t_resize(status, device, main->devices.array[local.device].used); if (F_status_is_error(status)) break; } - macro_firewall_concat_string(device.string, main.devices.array[local.device].string, main.devices.array[local.device].used); + macro_firewall_concat_string(device.string, main->devices.array[local.device].string, main->devices.array[local.device].used); - device.used = main.devices.array[local.device].used; + device.used = main->devices.array[local.device].used; } else { macro_f_string_dynamic_t_delete_simple(device); @@ -284,16 +298,16 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi // process rule rule, if the remaining rule does not match as firewall_rule_s, then it is an invalid rule. else if (length < firewall_rule_s_length || fl_string_compare(local.buffer.string + local.rule_objects.array[i].start, (f_string_t) firewall_rule_s, length, firewall_rule_s_length) == F_equal_to_not) { if (length) { - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%sAt line %ul, the object '%]%[", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, main.warning.notable); - f_print(local.buffer.string + local.rule_objects.array[i].start, length, main.warning.to.stream); - fl_print_format("%]%[' is invalid.%]%c", main.warning.to.stream, main.warning.notable, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%sAt line %ul, the object '%]%[", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, main->warning.notable); + f_print(local.buffer.string + local.rule_objects.array[i].start, length, main->warning.to.stream); + fl_print_format("%]%[' is invalid.%]%c", main->warning.to.stream, main->warning.notable, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } else { - fll_print_format("%c%[%sAt line %ul, the object is missing.%]%c", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, f_string_eol_s[0]); + fll_print_format("%c%[%sAt line %ul, the object is missing.%]%c", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, f_string_eol_s[0]); } continue; @@ -303,18 +317,18 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi length = macro_firewall_structure_size(local.rule_objects, i); if (length) { - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%sAt line %ul, the object '%]%[", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, main.warning.notable); - f_print(local.buffer.string + local.rule_objects.array[i].start, length, main.warning.to.stream); - fl_print_format("%]%[' has invalid content '%]%[", main.warning.to.stream, main.warning.notable, main.warning.context, main.warning.context, main.warning.notable); - f_print(local.buffer.string + local.rule_contents.array[i].array[0].start, macro_firewall_structure_size(local.rule_contents.array[i], 0), main.warning.to.stream); - fl_print_format("%]%['.%]%c", main.warning.to.stream, main.warning.notable, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%sAt line %ul, the object '%]%[", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, main->warning.notable); + f_print(local.buffer.string + local.rule_objects.array[i].start, length, main->warning.to.stream); + fl_print_format("%]%[' has invalid content '%]%[", main->warning.to.stream, main->warning.notable, main->warning.context, main->warning.context, main->warning.notable); + f_print(local.buffer.string + local.rule_contents.array[i].array[0].start, macro_firewall_structure_size(local.rule_contents.array[i], 0), main->warning.to.stream); + fl_print_format("%]%['.%]%c", main->warning.to.stream, main->warning.notable, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); } else { - fll_print_format("%c%[%sAt line %ul, the object has no content.%]%c", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, f_string_eol_s[0]); + fll_print_format("%c%[%sAt line %ul, the object has no content.%]%c", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, f_string_eol_s[0]); } continue; @@ -322,6 +336,18 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi for (r = repeat; r > 0; --r) { + status = firewall_signal_received(main); + + if (status) { + macro_f_string_dynamic_t_delete_simple(ip_list); + macro_f_string_dynamic_t_delete_simple(argument); + macro_f_string_dynamics_t_delete_simple(arguments); + macro_f_string_dynamic_t_delete_simple(device); + macro_f_string_dynamic_t_delete_simple(protocol); + + return F_status_set_error(F_interrupt); + } + // first add the program name f_string_dynamics_resize(0, &arguments); @@ -379,13 +405,13 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi // process the chain, which is required by the action. if (chain == firewall_chain_custom_id) { - if (main.chains.array[local.chain_ids.array[local.chain]].used > 0) { - macro_f_string_dynamic_t_resize(status, argument, main.chains.array[local.chain_ids.array[local.chain]].used); + if (main->chains.array[local.chain_ids.array[local.chain]].used > 0) { + macro_f_string_dynamic_t_resize(status, argument, main->chains.array[local.chain_ids.array[local.chain]].used); if (F_status_is_error(status)) break; - macro_firewall_concat_string(argument.string, main.chains.array[local.chain_ids.array[local.chain]].string, main.chains.array[local.chain_ids.array[local.chain]].used); - argument.used = main.chains.array[local.chain_ids.array[local.chain]].used; + macro_firewall_concat_string(argument.string, main->chains.array[local.chain_ids.array[local.chain]].string, main->chains.array[local.chain_ids.array[local.chain]].used); + argument.used = main->chains.array[local.chain_ids.array[local.chain]].used; } } else if (chain == firewall_chain_forward_id) { @@ -557,13 +583,13 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi else { length = macro_firewall_structure_size(local.rule_objects, i); - flockfile(main.warning.to.stream); + flockfile(main->warning.to.stream); - fl_print_format("%c%[%sAt line %ul, the object '%]%[", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, i, main.warning.context, main.warning.notable); - f_print(local.buffer.string + local.rule_objects.array[i].start, length, main.warning.to.stream); - fl_print_format("%]%[' has no content.%]%c", main.warning.to.stream, main.warning.notable, main.warning.context, main.warning.context, f_string_eol_s[0]); + fl_print_format("%c%[%sAt line %ul, the object '%]%[", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, i, main->warning.context, main->warning.notable); + f_print(local.buffer.string + local.rule_objects.array[i].start, length, main->warning.to.stream); + fl_print_format("%]%[' has no content.%]%c", main->warning.to.stream, main->warning.notable, main->warning.context, main->warning.context, f_string_eol_s[0]); - funlockfile(main.warning.to.stream); + funlockfile(main->warning.to.stream); break; } @@ -593,34 +619,34 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi status = F_status_set_fine(status); if (status == F_parameter) { - if (main.error.verbosity != f_console_verbosity_quiet) { - firewall_print_error_on_invalid_parameter(main.error, "f_file_open"); + if (main->error.verbosity != f_console_verbosity_quiet) { + firewall_print_error_on_invalid_parameter(main->error, "f_file_open"); } } else if (status == F_file_found_not) { // the file does not have to exist - if (main.error.verbosity != f_console_verbosity_verbose || main.error.verbosity == f_console_verbosity_debug) { - fll_print_format("%c%[%sCannot find the file '%Q'.%]%c", main.warning.to.stream, f_string_eol_s[0], main.warning.context, main.warning.prefix, file_path, main.warning.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_verbose || main->error.verbosity == f_console_verbosity_debug) { + fll_print_format("%c%[%sCannot find the file '%Q'.%]%c", main->warning.to.stream, f_string_eol_s[0], main->warning.context, main->warning.prefix, file_path, main->warning.context, f_string_eol_s[0]); } status = F_none; } else if (status == F_file_open) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sUnable to open the file '%Q'.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sUnable to open the file '%Q'.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } } else if (status == F_file_descriptor) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sFile descriptor error while trying to open the file '%Q'.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sFile descriptor error while trying to open the file '%Q'.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } } else if (status == F_memory_not) { - firewall_print_error_on_allocation_failure(main.error); + firewall_print_error_on_allocation_failure(main->error); } else { - firewall_print_error_on_unhandled(main.error, "f_file_open", status); + firewall_print_error_on_unhandled(main->error, "f_file_open", status); } if (status != F_file_found_not) { @@ -637,27 +663,27 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi if (F_status_is_error(status)) { status = F_status_set_fine(status); - if (main.error.verbosity != f_console_verbosity_quiet) { + if (main->error.verbosity != f_console_verbosity_quiet) { if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "f_file_read"); + firewall_print_error_on_invalid_parameter(main->error, "f_file_read"); } else if (status == F_number_overflow) { - fll_print_format("%c%[%sInteger overflow while trying to buffer the file '%Q'.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + fll_print_format("%c%[%sInteger overflow while trying to buffer the file '%Q'.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } else if (status == F_file_closed) { - fll_print_format("%c%[%sThe file '%Q' is no longer open.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + fll_print_format("%c%[%sThe file '%Q' is no longer open.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } else if (status == F_file_seek) { - fll_print_format("%c%[%sA seek error occurred while accessing the file '%Q'.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + fll_print_format("%c%[%sA seek error occurred while accessing the file '%Q'.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } else if (status == F_file_read) { - fll_print_format("%c%[%sA read error occurred while accessing the file '%Q'.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, file_path, main.error.context, f_string_eol_s[0]); + fll_print_format("%c%[%sA read error occurred while accessing the file '%Q'.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, file_path, main->error.context, f_string_eol_s[0]); } else if (status == F_memory_not) { - firewall_print_error_on_allocation_failure(main.error); + firewall_print_error_on_allocation_failure(main->error); } else { - firewall_print_error_on_unhandled(main.error, "f_file_read", status); + firewall_print_error_on_unhandled(main->error, "f_file_read", status); } } @@ -677,16 +703,16 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi status = F_status_set_fine(status); if (status == F_parameter) { - firewall_print_error_on_invalid_parameter_for_file(main.error, "fll_fss_basic_read", file_path.used ? file_path.string : ""); + firewall_print_error_on_invalid_parameter_for_file(main->error, "fll_fss_basic_read", file_path.used ? file_path.string : ""); } else if (status == F_data_not_eos || status == F_data_not || status == F_data_not_stop) { // empty files are to be silently ignored } else if (status == F_memory_not) { - firewall_print_error_on_allocation_failure(main.error); + firewall_print_error_on_allocation_failure(main->error); } else { - firewall_print_error_on_unhandled_for_file(main.error, "fll_fss_basic_read", status, file_path.used ? file_path.string : ""); + firewall_print_error_on_unhandled_for_file(main->error, "fll_fss_basic_read", status, file_path.used ? file_path.string : ""); } status = F_status_set_error(status); @@ -696,7 +722,7 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi status = fl_fss_apply_delimit(delimits, &local_buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); } } @@ -728,7 +754,7 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi } if (F_status_is_error(status)) { - firewall_print_error_on_allocation_failure(main.error); + firewall_print_error_on_allocation_failure(main->error); macro_f_string_dynamic_t_delete_simple(ip_list_action); } @@ -749,7 +775,7 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi macro_f_string_dynamic_t_resize(status, ip_argument, ip_length); if (F_status_is_error(status)) { - firewall_print_error_on_allocation_failure(main.error); + firewall_print_error_on_allocation_failure(main->error); break; } @@ -760,25 +786,31 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi macro_firewall_append_argument_to_arguments(status, arguments, ip_argument) if (F_status_is_error(status)) break; - firewall_print_debug_tool(main.warning, current_tool, arguments); + firewall_print_debug_tool(main->warning, current_tool, arguments); status = fll_execute_program((f_string_t) current_tool, arguments, 0, 0, (void *) &return_code); // immediately exit child process, @todo this may require additional memory deallocation and relating changes. if (status == F_child) { + macro_f_string_dynamic_t_delete_simple(ip_list); + macro_f_string_dynamic_t_delete_simple(argument); + macro_f_string_dynamics_t_delete_simple(arguments); + macro_f_string_dynamic_t_delete_simple(device); + macro_f_string_dynamic_t_delete_simple(protocol); + exit(return_code); } - if (status == F_failure) { - firewall_print_error_on_operation(main.error, current_tool, arguments); - - // remove ip_argument from arguments string. - macro_f_string_dynamic_t_delete_simple(arguments.array[arguments.used--]); - - break; - } - else if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "fll_execute_program"); + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_failure) { + firewall_print_error_on_operation(main->error, current_tool, arguments); + } + else if (F_status_set_fine(status) == F_parameter) { + firewall_print_error_on_invalid_parameter(main->error, "fll_execute_program"); + } + else { + firewall_print_error_on_unhandled(main->error, "fll_execute_program", status); + } // remove ip_argument from arguments string. macro_f_string_dynamic_t_delete_simple(arguments.array[arguments.used--]); @@ -806,25 +838,34 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi macro_f_fss_objects_t_delete_simple(basic_objects); macro_f_fss_contents_t_delete_simple(basic_contents); - if (status == F_failure || status == F_parameter) break; + if (F_status_set_fine(status) == F_failure || F_status_set_fine(status) == F_parameter) break; } else { - firewall_print_debug_tool(main.warning, current_tool, arguments); + firewall_print_debug_tool(main->warning, current_tool, arguments); status = fll_execute_program(current_tool, arguments, 0, 0, (void *) &return_code); // immediately exit child process, @todo this may require additional memory deallocation and relating changes. if (status == F_child) { + macro_f_string_dynamic_t_delete_simple(ip_list); + macro_f_string_dynamic_t_delete_simple(argument); + macro_f_string_dynamics_t_delete_simple(arguments); + macro_f_string_dynamic_t_delete_simple(device); + macro_f_string_dynamic_t_delete_simple(protocol); + exit(return_code); } - if (status == F_failure) { - firewall_print_error_on_operation(main.error, current_tool, arguments); - - break; - } - else if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "fll_execute_program"); + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_failure) { + firewall_print_error_on_operation(main->error, current_tool, arguments); + } + else if (F_status_set_fine(status) == F_parameter) { + firewall_print_error_on_invalid_parameter(main->error, "fll_execute_program"); + } + else { + firewall_print_error_on_unhandled(main->error, "fll_execute_program", status); + } break; } @@ -842,7 +883,8 @@ f_status_t firewall_perform_commands(const firewall_local_data_t local, const fi return status; } -f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, firewall_local_data_t *local, firewall_main_t *main) { +f_status_t firewall_create_custom_chains(firewall_main_t * const main, firewall_reserved_chains_t *reserved, firewall_local_data_t *local) { + f_status_t status = F_none; uint8_t tool = firewall_program_iptables; @@ -898,9 +940,18 @@ f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, f reserved->has_main = F_false; while (i < local->chain_objects.used) { + new_chain = F_true; j = 0; + status = firewall_signal_received(main); + + if (status) { + macro_f_string_dynamics_t_delete_simple(arguments); + + return F_status_set_error(F_interrupt); + } + // skip globally reserved chain name: main range.start = 0; range.stop = firewall_group_main_s_length - 1; @@ -947,6 +998,7 @@ f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, f if (new_chain) { while (j < main->chains.used) { + range.start = 0; range.stop = main->chains.array[j].used - 1; @@ -1038,10 +1090,20 @@ f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, f // immediately exit child process, @todo this may require additional memory deallocation and relating changes. if (status == F_child) { + macro_f_string_dynamics_t_delete_simple(arguments); + exit(return_code); } if (F_status_is_error_not(status)) { + status = firewall_signal_received(main); + + if (status) { + macro_f_string_dynamics_t_delete_simple(arguments); + + return F_status_set_error(F_interrupt); + } + firewall_print_debug_tool(main->warning, firewall_tool_ip6tables_s, arguments); tool = firewall_program_ip6tables; @@ -1049,6 +1111,8 @@ f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, f // immediately exit child process, @todo this may require additional memory deallocation and relating changes. if (status == F_child) { + macro_f_string_dynamics_t_delete_simple(arguments); + exit(return_code); } } @@ -1082,11 +1146,17 @@ f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, f return status; } -f_status_t firewall_delete_chains(const firewall_main_t main) { +f_status_t firewall_delete_chains(firewall_main_t * const main) { + const f_string_t tools[2] = { firewall_tool_iptables_s, firewall_tool_ip6tables_s }; f_status_t status = F_none; for (f_array_length_t i = 0; i < 2; ++i) { + + if (firewall_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + f_string_dynamics_t arguments = f_string_dynamics_t_initialize; f_string_dynamic_t argument[1] = f_string_dynamic_t_initialize; int return_code = 0; @@ -1099,7 +1169,7 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { arguments.size = 1; arguments.used = 1; - firewall_print_debug_tool(main.warning, tools[i], arguments); + firewall_print_debug_tool(main->warning, tools[i], arguments); status = fll_execute_program(tools[i], arguments, 0, 0, (void *) &return_code); @@ -1112,13 +1182,13 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { status = F_status_set_fine(status); if (status == F_failure) { - firewall_print_error_on_operation(main.error, tools[i], arguments); + firewall_print_error_on_operation(main->error, tools[i], arguments); } else if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "fll_execute_program"); + firewall_print_error_on_invalid_parameter(main->error, "fll_execute_program"); } else { - firewall_print_error_on_unhandled(main.error, "fll_execute_program", status); + firewall_print_error_on_unhandled(main->error, "fll_execute_program", status); } return status; @@ -1126,6 +1196,11 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { } // for for (f_array_length_t i = 0; i < 2; ++i) { + + if (firewall_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + f_string_dynamics_t arguments = f_string_dynamics_t_initialize; f_string_dynamic_t argument[1] = f_string_dynamic_t_initialize; int return_code = 0; @@ -1138,7 +1213,7 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { arguments.size = 1; arguments.used = 1; - firewall_print_debug_tool(main.warning, tools[i], arguments); + firewall_print_debug_tool(main->warning, tools[i], arguments); status = fll_execute_program(tools[i], arguments, 0, 0, (void *) &return_code); @@ -1151,13 +1226,13 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { status = F_status_set_fine(status); if (status == F_failure) { - firewall_print_error_on_operation(main.error, tools[i], arguments); + firewall_print_error_on_operation(main->error, tools[i], arguments); } else if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "fll_execute_program"); + firewall_print_error_on_invalid_parameter(main->error, "fll_execute_program"); } else { - firewall_print_error_on_unhandled(main.error, "fll_execute_program", status); + firewall_print_error_on_unhandled(main->error, "fll_execute_program", status); } return status; @@ -1167,7 +1242,8 @@ f_status_t firewall_delete_chains(const firewall_main_t main) { return status; } -f_status_t firewall_default_lock(const firewall_main_t main) { +f_status_t firewall_default_lock(firewall_main_t * const main) { + const f_string_t chains[3] = { firewall_chain_input_s, firewall_chain_output_s, firewall_chain_forward_s }; const f_string_t tools[2] = { firewall_tool_iptables_s, firewall_tool_ip6tables_s }; @@ -1175,7 +1251,10 @@ f_status_t firewall_default_lock(const firewall_main_t main) { f_status_t status = F_none; + int return_code = 0; + for (f_array_length_t i = 0; i < 3; ++i) { + f_string_dynamics_t arguments = f_string_dynamics_t_initialize; f_string_dynamic_t argument[3]; @@ -1196,9 +1275,10 @@ f_status_t firewall_default_lock(const firewall_main_t main) { arguments.array[2].size = arguments.array[2].used; for (f_array_length_t j = 0; j < 2; ++j) { - int return_code = 0; - firewall_print_debug_tool(main.warning, tools[j], arguments); + firewall_print_debug_tool(main->warning, tools[j], arguments); + + return_code = 0; status = fll_execute_program(tools[j], arguments, 0, 0, (void *) &return_code); @@ -1207,17 +1287,21 @@ f_status_t firewall_default_lock(const firewall_main_t main) { exit(return_code); } + if (firewall_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (F_status_is_error(status)) { status = F_status_set_fine(status); if (status == F_failure) { - firewall_print_error_on_operation(main.error, tools[j], arguments); + firewall_print_error_on_operation(main->error, tools[j], arguments); } else if (status == F_parameter) { - firewall_print_error_on_invalid_parameter(main.error, "fll_execute_program"); + firewall_print_error_on_invalid_parameter(main->error, "fll_execute_program"); } else { - firewall_print_error_on_unhandled(main.error, "fll_execute_program", status); + firewall_print_error_on_unhandled(main->error, "fll_execute_program", status); } return status; @@ -1228,7 +1312,8 @@ f_status_t firewall_default_lock(const firewall_main_t main) { return status; } -f_status_t firewall_buffer_rules(const f_string_t filename, const bool optional, firewall_local_data_t *local, firewall_main_t *main) { +f_status_t firewall_buffer_rules(firewall_main_t * const main, const f_string_t filename, const bool optional, firewall_local_data_t *local) { + f_file_t file = f_file_t_initialize; f_status_t status = f_file_open(filename, 0, &file); @@ -1342,7 +1427,7 @@ f_status_t firewall_buffer_rules(const f_string_t filename, const bool optional, return status; } -f_status_t firewall_process_rules(f_string_range_t *range, firewall_local_data_t *local, firewall_main_t *main) { +f_status_t firewall_process_rules(firewall_main_t * const main, f_string_range_t *range, firewall_local_data_t *local) { f_status_t status = F_none; f_fss_delimits_t delimits = f_fss_delimits_t_initialize; @@ -1364,7 +1449,7 @@ f_status_t firewall_process_rules(f_string_range_t *range, firewall_local_data_t macro_f_fss_delimits_t_delete_simple(delimits); if (F_status_is_error_not(status)) { - status = firewall_perform_commands(*local, *main); + status = firewall_perform_commands(main, *local); if (F_status_is_error(status)) { status = F_status_set_fine(status); @@ -1390,8 +1475,7 @@ f_status_t firewall_process_rules(f_string_range_t *range, firewall_local_data_t return status; } -f_status_t firewall_delete_local_data(firewall_local_data_t *local) { - f_status_t status = F_none; +f_status_t firewall_delete_local_data(firewall_local_data_t * const local) { local->is_global = F_true; local->is_main = F_false; diff --git a/level_3/firewall/c/private-firewall.h b/level_3/firewall/c/private-firewall.h index 2fe49f1..f9bf05a 100644 --- a/level_3/firewall/c/private-firewall.h +++ b/level_3/firewall/c/private-firewall.h @@ -15,64 +15,72 @@ extern "C" { /** * Perform commands. * + * @param main + * The main program data. * @param local * Local firewall settings. - * @param main - * The main data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_perform_commands(const firewall_local_data_t local, const firewall_main_t main) F_attribute_visibility_internal_d; +extern f_status_t firewall_perform_commands(firewall_main_t * const main, const firewall_local_data_t local) F_attribute_visibility_internal_d; /** * Create custom chains. * + * @param main + * The main program data. * @param reserved * firewall chains. * @param local * Local firewall settings. - * @param main - * The main data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_create_custom_chains(firewall_reserved_chains_t *reserved, firewall_local_data_t *local, firewall_main_t *main) F_attribute_visibility_internal_d; +extern f_status_t firewall_create_custom_chains(firewall_main_t * const main, firewall_reserved_chains_t *reserved, firewall_local_data_t *local) F_attribute_visibility_internal_d; /** * Deallocate chains. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_delete_chains(const firewall_main_t main) F_attribute_visibility_internal_d; +extern f_status_t firewall_delete_chains(firewall_main_t * const main) F_attribute_visibility_internal_d; /** * Lock the firewall. * * @param main - * The main data. + * The main program data. * * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_default_lock(const firewall_main_t main) F_attribute_visibility_internal_d; +extern f_status_t firewall_default_lock(firewall_main_t * const main) F_attribute_visibility_internal_d; /** * Buffer firewall rules. * + * @param main + * The main program data. * @param filename * File name to read the rules from. * @param optional @@ -80,32 +88,30 @@ extern f_status_t firewall_default_lock(const firewall_main_t main) F_attribute_ * FALSE otherwise (more are errors returned when not optional). * @param local * Local firewall settings. - * @param main - * The main data. * * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_buffer_rules(const f_string_t filename, const bool optional, firewall_local_data_t *local, firewall_main_t *main) F_attribute_visibility_internal_d; +extern f_status_t firewall_buffer_rules(firewall_main_t * const main, const f_string_t filename, const bool optional, firewall_local_data_t *local) F_attribute_visibility_internal_d; /** * Process buffered rules. * + * @param main + * The main program data. * @param range * The current position within the buffer and the stop point. * @param local * Local firewall settings. - * @param main - * The main data. * * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_process_rules(f_string_range_t *range, firewall_local_data_t *local, firewall_main_t *main) F_attribute_visibility_internal_d; +extern f_status_t firewall_process_rules(firewall_main_t * const main, f_string_range_t *range, firewall_local_data_t *local) F_attribute_visibility_internal_d; /** * Delete allocated local data. @@ -118,7 +124,7 @@ extern f_status_t firewall_process_rules(f_string_range_t *range, firewall_local * * Status codes (with error bit) are returned on any problem. */ -extern f_status_t firewall_delete_local_data(firewall_local_data_t *local) F_attribute_visibility_internal_d; +extern f_status_t firewall_delete_local_data(firewall_local_data_t * const local) F_attribute_visibility_internal_d; #ifdef __cplusplus } // extern "C" diff --git a/level_3/firewall/data/build/dependencies b/level_3/firewall/data/build/dependencies index 590d654..c5cb46b 100644 --- a/level_3/firewall/data/build/dependencies +++ b/level_3/firewall/data/build/dependencies @@ -19,6 +19,7 @@ f_fss f_path f_pipe f_print +f_signal fl_console fl_control_group fl_conversion diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.c b/level_3/fss_basic_list_read/c/fss_basic_list_read.c index 00d2167..67822a3 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.c @@ -117,7 +117,7 @@ extern "C" { #endif // _di_fss_basic_list_read_print_help_ #ifndef _di_fss_basic_list_read_main_ - f_status_t fss_basic_list_read_main(f_console_arguments_t * const arguments, fss_basic_list_read_main_t *main) { + f_status_t fss_basic_list_read_main(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -350,6 +350,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_basic_list_read_parameter_delimit].values.used; ++i) { + if (fss_basic_list_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + location = main->parameters[fss_basic_list_read_parameter_delimit].values.array[i]; length = strnlen(arguments->argv[location], f_console_parameter_size); @@ -465,13 +470,13 @@ extern "C" { } // for // Guarantee the default value is "all". - if (!data.delimit_mode) { + if (F_status_is_error_not(status) && !data.delimit_mode) { data.delimit_mode = fss_basic_list_read_delimit_mode_all; } } if (F_status_is_error_not(status)) { - status = fss_basic_list_read_depth_process(arguments, main, &data); + status = fss_basic_list_read_depth_process(main, arguments, &data); } // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. @@ -542,6 +547,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + if (fss_basic_list_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + data.files.array[data.files.used].range.start = data.buffer.used; file.stream = 0; file.id = -1; @@ -603,7 +613,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_basic_list_read_process(arguments, main, &data); + status = fss_basic_list_read_process(main, arguments, &data); } fss_basic_list_read_data_delete_simple(&data); @@ -613,6 +623,14 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_basic_list_read_data_delete_simple(&data); fss_basic_list_read_main_delete(main); @@ -621,7 +639,7 @@ extern "C" { #endif // _di_fss_basic_list_read_main_ #ifndef _di_fss_basic_list_read_main_delete_ - f_status_t fss_basic_list_read_main_delete(fss_basic_list_read_main_t *main) { + f_status_t fss_basic_list_read_main_delete(fss_basic_list_read_main_t * const main) { for (f_array_length_t i = 0; i < fss_basic_list_total_parameters_d; ++i) { diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.h b/level_3/fss_basic_list_read/c/fss_basic_list_read.h index c7dc942..b38bb54 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -213,6 +214,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_basic_list_read_main_t; @@ -224,6 +227,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_basic_list_read_main_t_ @@ -248,10 +252,18 @@ extern "C" { * * Be sure to call fss_basic_list_read_main_delete() after executing this. * + * 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 arguments * The parameters passed to the process. * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -261,7 +273,7 @@ extern "C" { * @see fss_basic_list_read_main_delete() */ #ifndef _di_fss_basic_list_read_main_ - extern f_status_t fss_basic_list_read_main(f_console_arguments_t * const arguments, fss_basic_list_read_main_t *main); + extern f_status_t fss_basic_list_read_main(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_basic_list_read_main_ /** @@ -270,7 +282,7 @@ extern "C" { * Be sure to call this after executing fss_basic_list_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -280,7 +292,7 @@ extern "C" { * @see fss_basic_list_read_main() */ #ifndef _di_fss_basic_list_read_main_delete_ - extern f_status_t fss_basic_list_read_main_delete(fss_basic_list_read_main_t *main); + extern f_status_t fss_basic_list_read_main_delete(fss_basic_list_read_main_t * const main); #endif // _di_fss_basic_list_read_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_basic_list_read/c/main.c b/level_3/fss_basic_list_read/c/main.c index 236fc47..80d3a03 100644 --- a/level_3/fss_basic_list_read/c/main.c +++ b/level_3/fss_basic_list_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_basic_list_read_main(&arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_basic_list_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_basic_list_read/c/private-common.c b/level_3/fss_basic_list_read/c/private-common.c index ed0361e..aa8bfbb 100644 --- a/level_3/fss_basic_list_read/c/private-common.c +++ b/level_3/fss_basic_list_read/c/private-common.c @@ -57,6 +57,53 @@ extern "C" { } #endif // _di_fss_basic_list_read_depths_resize_ +#ifndef _di_fss_basic_list_read_print_signal_received_ + void fss_basic_list_read_print_signal_received(fss_basic_list_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_basic_list_read_print_signal_received_ + +#ifndef _di_fss_basic_list_read_signal_received_ + f_status_t fss_basic_list_read_signal_received(fss_basic_list_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_basic_list_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_basic_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/private-common.h b/level_3/fss_basic_list_read/c/private-common.h index b17a52b..2378dda 100644 --- a/level_3/fss_basic_list_read/c/private-common.h +++ b/level_3/fss_basic_list_read/c/private-common.h @@ -248,6 +248,36 @@ extern "C" { extern f_status_t fss_basic_list_read_depths_resize(const f_array_length_t length, fss_basic_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_depths_resize_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_basic_list_read_print_signal_received_ + extern void fss_basic_list_read_print_signal_received(fss_basic_list_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_list_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_basic_list_read_signal_received_ + extern f_status_t fss_basic_list_read_signal_received(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c index a309dca..8a565f5 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c @@ -55,7 +55,7 @@ extern "C" { #endif // _di_fss_basic_list_read_delimit_object_is_ #ifndef _di_fss_basic_list_read_depth_process_ - f_status_t fss_basic_list_read_depth_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { + f_status_t fss_basic_list_read_depth_process(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) { f_status_t status = F_none; @@ -85,6 +85,10 @@ extern "C" { for (f_array_length_t i = 0; i < data->depths.used; ++i) { + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + data->depths.array[i].depth = 0; data->depths.array[i].index_at = 0; data->depths.array[i].index_name = 0; @@ -167,6 +171,10 @@ extern "C" { for (f_array_length_t j = i + 1; j < data->depths.used; ++j) { + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->depths.array[i].depth == data->depths.array[j].depth) { if (main->error.verbosity != f_console_verbosity_quiet) { flockfile(main->error.to.stream); @@ -257,7 +265,7 @@ extern "C" { #endif // _di_fss_basic_list_read_load_ #ifndef _di_fss_basic_list_read_load_number_ - f_status_t fss_basic_list_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, f_number_unsigned_t *number) { + f_status_t fss_basic_list_read_load_number(fss_basic_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) { if (main->parameters[parameter].result == f_console_result_additional) { const f_array_length_t index = main->parameters[parameter].values.array[main->parameters[parameter].values.used - 1]; @@ -279,7 +287,7 @@ extern "C" { #endif // _di_fss_basic_list_read_load_number_ #ifndef _di_fss_basic_list_read_print_at_ - void fss_basic_list_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data) { + void fss_basic_list_read_print_at(fss_basic_list_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_list_read_data_t * const data) { if (at >= data->contents.used) { return; @@ -385,9 +393,9 @@ extern "C" { #endif // _di_fss_basic_list_read_print_zero_ #ifndef _di_fss_basic_list_read_process_ - f_status_t fss_basic_list_read_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { + f_status_t fss_basic_list_read_process(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) { - f_status_t status = fss_basic_list_read_process_option(arguments, main, data); + f_status_t status = fss_basic_list_read_process_option(main, arguments, data); if (F_status_is_error(status)) return status; // This standard does not support multiple content groups. @@ -440,7 +448,11 @@ extern "C" { if (!names[i]) continue; - fss_basic_list_read_print_at(i, *delimits_object, *delimits_content, main, data); + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + + fss_basic_list_read_print_at(main, i, *delimits_object, *delimits_content, data); } // for return F_none; @@ -478,11 +490,15 @@ extern "C" { if (!names[i]) continue; + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (at == data->depths.array[0].value_at) { if (data->option & fss_basic_list_read_data_option_line_d) { f_array_length_t line = 0; - status = fss_basic_list_read_process_at_line(i, *delimits_object, *delimits_content, main, data, &line); + status = fss_basic_list_read_process_at_line(main, i, *delimits_object, *delimits_content, data, &line); if (status == F_success) return F_none; } else if (data->option & fss_basic_list_read_data_option_columns_d) { @@ -501,7 +517,7 @@ extern "C" { funlockfile(main->output.to.stream); } else { - fss_basic_list_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_basic_list_read_print_at(main, i, *delimits_object, *delimits_content, data); } return F_none; @@ -541,6 +557,10 @@ extern "C" { if (!names[at]) continue; + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->contents.array[at].used > max) { max = data->contents.array[at].used; } @@ -553,7 +573,7 @@ extern "C" { #endif // _di_fss_basic_list_read_process_columns_ #ifndef _di_fss_basic_list_read_process_at_line_ - f_status_t fss_basic_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, f_array_length_t *line) { + f_status_t fss_basic_list_read_process_at_line(fss_basic_list_read_main_t * const main, const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_data_t *data, f_array_length_t *line) { if (data->option & fss_basic_list_read_data_option_object_d) { if (*line == data->line) { @@ -593,6 +613,10 @@ extern "C" { for (i = range.start; i <= range.stop; ++i) { + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->buffer.string[i] == f_string_eol_s[0]) { if (*line == data->line) { range.stop = i; @@ -666,7 +690,11 @@ extern "C" { if (!names[i]) continue; - status = fss_basic_list_read_process_at_line(i, *delimits_object, *delimits_content, main, data, &line); + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + + status = fss_basic_list_read_process_at_line(main, i, *delimits_object, *delimits_content, data, &line); if (status == F_success) break; } // for @@ -701,7 +729,7 @@ extern "C" { #endif // _di_fss_basic_list_read_process_name_ #ifndef _di_fss_basic_list_read_process_option_ - f_status_t fss_basic_list_read_process_option(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) { + f_status_t fss_basic_list_read_process_option(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) { f_status_t status = F_none; @@ -724,7 +752,7 @@ extern "C" { if (main->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { data->option |= fss_basic_list_read_data_option_line_d; - status = fss_basic_list_read_load_number(fss_basic_list_read_parameter_line, fss_basic_list_long_line_s, arguments, main, &data->line); + status = fss_basic_list_read_load_number(main, fss_basic_list_read_parameter_line, fss_basic_list_long_line_s, arguments, &data->line); if (F_status_is_error(status)) return status; } @@ -743,7 +771,7 @@ extern "C" { if (main->parameters[fss_basic_list_read_parameter_select].result == f_console_result_additional) { data->option |= fss_basic_list_read_data_option_select_d; - status = fss_basic_list_read_load_number(fss_basic_list_read_parameter_select, fss_basic_list_long_select_s, arguments, main, &data->select); + status = fss_basic_list_read_load_number(main, fss_basic_list_read_parameter_select, fss_basic_list_long_select_s, arguments, &data->select); if (F_status_is_error(status)) return status; } @@ -775,6 +803,10 @@ extern "C" { if (!names[at]) continue; + if (fss_basic_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->option & fss_basic_list_read_data_option_object_d) { ++total; } diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h index 8fdc38b..f5544b7 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h @@ -49,16 +49,18 @@ extern "C" { * * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed). * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * * @return * F_none on success. * + * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * * Errors (with error bit) from: f_string_append(). * Errors (with error bit) from: fl_string_rip(). * Errors (with error bit) from: fl_conversion_string_to_number_unsigned(). @@ -72,7 +74,7 @@ extern "C" { * @see fss_basic_list_read_depths_resize() */ #ifndef _di_fss_basic_list_read_depth_process_ - extern f_status_t fss_basic_list_read_depth_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_read_depth_process(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_depth_process_ /** @@ -99,7 +101,7 @@ extern "C" { * This will print an error message on error. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @@ -124,14 +126,14 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param parameter * An ID representing the parameter. * @param name * The parameter name to print on error. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param number * The location to store the loaded number. * @@ -146,7 +148,7 @@ extern "C" { * @see fss_basic_list_read_depths_resize() */ #ifndef _di_fss_basic_list_read_load_number_ - extern f_status_t fss_basic_list_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_read_load_number(fss_basic_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_load_number_ /** @@ -154,26 +156,26 @@ extern "C" { * * Only what is requested to print (Object, Content, both, or neither) will be printed, if there is something to print. * + * @param main + * The main program data. * @param at * The index in the Objects and Contents to print. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content * The delimits to be applied to Content. - * @param main - * The main data. * @param data * The program data. */ #ifndef _di_fss_basic_list_read_print_at_ - extern void fss_basic_list_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t * const data) F_attribute_visibility_internal_d; + extern void fss_basic_list_read_print_at(fss_basic_list_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_list_read_data_t * const data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_print_at_ /** * Explicitly print the Object at the given position. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param at @@ -191,7 +193,7 @@ extern "C" { * This is only used in pipe output mode. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_read_print_content_ignore_ extern void fss_basic_list_read_print_content_ignore(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -201,7 +203,7 @@ extern "C" { * Print the end of an Object (which is essentially the start of Content). * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_read_print_object_end_ extern void fss_basic_list_read_print_object_end(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -211,7 +213,7 @@ extern "C" { * Print the number one and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_read_print_one_ extern void fss_basic_list_read_print_one(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -221,7 +223,7 @@ extern "C" { * Print the end of an Object/Content set. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_read_print_set_end_ extern void fss_basic_list_read_print_set_end(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -231,7 +233,7 @@ extern "C" { * Print the number zero and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_read_print_zero_ extern void fss_basic_list_read_print_zero(fss_basic_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -242,10 +244,10 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -259,14 +261,14 @@ extern "C" { * @see fss_basic_list_read_process_option() */ #ifndef _di_fss_basic_list_read_process_ - extern f_status_t fss_basic_list_read_process(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_read_process(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_process_ /** * Process based on at parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -286,7 +288,7 @@ extern "C" { * Process based on columns parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -304,7 +306,7 @@ extern "C" { * Process based on at parameter for some line. * * @param main - * The main data. + * The main program data. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content @@ -320,14 +322,14 @@ extern "C" { * F_success on success and the line was matched (and possibly printed). */ #ifndef _di_fss_basic_list_read_process_at_line_ - extern f_status_t fss_basic_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data, f_array_length_t *line) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_read_process_at_line(fss_basic_list_read_main_t * const main, const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_basic_list_read_data_t *data, f_array_length_t *line) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_process_at_line_ /** * Process based on line parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -362,10 +364,10 @@ extern "C" { /** * Process the parameters, populating the option property of the program data. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -379,14 +381,14 @@ extern "C" { * @see fss_basic_list_read_load_setting() */ #ifndef _di_fss_basic_list_read_process_option_ - extern f_status_t fss_basic_list_read_process_option(f_console_arguments_t * const arguments, fss_basic_list_read_main_t * const main, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_read_process_option(fss_basic_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_process_option_ /** * Process based on total parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names diff --git a/level_3/fss_basic_list_read/data/build/dependencies b/level_3/fss_basic_list_read/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_basic_list_read/data/build/dependencies +++ b/level_3/fss_basic_list_read/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.c b/level_3/fss_basic_list_write/c/fss_basic_list_write.c index bc0acc8..6e97da5 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.c @@ -57,7 +57,8 @@ extern "C" { #endif // _di_fss_basic_list_write_print_help_ #ifndef _di_fss_basic_list_write_main_ - f_status_t fss_basic_list_write_main(const f_console_arguments_t arguments, fss_basic_list_write_main_t *main) { + f_status_t fss_basic_list_write_main(fss_basic_list_write_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -67,7 +68,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_basic_list_write_parameter_no_color, fss_basic_list_write_parameter_light, fss_basic_list_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -175,15 +176,15 @@ extern "C" { output.id = -1; output.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &output); + status = f_file_stream_open(arguments->argv[location], 0, &output); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } else if (main->parameters[fss_basic_list_write_parameter_file].result == f_console_result_found) { - fss_basic_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_list_write_long_file_s); + fss_basic_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_list_write_long_file_s); status = F_status_set_error(F_parameter); } } @@ -192,15 +193,15 @@ extern "C" { if (main->parameters[fss_basic_list_write_parameter_object].locations.used || main->parameters[fss_basic_list_write_parameter_content].locations.used) { if (main->parameters[fss_basic_list_write_parameter_object].locations.used) { if (main->parameters[fss_basic_list_write_parameter_object].locations.used != main->parameters[fss_basic_list_write_parameter_object].values.used) { - fss_basic_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_list_write_long_object_s); + fss_basic_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_list_write_long_object_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_list_write_parameter_content].locations.used != main->parameters[fss_basic_list_write_parameter_content].values.used) { - fss_basic_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s); + fss_basic_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_list_write_parameter_object].locations.used != main->parameters[fss_basic_list_write_parameter_content].locations.used && main->parameters[fss_basic_list_write_parameter_partial].result == f_console_result_none) { - fss_basic_list_write_error_parameter_same_times_print(*main); + fss_basic_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_list_write_parameter_content].locations.used && main->parameters[fss_basic_list_write_parameter_partial].locations.used) { @@ -258,11 +259,11 @@ extern "C" { } else if (main->parameters[fss_basic_list_write_parameter_content].locations.used) { if (main->parameters[fss_basic_list_write_parameter_content].locations.used != main->parameters[fss_basic_list_write_parameter_content].values.used) { - fss_basic_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s); + fss_basic_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_basic_list_write_parameter_partial].locations.used) { - fss_basic_list_write_error_parameter_same_times_print(*main); + fss_basic_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } } @@ -316,12 +317,12 @@ extern "C" { } else if (main->parameters[fss_basic_list_write_parameter_prepend].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_basic_list_write_parameter_prepend].values.array[main->parameters[fss_basic_list_write_parameter_prepend].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); if (length) { f_string_range_t range = macro_f_string_range_t_initialize(length); - main->prepend.string = arguments.argv[index]; + main->prepend.string = arguments->argv[index]; main->prepend.used = length; main->prepend.size = length; @@ -417,7 +418,7 @@ extern "C" { f_string_dynamic_t escaped = f_string_dynamic_t_initialize; if (main->process_pipe) { - status = fss_basic_list_write_process_pipe(*main, output, quote, &buffer); + status = fss_basic_list_write_process_pipe(main, output, quote, &buffer); if (F_status_is_error(status)) { if (main->error.verbosity != f_console_verbosity_quiet) { @@ -437,22 +438,32 @@ extern "C" { if (main->parameters[fss_basic_list_write_parameter_object].result == f_console_result_additional) { for (f_array_length_t i = 0; i < main->parameters[fss_basic_list_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_basic_list_write_parameter_object].values.array[i]]; + if (fss_basic_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_basic_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - status = fss_basic_list_write_process(*main, output, quote, &object, 0, &buffer); + status = fss_basic_list_write_process(main, output, quote, &object, 0, &buffer); if (F_status_is_error(status)) break; } // for } else { for (f_array_length_t i = 0; i < main->parameters[fss_basic_list_write_parameter_content].values.used; ++i) { - content.string = arguments.argv[main->parameters[fss_basic_list_write_parameter_content].values.array[i]]; + if (fss_basic_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + content.string = arguments->argv[main->parameters[fss_basic_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_basic_list_write_process(*main, output, quote, 0, &content, &buffer); + status = fss_basic_list_write_process(main, output, quote, 0, &content, &buffer); if (F_status_is_error(status)) break; } // for } @@ -460,15 +471,20 @@ extern "C" { else { for (f_array_length_t i = 0; i < main->parameters[fss_basic_list_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_basic_list_write_parameter_object].values.array[i]]; + if (fss_basic_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_basic_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - content.string = arguments.argv[main->parameters[fss_basic_list_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_basic_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_basic_list_write_process(*main, output, quote, &object, &content, &buffer); + status = fss_basic_list_write_process(main, output, quote, &object, &content, &buffer); if (F_status_is_error(status)) break; } // for } @@ -519,12 +535,13 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); fss_basic_list_write_main_delete(main); + return status; } #endif // _di_fss_basic_list_write_main_ #ifndef _di_fss_basic_list_write_main_delete_ - f_status_t fss_basic_list_write_main_delete(fss_basic_list_write_main_t *main) { + f_status_t fss_basic_list_write_main_delete(fss_basic_list_write_main_t * const main) { for (f_array_length_t i = 0; i < fss_basic_list_write_total_parameters_d; ++i) { diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.h b/level_3/fss_basic_list_write/c/fss_basic_list_write.h index 1b02e89..b0d031b 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.h +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -147,6 +148,9 @@ extern "C" { fl_print_t output; fl_print_t error; fl_print_t warning; + + f_signal_t signal; + f_string_static_t prepend; f_color_context_t context; @@ -160,6 +164,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_static_t_initialize, \ f_color_context_t_initialize, \ } @@ -185,10 +190,18 @@ extern "C" { * * Be sure to call fss_basic_list_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -198,7 +211,7 @@ extern "C" { * @see fss_basic_list_write_main_delete() */ #ifndef _di_fss_basic_list_write_main_ - extern f_status_t fss_basic_list_write_main(const f_console_arguments_t arguments, fss_basic_list_write_main_t *main); + extern f_status_t fss_basic_list_write_main(fss_basic_list_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_basic_list_write_main_ /** @@ -207,7 +220,7 @@ extern "C" { * Be sure to call this after executing fss_basic_list_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -217,7 +230,7 @@ extern "C" { * @see fss_basic_list_write_main() */ #ifndef _di_fss_basic_list_write_main_delete_ - extern f_status_t fss_basic_list_write_main_delete(fss_basic_list_write_main_t *main); + extern f_status_t fss_basic_list_write_main_delete(fss_basic_list_write_main_t * const main); #endif // _di_fss_basic_list_write_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_basic_list_write/c/main.c b/level_3/fss_basic_list_write/c/main.c index 9c53f81..28f7cf6 100644 --- a/level_3/fss_basic_list_write/c/main.c +++ b/level_3/fss_basic_list_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_basic_list_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_basic_list_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_basic_list_write/c/private-common.c b/level_3/fss_basic_list_write/c/private-common.c index 1975491..5cea228 100644 --- a/level_3/fss_basic_list_write/c/private-common.c +++ b/level_3/fss_basic_list_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_basic_list_write_print_signal_received_ + void fss_basic_list_write_print_signal_received(fss_basic_list_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_basic_list_write_print_signal_received_ + +#ifndef _di_fss_basic_list_write_signal_received_ + f_status_t fss_basic_list_write_signal_received(fss_basic_list_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_basic_list_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_basic_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/private-common.h b/level_3/fss_basic_list_write/c/private-common.h index 2f8c598..42499d3 100644 --- a/level_3/fss_basic_list_write/c/private-common.h +++ b/level_3/fss_basic_list_write/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define fss_basic_list_write_common_allocation_small_d 16 #endif // _di_fss_basic_list_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_basic_list_write_print_signal_received_ + extern void fss_basic_list_write_print_signal_received(fss_basic_list_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_list_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_basic_list_write_signal_received_ + extern f_status_t fss_basic_list_write_signal_received(fss_basic_list_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c index 90f1d76..ce64de5 100644 --- a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.c @@ -7,62 +7,62 @@ extern "C" { #endif #ifndef _di_fss_basic_list_write_error_parameter_same_times_print_ - void fss_basic_list_write_error_parameter_same_times_print(const fss_basic_list_write_main_t main) { + void fss_basic_list_write_error_parameter_same_times_print(fss_basic_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sMust specify the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_object_s, main.error.notable); - fl_print_format("%[' parameter and the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s, main.error.notable); - fl_print_format("%[' parameter the same number of times when not specifying the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_partial_s, main.error.notable); - fl_print_format("%[' parameter.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sMust specify the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_object_s, main->error.notable); + fl_print_format("%[' parameter and the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_content_s, main->error.notable); + fl_print_format("%[' parameter the same number of times when not specifying the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_partial_s, main->error.notable); + fl_print_format("%[' parameter.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_list_write_error_parameter_same_times_print_ #ifndef _di_fss_basic_list_write_error_parameter_unsupported_eol_print_ - void fss_basic_list_write_error_parameter_unsupported_eol_print(const fss_basic_list_write_main_t main) { + void fss_basic_list_write_error_parameter_unsupported_eol_print(fss_basic_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThis standard does not support end of line character '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[\\n%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[' in objects.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThis standard does not support end of line character '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[\\n%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[' in objects.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_list_write_error_parameter_unsupported_eol_print_ #ifndef _di_fss_basic_list_write_error_parameter_value_missing_print_ - void fss_basic_list_write_error_parameter_value_missing_print(const fss_basic_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) { + void fss_basic_list_write_error_parameter_value_missing_print(fss_basic_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, symbol, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, symbol, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_list_write_error_parameter_value_missing_print_ #ifndef _di_fss_basic_list_write_process_ - f_status_t fss_basic_list_write_process(const fss_basic_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) { + f_status_t fss_basic_list_write_process(fss_basic_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_state_t state = macro_f_state_t_initialize(fss_basic_list_write_common_allocation_large_d, fss_basic_list_write_common_allocation_small_d, 0, 0, 0, 0, 0); @@ -81,7 +81,7 @@ extern "C" { } if (content) { - if (main.parameters[fss_basic_list_write_parameter_trim].result == f_console_result_found) { + if (main->parameters[fss_basic_list_write_parameter_trim].result == f_console_result_found) { complete = f_fss_complete_full_trim; } else { @@ -98,7 +98,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_basic_list_object_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_basic_list_object_write_string", F_true); return status; } @@ -108,10 +108,10 @@ extern "C" { range.start = 0; range.stop = content->used - 1; - status = fl_fss_basic_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main.prepend, state, &range, buffer); + status = fl_fss_basic_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main->prepend, state, &range, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_basic_list_content_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_basic_list_content_write_string", F_true); return status; } @@ -121,7 +121,7 @@ extern "C" { status = f_string_append(f_string_eol_s, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -130,12 +130,13 @@ extern "C" { fll_print_dynamic(*buffer, output.stream); buffer->used = 0; + return status; } #endif // _di_fss_basic_list_write_process_ #ifndef _di_fss_basic_list_write_process_pipe_ - f_status_t fss_basic_list_write_process_pipe(const fss_basic_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { + f_status_t fss_basic_list_write_process_pipe(fss_basic_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_status_t status_pipe = F_none; @@ -158,6 +159,11 @@ extern "C" { for (;;) { + if (fss_basic_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + if (range.start > range.stop) { if (status_pipe == F_none_eof) break; @@ -166,7 +172,7 @@ extern "C" { status_pipe = f_file_read_block(input, &block); if (F_status_is_error(status_pipe)) { - fll_error_print(main.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); + fll_error_print(main->error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); status_pipe = F_status_set_error(F_pipe); break; @@ -190,7 +196,7 @@ extern "C" { status = f_string_dynamic_increase_by(block.used, &object); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -239,7 +245,7 @@ extern "C" { status = f_string_dynamic_increase_by(total, &content); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -247,8 +253,8 @@ extern "C" { for (; range.start <= range.stop; ++range.start) { if (block.string[range.start] == fss_basic_list_write_pipe_content_start_s) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context, f_string_eol_s[0]); } status = F_status_set_error(F_supported_not); @@ -292,6 +298,7 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(block); macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); + return status; } #endif // _di_fss_basic_list_write_process_pipe_ diff --git a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.h b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.h index de4156c..f350c6a 100644 --- a/level_3/fss_basic_list_write/c/private-fss_basic_list_write.h +++ b/level_3/fss_basic_list_write/c/private-fss_basic_list_write.h @@ -16,41 +16,41 @@ extern "C" { * Print an message about the object and content parameters not being specified the same number of times. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_write_error_parameter_same_times_print_ - void fss_basic_list_write_error_parameter_same_times_print(const fss_basic_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_basic_list_write_error_parameter_same_times_print(fss_basic_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_write_error_parameter_same_times_print_ /** * Print an message about a parameter EOL being unsupported. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_list_write_error_parameter_unsupported_eol_print_ - void fss_basic_list_write_error_parameter_unsupported_eol_print(const fss_basic_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_basic_list_write_error_parameter_unsupported_eol_print(fss_basic_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_write_error_parameter_unsupported_eol_print_ /** * Print an message about a parameter missing a value. * * @param main - * The main data. + * The main program data. * @param symbol * The console symbol, such as "--" in "--help". * @param parameter * The parameter name, such as "help" in "--help". */ #ifndef _di_fss_basic_list_write_error_parameter_value_missing_print_ - void fss_basic_list_write_error_parameter_value_missing_print(const fss_basic_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; + void fss_basic_list_write_error_parameter_value_missing_print(fss_basic_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_write_error_parameter_value_missing_print_ /** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -70,14 +70,14 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_basic_list_write_process_ - extern f_status_t fss_basic_list_write_process(const fss_basic_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_write_process(fss_basic_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_write_process_ /** * Process the pipe, reading from the pipe and writing to the output. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -91,7 +91,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_basic_list_write_process_pipe_ - extern f_status_t fss_basic_list_write_process_pipe(const fss_basic_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_list_write_process_pipe(fss_basic_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_write_process_pipe_ #ifdef __cplusplus diff --git a/level_3/fss_basic_list_write/data/build/dependencies b/level_3/fss_basic_list_write/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_basic_list_write/data/build/dependencies +++ b/level_3/fss_basic_list_write/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_basic_read/c/fss_basic_read.c b/level_3/fss_basic_read/c/fss_basic_read.c index ad237e4..ca8ac6d 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.c +++ b/level_3/fss_basic_read/c/fss_basic_read.c @@ -117,7 +117,7 @@ extern "C" { #endif // _di_fss_basic_read_print_help_ #ifndef _di_fss_basic_read_main_ - f_status_t fss_basic_read_main(f_console_arguments_t * const arguments, fss_basic_read_main_t *main) { + f_status_t fss_basic_read_main(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -350,6 +350,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_basic_read_parameter_delimit].values.used; ++i) { + if (fss_basic_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + location = main->parameters[fss_basic_read_parameter_delimit].values.array[i]; length = strnlen(arguments->argv[location], f_console_parameter_size); @@ -471,7 +476,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_basic_read_depth_process(arguments, main, &data); + status = fss_basic_read_depth_process(main, arguments, &data); } // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. @@ -542,6 +547,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + if (fss_basic_read_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + data.files.array[data.files.used].range.start = data.buffer.used; file.stream = 0; file.id = -1; @@ -603,7 +613,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_basic_read_process(arguments, main, &data); + status = fss_basic_read_process(main, arguments, &data); } fss_basic_read_data_delete_simple(&data); @@ -613,6 +623,14 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_basic_read_data_delete_simple(&data); fss_basic_read_main_delete(main); @@ -621,7 +639,7 @@ extern "C" { #endif // _di_fss_basic_read_main_ #ifndef _di_fss_basic_read_main_delete_ - f_status_t fss_basic_read_main_delete(fss_basic_read_main_t *main) { + f_status_t fss_basic_read_main_delete(fss_basic_read_main_t * const main) { for (f_array_length_t i = 0; i < fss_basic_read_total_parameters_d; ++i) { diff --git a/level_3/fss_basic_read/c/fss_basic_read.h b/level_3/fss_basic_read/c/fss_basic_read.h index f808cc5..204f060 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.h +++ b/level_3/fss_basic_read/c/fss_basic_read.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -213,6 +214,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_basic_read_main_t; @@ -224,6 +227,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_basic_read_main_t_ @@ -248,10 +252,18 @@ extern "C" { * * Be sure to call fss_basic_read_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -261,7 +273,7 @@ extern "C" { * @see fss_basic_read_main_delete() */ #ifndef _di_fss_basic_read_main_ - extern f_status_t fss_basic_read_main(f_console_arguments_t * const arguments, fss_basic_read_main_t *main); + extern f_status_t fss_basic_read_main(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_basic_read_main_ /** @@ -270,7 +282,7 @@ extern "C" { * Be sure to call this after executing fss_basic_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -280,7 +292,7 @@ extern "C" { * @see fss_basic_read_main() */ #ifndef _di_fss_basic_read_main_delete_ - extern f_status_t fss_basic_read_main_delete(fss_basic_read_main_t *main); + extern f_status_t fss_basic_read_main_delete(fss_basic_read_main_t * const main); #endif // _di_fss_basic_read_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_basic_read/c/main.c b/level_3/fss_basic_read/c/main.c index eac565f..56d401d 100644 --- a/level_3/fss_basic_read/c/main.c +++ b/level_3/fss_basic_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_basic_read_main(&arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_basic_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_basic_read/c/private-common.c b/level_3/fss_basic_read/c/private-common.c index fc3c4b7..26d9f3b 100644 --- a/level_3/fss_basic_read/c/private-common.c +++ b/level_3/fss_basic_read/c/private-common.c @@ -56,6 +56,53 @@ extern "C" { } #endif // _di_fss_basic_read_depths_resize_ +#ifndef _di_fss_basic_read_print_signal_received_ + void fss_basic_read_print_signal_received(fss_basic_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_basic_read_print_signal_received_ + +#ifndef _di_fss_basic_read_signal_received_ + f_status_t fss_basic_read_signal_received(fss_basic_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_basic_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_basic_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/private-common.h b/level_3/fss_basic_read/c/private-common.h index b769cdc..4e64856 100644 --- a/level_3/fss_basic_read/c/private-common.h +++ b/level_3/fss_basic_read/c/private-common.h @@ -243,6 +243,36 @@ extern "C" { extern f_status_t fss_basic_read_depths_resize(const f_array_length_t length, fss_basic_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_depths_resize_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_basic_read_print_signal_received_ + extern void fss_basic_read_print_signal_received(fss_basic_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_basic_read_signal_received_ + extern f_status_t fss_basic_read_signal_received(fss_basic_read_main_t * const main); +#endif // _di_fss_basic_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/private-fss_basic_read.c b/level_3/fss_basic_read/c/private-fss_basic_read.c index 9584e55..0e8ec27 100644 --- a/level_3/fss_basic_read/c/private-fss_basic_read.c +++ b/level_3/fss_basic_read/c/private-fss_basic_read.c @@ -32,7 +32,7 @@ extern "C" { #endif // _di_fss_basic_read_delimit_object_is_ #ifndef _di_fss_basic_read_depth_process_ - f_status_t fss_basic_read_depth_process(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) { + f_status_t fss_basic_read_depth_process(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) { f_status_t status = F_none; @@ -62,6 +62,10 @@ extern "C" { for (f_array_length_t i = 0; i < data->depths.used; ++i) { + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + data->depths.array[i].depth = 0; data->depths.array[i].index_at = 0; data->depths.array[i].index_name = 0; @@ -144,6 +148,10 @@ extern "C" { for (f_array_length_t j = i + 1; j < data->depths.used; ++j) { + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->depths.array[i].depth == data->depths.array[j].depth) { if (main->error.verbosity != f_console_verbosity_quiet) { flockfile(main->error.to.stream); @@ -230,7 +238,7 @@ extern "C" { #endif // _di_fss_basic_read_load_ #ifndef _di_fss_basic_read_load_number_ - f_status_t fss_basic_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, f_number_unsigned_t *number) { + f_status_t fss_basic_read_load_number(fss_basic_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) { if (main->parameters[parameter].result == f_console_result_additional) { const f_array_length_t index = main->parameters[parameter].values.array[main->parameters[parameter].values.used - 1]; @@ -252,7 +260,7 @@ extern "C" { #endif // _di_fss_basic_read_load_number_ #ifndef _di_fss_basic_read_print_at_ - void fss_basic_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_read_main_t * const main, fss_basic_read_data_t * const data) { + void fss_basic_read_print_at(fss_basic_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_read_data_t * const data) { if (at >= data->contents.used) { return; @@ -355,9 +363,9 @@ extern "C" { #endif // _di_fss_basic_read_print_zero_ #ifndef _di_fss_basic_read_process_ - f_status_t fss_basic_read_process(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) { + f_status_t fss_basic_read_process(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) { - f_status_t status = fss_basic_read_process_option(arguments, main, data); + f_status_t status = fss_basic_read_process_option(main, arguments, data); if (F_status_is_error(status)) return status; // This standard does not support multiple content groups. @@ -404,7 +412,7 @@ extern "C" { if (!names[i]) continue; - fss_basic_read_print_at(i, *delimits, except_none, main, data); + fss_basic_read_print_at(main, i, *delimits, except_none, data); } // for return F_none; @@ -450,6 +458,10 @@ extern "C" { if (!names[i]) continue; + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (at == data->depths.array[0].value_at) { if (data->option & fss_basic_read_data_option_line) { @@ -464,7 +476,7 @@ extern "C" { funlockfile(main->output.to.stream); } else { - fss_basic_read_print_at(i, *delimits, except_none, main, data); + fss_basic_read_print_at(main, i, *delimits, except_none, data); } } else if (data->option & fss_basic_read_data_option_columns) { @@ -483,7 +495,7 @@ extern "C" { funlockfile(main->output.to.stream); } else { - fss_basic_read_print_at(i, *delimits, except_none, main, data); + fss_basic_read_print_at(main, i, *delimits, except_none, data); } return F_none; @@ -523,6 +535,10 @@ extern "C" { if (!names[at]) continue; + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->contents.array[at].used > max) { max = data->contents.array[at].used; } @@ -546,6 +562,10 @@ extern "C" { if (!names[i]) continue; + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (!(data->option & fss_basic_read_data_option_object) && (data->option & fss_basic_read_data_option_content)) { if (!data->contents.array[i].used) { if (data->option & fss_basic_read_data_option_empty) { @@ -567,7 +587,7 @@ extern "C" { } if (line == data->line) { - fss_basic_read_print_at(i, *delimits, except_none, main, data); + fss_basic_read_print_at(main, i, *delimits, except_none, data); break; } @@ -615,7 +635,7 @@ extern "C" { #endif // _di_fss_basic_read_process_name_ #ifndef _di_fss_basic_read_process_option_ - f_status_t fss_basic_read_process_option(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) { + f_status_t fss_basic_read_process_option(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) { f_status_t status = F_none; @@ -638,7 +658,7 @@ extern "C" { if (main->parameters[fss_basic_read_parameter_line].result == f_console_result_additional) { data->option |= fss_basic_read_data_option_line; - status = fss_basic_read_load_number(fss_basic_read_parameter_line, fss_basic_read_long_line_s, arguments, main, &data->line); + status = fss_basic_read_load_number(main, fss_basic_read_parameter_line, fss_basic_read_long_line_s, arguments, &data->line); if (F_status_is_error(status)) return status; } @@ -657,7 +677,7 @@ extern "C" { if (main->parameters[fss_basic_read_parameter_select].result == f_console_result_additional) { data->option |= fss_basic_read_data_option_select; - status = fss_basic_read_load_number(fss_basic_read_parameter_select, fss_basic_read_long_select_s, arguments, main, &data->select); + status = fss_basic_read_load_number(main, fss_basic_read_parameter_select, fss_basic_read_long_select_s, arguments, &data->select); if (F_status_is_error(status)) return status; } @@ -687,6 +707,10 @@ extern "C" { if (!names[i]) continue; + if (fss_basic_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (!(data->option & fss_basic_read_data_option_object) && data->option & fss_basic_read_data_option_content) { if (!(data->contents.array[i].used || (data->option & fss_basic_read_data_option_empty))) { continue; diff --git a/level_3/fss_basic_read/c/private-fss_basic_read.h b/level_3/fss_basic_read/c/private-fss_basic_read.h index 5c1f896..bc7d858 100644 --- a/level_3/fss_basic_read/c/private-fss_basic_read.h +++ b/level_3/fss_basic_read/c/private-fss_basic_read.h @@ -33,10 +33,10 @@ extern "C" { * * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed). * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -56,7 +56,7 @@ extern "C" { * @see fss_basic_read_depths_resize() */ #ifndef _di_fss_basic_read_depth_process_ - extern f_status_t fss_basic_read_depth_process(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_read_depth_process(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_depth_process_ /** @@ -83,7 +83,7 @@ extern "C" { * This will print an error message on error. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @@ -108,14 +108,14 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param parameter * An ID representing the parameter. * @param name * The parameter name to print on error. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param number * The location to store the loaded number. * @@ -130,7 +130,7 @@ extern "C" { * @see fss_basic_read_depths_resize() */ #ifndef _di_fss_basic_read_load_number_ - extern f_status_t fss_basic_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_read_load_number(fss_basic_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_load_number_ /** @@ -138,26 +138,26 @@ extern "C" { * * Only what is requested to print (Object, Content, both, or neither) will be printed, if there is something to print. * + * @param main + * The main program data. * @param at * The index in the Objects and Contents to print. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content * The delimits to be applied to Content. - * @param main - * The main data. * @param data * The program data. */ #ifndef _di_fss_basic_read_print_at_ - extern void fss_basic_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_read_main_t * const main, fss_basic_read_data_t * const data) F_attribute_visibility_internal_d; + extern void fss_basic_read_print_at(fss_basic_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_basic_read_data_t * const data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_print_at_ /** * Print the end of an Object (which is essentially the start of Content). * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_read_print_object_end_ extern void fss_basic_read_print_object_end(fss_basic_read_main_t * const main) F_attribute_visibility_internal_d; @@ -167,7 +167,7 @@ extern "C" { * Print the number one and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_read_print_one_ extern void fss_basic_read_print_one(fss_basic_read_main_t * const main) F_attribute_visibility_internal_d; @@ -177,7 +177,7 @@ extern "C" { * Print the end of an Object/Content set. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_read_print_set_end_ extern void fss_basic_read_print_set_end(fss_basic_read_main_t * const main) F_attribute_visibility_internal_d; @@ -187,7 +187,7 @@ extern "C" { * Print the number zero and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_read_print_zero_ extern void fss_basic_read_print_zero(fss_basic_read_main_t * const main) F_attribute_visibility_internal_d; @@ -198,10 +198,10 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -215,14 +215,14 @@ extern "C" { * @see fss_basic_read_process_option() */ #ifndef _di_fss_basic_read_process_ - extern f_status_t fss_basic_read_process(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_read_process(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_process_ /** * Process based on at parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -240,7 +240,7 @@ extern "C" { * Process based on columns parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -258,7 +258,7 @@ extern "C" { * Process based on line parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -293,10 +293,10 @@ extern "C" { /** * Process the parameters, populating the option property of the program data. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -310,14 +310,14 @@ extern "C" { * @see fss_basic_read_load_setting() */ #ifndef _di_fss_basic_read_process_option_ - extern f_status_t fss_basic_read_process_option(f_console_arguments_t * const arguments, fss_basic_read_main_t * const main, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_read_process_option(fss_basic_read_main_t * const main, const f_console_arguments_t *arguments, fss_basic_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_process_option_ /** * Process based on total parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names diff --git a/level_3/fss_basic_read/data/build/dependencies b/level_3/fss_basic_read/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_basic_read/data/build/dependencies +++ b/level_3/fss_basic_read/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_basic_write/c/fss_basic_write.c b/level_3/fss_basic_write/c/fss_basic_write.c index 4218e5c..0bad5fc 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.c +++ b/level_3/fss_basic_write/c/fss_basic_write.c @@ -57,7 +57,8 @@ extern "C" { #endif // _di_fss_basic_write_print_help_ #ifndef _di_fss_basic_write_main_ - f_status_t fss_basic_write_main(const f_console_arguments_t arguments, fss_basic_write_main_t *main) { + f_status_t fss_basic_write_main(fss_basic_write_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -67,7 +68,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_basic_write_parameter_no_color, fss_basic_write_parameter_light, fss_basic_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -173,15 +174,15 @@ extern "C" { output.id = -1; output.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &output); + status = f_file_stream_open(arguments->argv[location], 0, &output); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } else if (main->parameters[fss_basic_write_parameter_file].result == f_console_result_found) { - fss_basic_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_write_long_file_s); + fss_basic_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_write_long_file_s); status = F_status_set_error(F_parameter); } } @@ -190,15 +191,15 @@ extern "C" { if (main->parameters[fss_basic_write_parameter_object].locations.used || main->parameters[fss_basic_write_parameter_content].locations.used) { if (main->parameters[fss_basic_write_parameter_object].locations.used) { if (main->parameters[fss_basic_write_parameter_object].locations.used != main->parameters[fss_basic_write_parameter_object].values.used) { - fss_basic_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_write_long_object_s); + fss_basic_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_write_long_object_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_write_parameter_content].locations.used != main->parameters[fss_basic_write_parameter_content].values.used) { - fss_basic_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_write_long_content_s); + fss_basic_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_write_long_content_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_write_parameter_object].locations.used != main->parameters[fss_basic_write_parameter_content].locations.used && main->parameters[fss_basic_write_parameter_partial].result == f_console_result_none) { - fss_basic_write_error_parameter_same_times_print(*main); + fss_basic_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_basic_write_parameter_content].locations.used && main->parameters[fss_basic_write_parameter_partial].locations.used) { @@ -256,11 +257,11 @@ extern "C" { } else if (main->parameters[fss_basic_write_parameter_content].locations.used) { if (main->parameters[fss_basic_write_parameter_content].locations.used != main->parameters[fss_basic_write_parameter_content].values.used) { - fss_basic_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_basic_write_long_content_s); + fss_basic_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_basic_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_basic_write_parameter_partial].locations.used) { - fss_basic_write_error_parameter_same_times_print(*main); + fss_basic_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } } @@ -314,12 +315,12 @@ extern "C" { } else if (main->parameters[fss_basic_write_parameter_prepend].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_basic_write_parameter_prepend].values.array[main->parameters[fss_basic_write_parameter_prepend].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); // Even though this standard does not utilize this parameter, provide the validation for consistency. if (length) { f_string_range_t range = macro_f_string_range_t_initialize(length); - const f_string_static_t prepend = macro_f_string_static_t_initialize(arguments.argv[index], length); + const f_string_static_t prepend = macro_f_string_static_t_initialize(arguments->argv[index], length); for (; range.start < length; range.start++) { @@ -413,7 +414,7 @@ extern "C" { f_string_dynamic_t escaped = f_string_dynamic_t_initialize; if (main->process_pipe) { - status = fss_basic_write_process_pipe(*main, output, quote, &buffer); + status = fss_basic_write_process_pipe(main, output, quote, &buffer); if (F_status_is_error(status)) { if (main->error.verbosity != f_console_verbosity_quiet) { @@ -434,11 +435,16 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_basic_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_basic_write_parameter_object].values.array[i]]; + if (fss_basic_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_basic_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - status = fss_basic_write_process(*main, output, quote, &object, 0, &buffer); + status = fss_basic_write_process(main, output, quote, &object, 0, &buffer); if (F_status_is_error(status)) break; } // for } @@ -447,11 +453,16 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_basic_write_parameter_content].values.used; ++i) { - content.string = arguments.argv[main->parameters[fss_basic_write_parameter_content].values.array[i]]; + if (fss_basic_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + content.string = arguments->argv[main->parameters[fss_basic_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_basic_write_process(*main, output, quote, 0, &content, &buffer); + status = fss_basic_write_process(main, output, quote, 0, &content, &buffer); if (F_status_is_error(status)) break; } // for } @@ -459,15 +470,20 @@ extern "C" { else { for (f_array_length_t i = 0; i < main->parameters[fss_basic_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_basic_write_parameter_object].values.array[i]]; + if (fss_basic_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_basic_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - content.string = arguments.argv[main->parameters[fss_basic_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_basic_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_basic_write_process(*main, output, quote, &object, &content, &buffer); + status = fss_basic_write_process(main, output, quote, &object, &content, &buffer); if (F_status_is_error(status)) break; } // for } @@ -518,12 +534,13 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); fss_basic_write_main_delete(main); + return status; } #endif // _di_fss_basic_write_main_ #ifndef _di_fss_basic_write_main_delete_ - f_status_t fss_basic_write_main_delete(fss_basic_write_main_t *main) { + f_status_t fss_basic_write_main_delete(fss_basic_write_main_t * const main) { for (f_array_length_t i = 0; i < fss_basic_write_total_parameters_d; ++i) { diff --git a/level_3/fss_basic_write/c/fss_basic_write.h b/level_3/fss_basic_write/c/fss_basic_write.h index b2609be..3a3df38 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.h +++ b/level_3/fss_basic_write/c/fss_basic_write.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -149,6 +150,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_basic_write_main_t; @@ -160,6 +163,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_basic_write_data_ @@ -184,10 +188,18 @@ extern "C" { * * Be sure to call fss_basic_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -196,7 +208,7 @@ extern "C" { * @see fss_basic_write_main_delete() */ #ifndef _di_fss_basic_write_main_ - extern f_status_t fss_basic_write_main(const f_console_arguments_t arguments, fss_basic_write_main_t *main); + extern f_status_t fss_basic_write_main(fss_basic_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_basic_write_main_ /** @@ -205,7 +217,7 @@ extern "C" { * Be sure to call this after executing fss_basic_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -214,7 +226,7 @@ extern "C" { * @see fss_basic_write_main() */ #ifndef _di_fss_basic_write_main_delete_ - extern f_status_t fss_basic_write_main_delete(fss_basic_write_main_t *main); + extern f_status_t fss_basic_write_main_delete(fss_basic_write_main_t * const main); #endif // _di_fss_basic_write_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_basic_write/c/main.c b/level_3/fss_basic_write/c/main.c index 97f1f00..1e8da75 100644 --- a/level_3/fss_basic_write/c/main.c +++ b/level_3/fss_basic_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_basic_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_basic_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_basic_write/c/private-common.c b/level_3/fss_basic_write/c/private-common.c index d1c0ac4..66cad09 100644 --- a/level_3/fss_basic_write/c/private-common.c +++ b/level_3/fss_basic_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_basic_write_print_signal_received_ + void fss_basic_write_print_signal_received(fss_basic_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_basic_write_print_signal_received_ + +#ifndef _di_fss_basic_write_signal_received_ + f_status_t fss_basic_write_signal_received(fss_basic_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_basic_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_basic_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/private-common.h b/level_3/fss_basic_write/c/private-common.h index e583676..3fa1f5a 100644 --- a/level_3/fss_basic_write/c/private-common.h +++ b/level_3/fss_basic_write/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define fss_basic_write_common_allocation_small_d 16 #endif // _di_fss_basic_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_basic_write_print_signal_received_ + extern void fss_basic_write_print_signal_received(fss_basic_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_basic_write_signal_received_ + extern f_status_t fss_basic_write_signal_received(fss_basic_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/private-fss_basic_write.c b/level_3/fss_basic_write/c/private-fss_basic_write.c index f9abab2..0980837 100644 --- a/level_3/fss_basic_write/c/private-fss_basic_write.c +++ b/level_3/fss_basic_write/c/private-fss_basic_write.c @@ -7,62 +7,62 @@ extern "C" { #endif #ifndef _di_fss_basic_write_error_parameter_same_times_print_ - void fss_basic_write_error_parameter_same_times_print(const fss_basic_write_main_t main) { + void fss_basic_write_error_parameter_same_times_print(fss_basic_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sMust specify the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_object_s, main.error.notable); - fl_print_format("%[' parameter and the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_content_s, main.error.notable); - fl_print_format("%[' parameter the same number of times when not specifying the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_partial_s, main.error.notable); - fl_print_format("%[' parameter.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sMust specify the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_object_s, main->error.notable); + fl_print_format("%[' parameter and the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_content_s, main->error.notable); + fl_print_format("%[' parameter the same number of times when not specifying the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_basic_write_long_partial_s, main->error.notable); + fl_print_format("%[' parameter.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_write_error_parameter_same_times_print_ #ifndef _di_fss_basic_write_error_parameter_value_missing_print_ - void fss_basic_write_error_parameter_value_missing_print(const fss_basic_write_main_t main, const f_string_t symbol, const f_string_t parameter) { + void fss_basic_write_error_parameter_value_missing_print(fss_basic_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, symbol, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, symbol, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_write_error_parameter_value_missing_print_ #ifndef _di_fss_basic_write_error_parameter_unsupported_eol_print_ - void fss_basic_write_error_parameter_unsupported_eol_print(const fss_basic_write_main_t main) { + void fss_basic_write_error_parameter_unsupported_eol_print(fss_basic_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThis standard does not support end of line character '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[\\n%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[' in objects.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThis standard does not support end of line character '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[\\n%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[' in objects.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_basic_write_error_parameter_unsupported_eol_print_ #ifndef _di_fss_basic_write_process_ - f_status_t fss_basic_write_process(const fss_basic_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) { + f_status_t fss_basic_write_process(fss_basic_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_state_t state = macro_f_state_t_initialize(fss_basic_write_common_allocation_large_d, fss_basic_write_common_allocation_small_d, 0, 0, 0, 0, 0); @@ -81,7 +81,7 @@ extern "C" { } if (content) { - if (main.parameters[fss_basic_write_parameter_trim].result == f_console_result_found) { + if (main->parameters[fss_basic_write_parameter_trim].result == f_console_result_found) { complete = f_fss_complete_full_trim; } else { @@ -98,7 +98,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_basic_object_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_basic_object_write_string", F_true); return status; } @@ -123,7 +123,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_basic_content_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_basic_content_write_string", F_true); return status; } @@ -133,7 +133,7 @@ extern "C" { status = f_string_append(f_string_eol_s, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -142,12 +142,13 @@ extern "C" { fll_print_dynamic(*buffer, output.stream); buffer->used = 0; + return status; } #endif // _di_fss_basic_write_process_ #ifndef _di_fss_basic_write_process_pipe_ - f_status_t fss_basic_write_process_pipe(const fss_basic_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { + f_status_t fss_basic_write_process_pipe(fss_basic_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_status_t status_pipe = F_none; @@ -170,6 +171,10 @@ extern "C" { for (;;) { + if (fss_basic_write_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (range.start > range.stop) { if (status_pipe == F_none_eof) break; @@ -178,7 +183,7 @@ extern "C" { status_pipe = f_file_read_block(input, &block); if (F_status_is_error(status_pipe)) { - fll_error_print(main.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); + fll_error_print(main->error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); status_pipe = F_status_set_error(F_pipe); break; @@ -202,7 +207,7 @@ extern "C" { status = f_string_dynamic_increase_by(block.used, &object); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -251,7 +256,7 @@ extern "C" { status = f_string_dynamic_increase_by(total, &content); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -259,8 +264,8 @@ extern "C" { for (; range.start <= range.stop; ++range.start) { if (block.string[range.start] == fss_basic_write_pipe_content_start_s) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context, f_string_eol_s[0]); } status = F_status_set_error(F_supported_not); @@ -311,6 +316,7 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(block); macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); + return status; } #endif // _di_fss_basic_write_process_pipe_ diff --git a/level_3/fss_basic_write/c/private-fss_basic_write.h b/level_3/fss_basic_write/c/private-fss_basic_write.h index 72bd3ef..f27e702 100644 --- a/level_3/fss_basic_write/c/private-fss_basic_write.h +++ b/level_3/fss_basic_write/c/private-fss_basic_write.h @@ -16,41 +16,41 @@ extern "C" { * Print an message about the object and content parameters not being specified the same number of times. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_write_error_parameter_same_times_print_ - void fss_basic_write_error_parameter_same_times_print(const fss_basic_write_main_t main) F_attribute_visibility_internal_d; + void fss_basic_write_error_parameter_same_times_print(fss_basic_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_basic_write_error_parameter_same_times_print_ /** * Print an message about a parameter missing a value. * * @param main - * The main data. + * The main program data. * @param symbol * The console symbol, such as "--" in "--help". * @param parameter * The parameter name, such as "help" in "--help". */ #ifndef _di_fss_basic_write_error_parameter_value_missing_print_ - void fss_basic_write_error_parameter_value_missing_print(const fss_basic_write_main_t main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; + void fss_basic_write_error_parameter_value_missing_print(fss_basic_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fss_basic_write_error_parameter_value_missing_print_ /** * Print an message about a parameter EOL being unsupported. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_basic_write_error_parameter_unsupported_eol_print_ - void fss_basic_write_error_parameter_unsupported_eol_print(const fss_basic_write_main_t main) F_attribute_visibility_internal_d; + void fss_basic_write_error_parameter_unsupported_eol_print(fss_basic_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_basic_write_error_parameter_unsupported_eol_print_ /** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -70,14 +70,14 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_basic_write_process_ - extern f_status_t fss_basic_write_process(const fss_basic_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_write_process(fss_basic_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_basic_write_process_ /** * Process the pipe, reading from the pipe and writing to the output. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -91,9 +91,27 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_basic_write_process_pipe_ - extern f_status_t fss_basic_write_process_pipe(const fss_basic_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_basic_write_process_pipe(fss_basic_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_basic_write_process_pipe_ +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_basic_write_signal_received_ + extern f_status_t fss_basic_write_signal_received(fss_basic_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_basic_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/data/build/dependencies b/level_3/fss_basic_write/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_basic_write/data/build/dependencies +++ b/level_3/fss_basic_write/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c index 9cfcd54..1021763 100644 --- a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c +++ b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c @@ -118,7 +118,7 @@ extern "C" { #endif // _di_fss_embedded_list_read_print_help_ #ifndef _di_fss_embedded_list_read_main_ - f_status_t fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_main_t *main) { + f_status_t fss_embedded_list_read_main(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; { @@ -128,7 +128,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_embedded_list_read_parameter_no_color, fss_embedded_list_read_parameter_light, fss_embedded_list_read_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -331,7 +331,7 @@ extern "C" { } else if (main->parameters[fss_embedded_list_read_parameter_delimit].result == f_console_result_additional) { const f_array_length_t location = main->parameters[fss_embedded_list_read_parameter_delimit].values.array[0]; - f_array_length_t length = strnlen(arguments.argv[location], f_console_parameter_size); + f_array_length_t length = strnlen(arguments->argv[location], f_console_parameter_size); if (length == 0) { flockfile(main->error.to.stream); @@ -344,22 +344,22 @@ extern "C" { status = F_status_set_error(F_parameter); } - else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_none_s, length, fss_embedded_list_read_delimit_mode_name_none_s_length) == F_equal_to) { + else if (fl_string_compare(arguments->argv[location], fss_embedded_list_read_delimit_mode_name_none_s, length, fss_embedded_list_read_delimit_mode_name_none_s_length) == F_equal_to) { main->delimit_mode = fss_embedded_list_read_delimit_mode_none; } - else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_all_s, length, fss_embedded_list_read_delimit_mode_name_all_s_length) == F_equal_to) { + else if (fl_string_compare(arguments->argv[location], fss_embedded_list_read_delimit_mode_name_all_s, length, fss_embedded_list_read_delimit_mode_name_all_s_length) == F_equal_to) { main->delimit_mode = fss_embedded_list_read_delimit_mode_all; } else { main->delimit_mode = fss_embedded_list_read_delimit_mode_depth; - if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_greater_s[0]) { + if (arguments->argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_greater_s[0]) { main->delimit_mode = fss_embedded_list_read_delimit_mode_depth_greater; // shorten the length to better convert the remainder to a number. --length; } - else if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_lesser_s[0]) { + else if (arguments->argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_lesser_s[0]) { main->delimit_mode = fss_embedded_list_read_delimit_mode_depth_lesser; // shorten the length to better convert the remainder to a number. @@ -369,14 +369,14 @@ extern "C" { f_string_range_t range = macro_f_string_range_t_initialize(length); // ignore leading plus sign. - if (arguments.argv[location][0] == '+') { + if (arguments->argv[location][0] == '+') { ++range.start; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[location], range, &main->delimit_depth); + status = fl_conversion_string_to_number_unsigned(arguments->argv[location], range, &main->delimit_depth); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_delimit_s, arguments.argv[location]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_delimit_s, arguments->argv[location]); } } } @@ -391,7 +391,7 @@ extern "C" { f_array_length_t original_size = main->quantity.total; if (F_status_is_error_not(status)) { - status = fss_embedded_list_read_main_preprocess_depth(arguments, *main, &depths); + status = fss_embedded_list_read_main_preprocess_depth(main, arguments, &depths); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true); @@ -421,7 +421,7 @@ extern "C" { fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read", F_true, "-", "read", fll_error_file_type_pipe); } else { - status = fss_embedded_list_read_main_process_file(arguments, main, "-", depths, &objects_delimits, &contents_delimits, &comments); + status = fss_embedded_list_read_main_process_file(main, arguments, "-", depths, &objects_delimits, &contents_delimits, &comments); if (F_status_is_error(status)) { fll_error_file_print(main->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, "-", "read", fll_error_file_type_pipe); @@ -435,21 +435,27 @@ extern "C" { if (F_status_is_error_not(status) && main->remaining.used > 0) { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + + if (fss_embedded_list_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + f_file_t file = f_file_t_initialize; - status = f_file_open(arguments.argv[main->remaining.array[i]], 0, &file); + status = f_file_open(arguments->argv[main->remaining.array[i]], 0, &file); main->quantity.total = original_size; if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[main->remaining.array[i]], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments->argv[main->remaining.array[i]], "open", fll_error_file_type_file); break; } if (!main->quantity.total) { status = f_file_size_by_id(file.id, &main->quantity.total); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); f_file_stream_close(F_true, &file); break; @@ -471,14 +477,14 @@ extern "C" { f_file_stream_close(F_true, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); break; } - status = fss_embedded_list_read_main_process_file(arguments, main, arguments.argv[main->remaining.array[i]], depths, &objects_delimits, &contents_delimits, &comments); + status = fss_embedded_list_read_main_process_file(main, arguments, arguments->argv[main->remaining.array[i]], depths, &objects_delimits, &contents_delimits, &comments); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, arguments.argv[main->remaining.array[i]], "read", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, arguments->argv[main->remaining.array[i]], "read", fll_error_file_type_file); break; } @@ -503,13 +509,22 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_embedded_list_read_main_delete(main); + return status; } #endif // _di_fss_embedded_list_read_main_ #ifndef _di_fss_embedded_list_read_main_delete_ - f_status_t fss_embedded_list_read_main_delete(fss_embedded_list_read_main_t *main) { + f_status_t fss_embedded_list_read_main_delete(fss_embedded_list_read_main_t * const main) { for (f_array_length_t i = 0; i < fss_embedded_list_read_total_parameters_d; ++i) { diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h index 6eb8a95..82ab44a 100644 --- a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h +++ b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -194,6 +195,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_string_dynamic_t buffer; f_fss_nest_t nest; f_string_quantity_t quantity; @@ -212,6 +215,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_dynamic_t_initialize, \ f_fss_nest_t_initialize, \ f_string_quantity_t_initialize, \ @@ -241,10 +245,18 @@ extern "C" { * * Be sure to call fss_embedded_list_read_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -254,7 +266,7 @@ extern "C" { * @see fss_embedded_list_read_main_delete() */ #ifndef _di_fss_embedded_list_read_main_ - extern f_status_t fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_main_t *main); + extern f_status_t fss_embedded_list_read_main(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_embedded_list_read_main_ /** @@ -263,7 +275,7 @@ extern "C" { * Be sure to call this after executing fss_embedded_list_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -273,7 +285,7 @@ extern "C" { * @see fss_embedded_list_read_main() */ #ifndef _di_fss_embedded_list_read_main_delete_ - extern f_status_t fss_embedded_list_read_main_delete(fss_embedded_list_read_main_t *main); + extern f_status_t fss_embedded_list_read_main_delete(fss_embedded_list_read_main_t * const main); #endif // _di_fss_embedded_list_read_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_read/c/main.c b/level_3/fss_embedded_list_read/c/main.c index a874c21..37877e9 100644 --- a/level_3/fss_embedded_list_read/c/main.c +++ b/level_3/fss_embedded_list_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_embedded_list_read_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_embedded_list_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_embedded_list_read/c/private-common.c b/level_3/fss_embedded_list_read/c/private-common.c index d62fdfa..68cb82a 100644 --- a/level_3/fss_embedded_list_read/c/private-common.c +++ b/level_3/fss_embedded_list_read/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_embedded_list_read_print_signal_received_ + void fss_embedded_list_read_print_signal_received(fss_embedded_list_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_embedded_list_read_print_signal_received_ + +#ifndef _di_fss_embedded_list_read_signal_received_ + f_status_t fss_embedded_list_read_signal_received(fss_embedded_list_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_embedded_list_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_embedded_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/private-common.h b/level_3/fss_embedded_list_read/c/private-common.h index 4ce89d9..d410fd0 100644 --- a/level_3/fss_embedded_list_read/c/private-common.h +++ b/level_3/fss_embedded_list_read/c/private-common.h @@ -146,6 +146,36 @@ extern "C" { } #endif // _di_fss_embedded_list_read_depths_t_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_embedded_list_read_print_signal_received_ + extern void fss_embedded_list_read_print_signal_received(fss_embedded_list_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_embedded_list_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_embedded_list_read_signal_received_ + extern f_status_t fss_embedded_list_read_signal_received(fss_embedded_list_read_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_embedded_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c index d41b0b5..b79a1af 100644 --- a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c +++ b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c @@ -7,10 +7,11 @@ extern "C" { #endif #ifndef _di_fss_embedded_list_read_main_preprocess_depth_ - f_status_t fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_main_t main, fss_embedded_list_read_depths_t *depths) { + f_status_t fss_embedded_list_read_main_preprocess_depth(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_embedded_list_read_depths_t *depths) { + f_status_t status = F_none; - const f_array_length_t values_total = main.parameters[fss_embedded_list_read_parameter_depth].values.used + main.parameters[fss_embedded_list_read_parameter_at].values.used + main.parameters[fss_embedded_list_read_parameter_name].values.used; + const f_array_length_t values_total = main->parameters[fss_embedded_list_read_parameter_depth].values.used + main->parameters[fss_embedded_list_read_parameter_at].values.used + main->parameters[fss_embedded_list_read_parameter_name].values.used; f_array_length_t values_order[values_total]; f_array_length_t values_type[values_total]; @@ -25,24 +26,24 @@ extern "C" { f_array_length_t k = 0; f_array_length_t l = 0; - for (; j < main.parameters[fss_embedded_list_read_parameter_depth].values.used; ++j) { + for (; j < main->parameters[fss_embedded_list_read_parameter_depth].values.used; ++j) { - values_order[i] = main.parameters[fss_embedded_list_read_parameter_depth].values.array[j]; + values_order[i] = main->parameters[fss_embedded_list_read_parameter_depth].values.array[j]; values_type[i++] = fss_embedded_list_read_parameter_depth; } // for if (i) { - for (j = 0; j < main.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) { + for (j = 0; j < main->parameters[fss_embedded_list_read_parameter_at].values.used; ++j) { for (k = 0; k < i; ++k) { - if (values_order[k] > main.parameters[fss_embedded_list_read_parameter_at].values.array[j]) { + if (values_order[k] > main->parameters[fss_embedded_list_read_parameter_at].values.array[j]) { for (l = i; l > k; --l) { values_order[l] = values_order[l - 1]; values_type[l] = values_type[l - 1]; } // for - values_order[k] = main.parameters[fss_embedded_list_read_parameter_at].values.array[j]; + values_order[k] = main->parameters[fss_embedded_list_read_parameter_at].values.array[j]; values_type[k] = fss_embedded_list_read_parameter_at; i++; break; @@ -50,31 +51,31 @@ extern "C" { } // for if (k == i) { - values_order[i] = main.parameters[fss_embedded_list_read_parameter_at].values.array[j]; + values_order[i] = main->parameters[fss_embedded_list_read_parameter_at].values.array[j]; values_type[i++] = fss_embedded_list_read_parameter_at; } } // for } else { - for (; j < main.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) { + for (; j < main->parameters[fss_embedded_list_read_parameter_at].values.used; ++j) { - values_order[i] = main.parameters[fss_embedded_list_read_parameter_at].values.array[j]; + values_order[i] = main->parameters[fss_embedded_list_read_parameter_at].values.array[j]; values_type[i++] = fss_embedded_list_read_parameter_at; } // for } if (i) { - for (j = 0; j < main.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) { + for (j = 0; j < main->parameters[fss_embedded_list_read_parameter_name].values.used; ++j) { for (k = 0; k < i; ++k) { - if (values_order[k] > main.parameters[fss_embedded_list_read_parameter_name].values.array[j]) { + if (values_order[k] > main->parameters[fss_embedded_list_read_parameter_name].values.array[j]) { for (l = i; l > k; --l) { values_order[l] = values_order[l - 1]; values_type[l] = values_type[l - 1]; } // for - values_order[k] = main.parameters[fss_embedded_list_read_parameter_name].values.array[j]; + values_order[k] = main->parameters[fss_embedded_list_read_parameter_name].values.array[j]; values_type[k] = fss_embedded_list_read_parameter_name; i++; break; @@ -82,15 +83,15 @@ extern "C" { } // for if (k == i) { - values_order[i] = main.parameters[fss_embedded_list_read_parameter_name].values.array[j]; + values_order[i] = main->parameters[fss_embedded_list_read_parameter_name].values.array[j]; values_type[i++] = fss_embedded_list_read_parameter_name; } } // for } else { - for (; j < main.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) { + for (; j < main->parameters[fss_embedded_list_read_parameter_name].values.used; ++j) { - values_order[i] = main.parameters[fss_embedded_list_read_parameter_name].values.array[j]; + values_order[i] = main->parameters[fss_embedded_list_read_parameter_name].values.array[j]; values_type[i++] = fss_embedded_list_read_parameter_name; } // for } @@ -99,14 +100,14 @@ extern "C" { { i = 1; - if (main.parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_additional) { - i = main.parameters[fss_embedded_list_read_parameter_depth].values.used + 1; + if (main->parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_additional) { + i = main->parameters[fss_embedded_list_read_parameter_depth].values.used + 1; } macro_fss_embedded_list_read_depths_t_resize(status, (*depths), i); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true); return status; } @@ -124,13 +125,17 @@ extern "C" { for (i = 0; i < values_total; ++i) { + if (fss_embedded_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (values_type[i] == fss_embedded_list_read_parameter_depth || values_type[i] == fss_embedded_list_read_parameter_at) { - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[values_order[i]])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[values_order[i]])); - status = fl_conversion_string_to_number_unsigned(arguments.argv[values_order[i]], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[values_order[i]], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_depth_s, arguments.argv[values_order[i]]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_depth_s, arguments->argv[values_order[i]]); return status; } @@ -163,20 +168,20 @@ extern "C" { depths->array[depths->used].index_name = values_order[i]; depths->array[depths->used].value_name.used = 0; - if (main.parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) { - status = fl_string_rip(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_parameter_size), &depths->array[depths->used].value_name); + if (main->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) { + status = fl_string_rip(arguments->argv[values_order[i]], strnlen(arguments->argv[values_order[i]], f_console_parameter_size), &depths->array[depths->used].value_name); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_string_rip", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_string_rip", F_true); return status; } } else { - status = f_string_append(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_parameter_size), &depths->array[depths->used].value_name); + status = f_string_append(arguments->argv[values_order[i]], strnlen(arguments->argv[values_order[i]], f_console_parameter_size), &depths->array[depths->used].value_name); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -192,30 +197,30 @@ extern "C" { for (j = i + 1; j < depths->used; ++j) { if (depths->array[i].depth == depths->array[j].depth) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe value '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, depths->array[i].depth, main.error.notable); - fl_print_format("%[' may only be specified once for the parameter '%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe value '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, depths->array[i].depth, main->error.notable); + fl_print_format("%[' may only be specified once for the parameter '%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); return F_status_set_error(F_parameter); } else if (depths->array[i].depth > depths->array[j].depth) { - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, main.error.notable); - fl_print_format("%[' may not have the value '%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, depths->array[i].depth, main.error.notable); - fl_print_format("%[' before the value '%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[%ul%]", main.error.to.stream, main.error.notable, depths->array[j].depth, main.error.notable); - fl_print_format("%['.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, main->error.notable); + fl_print_format("%[' may not have the value '%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, depths->array[i].depth, main->error.notable); + fl_print_format("%[' before the value '%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[%ul%]", main->error.to.stream, main->error.notable, depths->array[j].depth, main->error.notable); + fl_print_format("%['.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); return F_status_set_error(F_parameter); } @@ -227,7 +232,7 @@ extern "C" { #endif // _di_fss_embedded_list_read_main_preprocess_depth_ #ifndef _di_fss_embedded_list_read_main_process_file_ - f_status_t fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_main_t *main, const f_string_t filename, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) { + f_status_t fss_embedded_list_read_main_process_file(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) { f_status_t status = F_none; @@ -292,12 +297,12 @@ extern "C" { if (main->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_embedded_list_read_parameter_select].values.array[main->parameters[fss_embedded_list_read_parameter_select].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &select); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &select); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_select_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_select_s, arguments->argv[index]); return status; } @@ -313,18 +318,18 @@ extern "C" { if (main->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_embedded_list_read_parameter_line].values.array[main->parameters[fss_embedded_list_read_parameter_line].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &line); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &line); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_line_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_line_s, arguments->argv[index]); return status; } } - fss_embedded_list_read_process_delimits(*main, objects_delimits, contents_delimits); + fss_embedded_list_read_process_delimits(main, objects_delimits, contents_delimits); const fss_embedded_list_read_skip_t parents = fss_embedded_list_read_skip_t_initialize; @@ -332,15 +337,15 @@ extern "C" { if (main->parameters[fss_embedded_list_read_parameter_raw].result == f_console_result_found) { f_fss_delimits_t except_none = f_fss_delimits_t_initialize; - return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, 0, line, parents, main, &except_none, &except_none); + return fss_embedded_list_read_main_process_for_depth(main, arguments, filename, depths, 0, line, parents, &except_none, &except_none); } - return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, 0, line, parents, main, objects_delimits, contents_delimits); + return fss_embedded_list_read_main_process_for_depth(main, arguments, filename, depths, 0, line, parents, objects_delimits, contents_delimits); } #endif // _di_fss_embedded_list_read_main_process_file_ #ifndef _di_fss_embedded_list_read_main_process_for_depth_ - f_status_t fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_main_t *main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) { + f_status_t fss_embedded_list_read_main_process_for_depth(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) { f_fss_items_t *items = &main->nest.depth[depths.array[depths_index].depth]; @@ -482,7 +487,7 @@ extern "C" { } // for } - return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, depths_index + 1, line, parents_next, main, objects_delimits, contents_delimits); + return fss_embedded_list_read_main_process_for_depth(main, arguments, filename, depths, depths_index + 1, line, parents_next, objects_delimits, contents_delimits); } // process objects. @@ -519,14 +524,14 @@ extern "C" { print_object(main->buffer, items->array[i].object, *objects_delimits, main->output.to.stream); if (main->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) { - fss_embedded_list_read_print_object_end(*main); + fss_embedded_list_read_print_object_end(main); if (items->array[i].content.used) { f_print_except_dynamic_partial(main->buffer, items->array[i].content.array[0], *contents_delimits, main->output.to.stream); } } - fss_embedded_list_read_print_set_end(*main); + fss_embedded_list_read_print_set_end(main); } // for funlockfile(main->output.to.stream); @@ -548,6 +553,10 @@ extern "C" { if (skip[i]) continue; + if (fss_embedded_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (!items->array[i].content.used) { if (include_empty) { ++total; @@ -583,7 +592,7 @@ extern "C" { if (!items->array[i].content.used) { if (include_empty) { if (line_current == line) { - fss_embedded_list_read_print_set_end(*main); + fss_embedded_list_read_print_set_end(main); break; } @@ -641,7 +650,7 @@ extern "C" { if (!items->array[i].content.used) { if (include_empty) { - fss_embedded_list_read_print_set_end(*main); + fss_embedded_list_read_print_set_end(main); } continue; @@ -661,68 +670,68 @@ extern "C" { #endif // _di_fss_embedded_list_read_main_process_for_depth_ #ifndef _di_fss_embedded_list_read_print_object_end_ - void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_main_t main) { + void fss_embedded_list_read_print_object_end(fss_embedded_list_read_main_t * const main) { - if (main.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { - f_print_character(fss_embedded_list_read_pipe_content_start_s, main.output.to.stream); + if (main->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { + f_print_character(fss_embedded_list_read_pipe_content_start_s, main->output.to.stream); } else { - if (main.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && main.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) { - f_print_character(f_fss_embedded_list_open_s[0], main.output.to.stream); - f_print_character(f_fss_embedded_list_open_end_s[0], main.output.to.stream); + if (main->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && main->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) { + f_print_character(f_fss_embedded_list_open_s[0], main->output.to.stream); + f_print_character(f_fss_embedded_list_open_end_s[0], main->output.to.stream); } else { - f_print_character(f_fss_eol_s[0], main.output.to.stream); + f_print_character(f_fss_eol_s[0], main->output.to.stream); } } } #endif // _di_fss_embedded_list_read_print_object_end_ #ifndef _di_fss_embedded_list_read_print_content_ignore_ - void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_main_t main) { + void fss_embedded_list_read_print_content_ignore(fss_embedded_list_read_main_t * const main) { - if (main.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { - f_print_character(fss_embedded_list_read_pipe_content_ignore_s, main.output.to.stream); + if (main->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { + f_print_character(fss_embedded_list_read_pipe_content_ignore_s, main->output.to.stream); } } #endif // _di_fss_embedded_list_read_print_content_ignore_ #ifndef _di_fss_embedded_list_read_print_set_end_ - void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_main_t main) { + void fss_embedded_list_read_print_set_end(fss_embedded_list_read_main_t * const main) { - if (main.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { - f_print_character(fss_embedded_list_read_pipe_content_end_s, main.output.to.stream); + if (main->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) { + f_print_character(fss_embedded_list_read_pipe_content_end_s, main->output.to.stream); } else { - if (main.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && main.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) { - f_print_character(f_fss_embedded_list_close_s[0], main.output.to.stream); - f_print_character(f_fss_embedded_list_close_end_s[0], main.output.to.stream); + if (main->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && main->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) { + f_print_character(f_fss_embedded_list_close_s[0], main->output.to.stream); + f_print_character(f_fss_embedded_list_close_end_s[0], main->output.to.stream); } else { - f_print_character(f_fss_eol_s[0], main.output.to.stream); + f_print_character(f_fss_eol_s[0], main->output.to.stream); } } } #endif // _di_fss_embedded_list_read_print_set_end_ #ifndef _di_fss_embedded_list_read_process_delimits_ - void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_main_t main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) { + void fss_embedded_list_read_process_delimits(fss_embedded_list_read_main_t * const main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) { - if (!main.nest.used) return; + if (!main->nest.used) return; - if ((!objects_delimits->used && !contents_delimits->used) || main.delimit_mode == fss_embedded_list_read_delimit_mode_all) return; + if ((!objects_delimits->used && !contents_delimits->used) || main->delimit_mode == fss_embedded_list_read_delimit_mode_all) return; - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser && main.nest.used < main.delimit_depth) return; - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater && main.delimit_depth == 0) return; + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser && main->nest.used < main->delimit_depth) return; + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater && main->delimit_depth == 0) return; - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_none) { + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_none) { objects_delimits->used = 0; contents_delimits->used = 0; return; } - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth || main.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) { - if (main.delimit_depth >= main.nest.used) { + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth || main->delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) { + if (main->delimit_depth >= main->nest.used) { objects_delimits->used = 0; contents_delimits->used = 0; return; @@ -741,34 +750,34 @@ extern "C" { objects_delimits->used = 0; contents_delimits->used = 0; - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth) { + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth) { // only depth 0 objects are stored in objects_delimits. - if (main.delimit_depth) { - fss_embedded_list_read_process_delimits_objects(main, main.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits); + if (main->delimit_depth) { + fss_embedded_list_read_process_delimits_objects(main, main->delimit_depth, original_contents_delimits, original_contents_used, contents_delimits); } else { - fss_embedded_list_read_process_delimits_objects(main, main.delimit_depth, original_objects_delimits, original_objects_used, objects_delimits); + fss_embedded_list_read_process_delimits_objects(main, main->delimit_depth, original_objects_delimits, original_objects_used, objects_delimits); } - fss_embedded_list_read_process_delimits_contents(main, main.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits); + fss_embedded_list_read_process_delimits_contents(main, main->delimit_depth, original_contents_delimits, original_contents_used, contents_delimits); } else { - if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser) { + if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser) { // only depth 0 objects are stored in objects_delimits. fss_embedded_list_read_process_delimits_objects(main, 0, original_objects_delimits, original_objects_used, objects_delimits); fss_embedded_list_read_process_delimits_contents(main, 0, original_contents_delimits, original_contents_used, contents_delimits); - for (f_array_length_t i = 1; i <= main.delimit_depth && i < main.nest.used; ++i) { + for (f_array_length_t i = 1; i <= main->delimit_depth && i < main->nest.used; ++i) { fss_embedded_list_read_process_delimits_objects(main, i, original_contents_delimits, original_contents_used, contents_delimits); fss_embedded_list_read_process_delimits_contents(main, i, original_contents_delimits, original_contents_used, contents_delimits); } // for } - else if (main.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) { - for (f_array_length_t i = main.delimit_depth; i < main.nest.used; ++i) { + else if (main->delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) { + for (f_array_length_t i = main->delimit_depth; i < main->nest.used; ++i) { fss_embedded_list_read_process_delimits_objects(main, i, original_contents_delimits, original_contents_used, contents_delimits); fss_embedded_list_read_process_delimits_contents(main, i, original_contents_delimits, original_contents_used, contents_delimits); @@ -779,11 +788,11 @@ extern "C" { #endif // _di_fss_embedded_list_read_process_delimits_ #ifndef _di_fss_embedded_list_read_process_delimits_contents_ - void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) { + void fss_embedded_list_read_process_delimits_contents(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) { if (!original_used) return; - f_fss_items_t *items = &main.nest.depth[depth]; + f_fss_items_t *items = &main->nest.depth[depth]; if (!items->used) return; @@ -832,11 +841,11 @@ extern "C" { #endif // _di_fss_embedded_list_read_process_delimits_contents_ #ifndef _di_fss_embedded_list_read_process_delimits_objects_ - void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) { + void fss_embedded_list_read_process_delimits_objects(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) { if (!original_used) return; - f_fss_items_t *items = &main.nest.depth[depth]; + f_fss_items_t *items = &main->nest.depth[depth]; if (!items->used) return; @@ -881,17 +890,17 @@ extern "C" { #endif // _di_fss_embedded_list_read_process_delimits_objects_ #ifndef _di_fss_embedded_list_read_process_delimits_within_greater_ - f_status_t fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t location) { + f_status_t fss_embedded_list_read_process_delimits_within_greater(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t location) { - if (depth + 1 >= main.nest.used) return F_false; + if (depth + 1 >= main->nest.used) return F_false; f_fss_items_t *items = 0; f_array_length_t i = 0; f_array_length_t j = 0; - for (f_array_length_t d = depth + 1; d < main.nest.used; ++d) { - items = &main.nest.depth[d]; + for (f_array_length_t d = depth + 1; d < main->nest.used; ++d) { + items = &main->nest.depth[d]; for (i = 0; i < items->used; ++i) { diff --git a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h index a16a732..c63047d 100644 --- a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h +++ b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h @@ -17,10 +17,10 @@ extern "C" { * * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed). * + * @param main + * The main program data. * @param arguments * The console arguments to pre-process. - * @param main - * The main data. * @param depths * This stores the pre-processed depth parameters. * @@ -30,16 +30,16 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_embedded_list_read_main_preprocess_depth_ - extern f_status_t fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_main_t main, fss_embedded_list_read_depths_t *depths) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_read_main_preprocess_depth(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_embedded_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_main_preprocess_depth_ /** * Process a given file. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param file_name * The name of the file being processed. * @param depths @@ -61,7 +61,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_embedded_list_read_main_process_file_ - extern f_status_t fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_main_t *main, const f_string_t file_name, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_read_main_process_file(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_main_process_file_ /** @@ -69,6 +69,8 @@ extern "C" { * * This will recursively continue down the depth chain until the final depth is reached. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name @@ -82,8 +84,6 @@ extern "C" { * @param parents * The skip status of any parent lists. * Set parents.length to 0 for depth 0. - * @param main - * The main data. * @param objects_delimits * An array of delimits detected during processing, for top-level objects. * @param contents_delimits @@ -97,7 +97,7 @@ extern "C" { * @see fss_embedded_list_read_main_process_file() */ #ifndef _di_fss_embedded_list_read_main_process_for_depth_ - extern f_status_t fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_main_t *main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_read_main_process_for_depth(fss_embedded_list_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_main_process_for_depth_ /** @@ -106,37 +106,37 @@ extern "C" { * This is only used in pipe output mode. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_embedded_list_read_print_content_ignore_ - extern void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_main_t main) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_print_content_ignore(fss_embedded_list_read_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_print_content_ignore_ /** * Print the end of an object (which is essentially the start of a content). * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_embedded_list_read_print_object_end_ - extern void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_main_t main) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_print_object_end(fss_embedded_list_read_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_print_object_end_ /** * Print the end of an object/content set. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_embedded_list_read_print_set_end_ - extern void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_main_t main) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_print_set_end(fss_embedded_list_read_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_print_set_end_ /** * Rewrite the object and content delimit ranges to be within the given depth range. * * @param main - * The main data. + * The main program data. * @param objects_delimits * An array of delimits detected during processing, for top-level objects. * @param contents_delimits @@ -145,14 +145,14 @@ extern "C" { * @see fss_embedded_list_read_main_process_file() */ #ifndef _di_fss_embedded_list_read_process_delimits_ - extern void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_main_t main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_process_delimits(fss_embedded_list_read_main_t * const main, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_process_delimits_ /** * Write the given delimits at the given depth back into the new delimits array, specifically for contents. * * @param main - * The main data. + * The main program data. * @param depth * The depth in which to process. * @param original_delimits @@ -165,14 +165,14 @@ extern "C" { * @see fss_embedded_list_read_process_delimits() */ #ifndef _di_fss_embedded_list_read_process_delimits_contents_ - extern void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_process_delimits_contents(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_process_delimits_contents_ /** * Write the given delimits at the given depth back into the new delimits array, specifically for objects. * * @param main - * The main data. + * The main program data. * @param depth * The depth in which to process. * @param original_delimits @@ -185,14 +185,14 @@ extern "C" { * @see fss_embedded_list_read_process_delimits() */ #ifndef _di_fss_embedded_list_read_process_delimits_objects_ - extern void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) F_attribute_visibility_internal_d; + extern void fss_embedded_list_read_process_delimits_objects(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t original_delimits[], const f_array_length_t original_used, f_fss_delimits_t *delimits) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_process_delimits_objects_ /** * Determine if the given location is actually within another depth. * * @param main - * The main data. + * The main program data. * @param depth * The depth in which to process. * @param location @@ -206,7 +206,7 @@ extern "C" { * @see fss_embedded_list_read_process_delimits_contents() */ #ifndef _di_fss_embedded_list_read_process_delimits_within_greater_ - extern f_status_t fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_main_t main, const f_array_length_t depth, const f_array_length_t location) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_read_process_delimits_within_greater(fss_embedded_list_read_main_t * const main, const f_array_length_t depth, const f_array_length_t location) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_process_delimits_within_greater_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_read/data/build/dependencies b/level_3/fss_embedded_list_read/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_embedded_list_read/data/build/dependencies +++ b/level_3/fss_embedded_list_read/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c index 3c49f4b..1541118 100644 --- a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c +++ b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c @@ -60,7 +60,7 @@ extern "C" { #endif // _di_fss_embedded_list_write_print_help_ #ifndef _di_fss_embedded_list_write_main_ - f_status_t fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_main_t *main) { + f_status_t fss_embedded_list_write_main(fss_embedded_list_write_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; { @@ -70,7 +70,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_embedded_list_write_parameter_no_color, fss_embedded_list_write_parameter_light, fss_embedded_list_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -176,15 +176,15 @@ extern "C" { output.id = -1; output.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &output); + status = f_file_stream_open(arguments->argv[location], 0, &output); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } else if (main->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_found) { - fss_embedded_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_file_s); + fss_embedded_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_file_s); status = F_status_set_error(F_parameter); } } @@ -193,15 +193,15 @@ extern "C" { if (main->parameters[fss_embedded_list_write_parameter_object].locations.used || main->parameters[fss_embedded_list_write_parameter_content].locations.used) { if (main->parameters[fss_embedded_list_write_parameter_object].locations.used) { if (main->parameters[fss_embedded_list_write_parameter_object].locations.used != main->parameters[fss_embedded_list_write_parameter_object].values.used) { - fss_embedded_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_object_s); + fss_embedded_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_object_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_embedded_list_write_parameter_content].locations.used != main->parameters[fss_embedded_list_write_parameter_content].values.used) { - fss_embedded_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s); + fss_embedded_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_embedded_list_write_parameter_object].locations.used != main->parameters[fss_embedded_list_write_parameter_content].locations.used && main->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_none) { - fss_embedded_list_write_error_parameter_same_times_print(*main); + fss_embedded_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_embedded_list_write_parameter_content].locations.used && main->parameters[fss_embedded_list_write_parameter_partial].locations.used) { @@ -259,11 +259,11 @@ extern "C" { } else if (main->parameters[fss_embedded_list_write_parameter_content].locations.used) { if (main->parameters[fss_embedded_list_write_parameter_content].locations.used != main->parameters[fss_embedded_list_write_parameter_content].values.used) { - fss_embedded_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s); + fss_embedded_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_embedded_list_write_parameter_partial].locations.used) { - fss_embedded_list_write_error_parameter_same_times_print(*main); + fss_embedded_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } } @@ -317,12 +317,12 @@ extern "C" { } else if (main->parameters[fss_embedded_list_write_parameter_prepend].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_embedded_list_write_parameter_prepend].values.array[main->parameters[fss_embedded_list_write_parameter_prepend].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); if (length) { f_string_range_t range = macro_f_string_range_t_initialize(length); - main->prepend.string = arguments.argv[index]; + main->prepend.string = arguments->argv[index]; main->prepend.used = length; main->prepend.size = length; @@ -419,9 +419,9 @@ extern "C" { f_string_ranges_t ignore = f_string_ranges_t_initialize; if (main->process_pipe) { - status = fss_embedded_list_write_process_pipe(*main, output, quote, &buffer, &ignore); + status = fss_embedded_list_write_process_pipe(main, output, quote, &buffer, &ignore); - if (F_status_is_error(status)) { + if (F_status_is_error(status) && F_status_set_fine(status) != F_interrupt) { if (main->error.verbosity != f_console_verbosity_quiet) { flockfile(main->error.to.stream); @@ -441,25 +441,35 @@ extern "C" { if (main->parameters[fss_embedded_list_write_parameter_object].result == f_console_result_additional) { for (f_array_length_t i = 0; i < main->parameters[fss_embedded_list_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_embedded_list_write_parameter_object].values.array[i]]; + if (fss_embedded_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_embedded_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - status = fss_embedded_list_write_process(*main, output, quote, &object, 0, 0, &buffer); + status = fss_embedded_list_write_process(main, output, quote, &object, 0, 0, &buffer); if (F_status_is_error(status)) break; } // for } else { for (f_array_length_t i = 0; i < main->parameters[fss_embedded_list_write_parameter_content].values.used; ++i) { - status = fss_embedded_list_write_process_parameter_ignore(arguments, *main, main->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore); + if (fss_embedded_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status = fss_embedded_list_write_process_parameter_ignore(main, arguments, main->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore); if (F_status_is_error(status)) break; - content.string = arguments.argv[main->parameters[fss_embedded_list_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_embedded_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_embedded_list_write_process(*main, output, quote, 0, &content, &ignore, &buffer); + status = fss_embedded_list_write_process(main, output, quote, 0, &content, &ignore, &buffer); if (F_status_is_error(status)) break; } // for } @@ -467,18 +477,23 @@ extern "C" { else { for (f_array_length_t i = 0; i < main->parameters[fss_embedded_list_write_parameter_object].values.used; ++i) { - status = fss_embedded_list_write_process_parameter_ignore(arguments, *main, main->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore); + if (fss_embedded_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status = fss_embedded_list_write_process_parameter_ignore(main, arguments, main->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore); if (F_status_is_error(status)) break; - object.string = arguments.argv[main->parameters[fss_embedded_list_write_parameter_object].values.array[i]]; + object.string = arguments->argv[main->parameters[fss_embedded_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - content.string = arguments.argv[main->parameters[fss_embedded_list_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_embedded_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_embedded_list_write_process(*main, output, quote, &object, &content, &ignore, &buffer); + status = fss_embedded_list_write_process(main, output, quote, &object, &content, &ignore, &buffer); if (F_status_is_error(status)) break; } // for } @@ -530,12 +545,13 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); fss_embedded_list_write_main_delete(main); + return status; } #endif // _di_fss_embedded_list_write_main_ #ifndef _di_fss_embedded_list_write_main_delete_ - f_status_t fss_embedded_list_write_main_delete(fss_embedded_list_write_main_t *main) { + f_status_t fss_embedded_list_write_main_delete(fss_embedded_list_write_main_t * const main) { for (f_array_length_t i = 0; i < fss_embedded_list_write_total_parameters_d; ++i) { diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h index 8bc527e..3fd24b8 100644 --- a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h +++ b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -148,6 +149,9 @@ extern "C" { fl_print_t output; fl_print_t error; fl_print_t warning; + + f_signal_t signal; + f_string_static_t prepend; f_color_context_t context; @@ -161,6 +165,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_static_t_initialize, \ f_color_context_t_initialize, \ } @@ -186,10 +191,18 @@ extern "C" { * * Be sure to call fss_embedded_list_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -199,7 +212,7 @@ extern "C" { * @see fss_embedded_list_write_main_delete() */ #ifndef _di_fss_embedded_list_write_main_ - extern f_status_t fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_main_t *main); + extern f_status_t fss_embedded_list_write_main(fss_embedded_list_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_embedded_list_write_main_ /** @@ -208,7 +221,7 @@ extern "C" { * Be sure to call this after executing fss_embedded_list_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -218,7 +231,7 @@ extern "C" { * @see fss_embedded_list_write_main() */ #ifndef _di_fss_embedded_list_write_main_delete_ - extern f_status_t fss_embedded_list_write_main_delete(fss_embedded_list_write_main_t *main); + extern f_status_t fss_embedded_list_write_main_delete(fss_embedded_list_write_main_t * const main); #endif // _di_fss_embedded_list_write_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_write/c/main.c b/level_3/fss_embedded_list_write/c/main.c index 6f25d28..bba3014 100644 --- a/level_3/fss_embedded_list_write/c/main.c +++ b/level_3/fss_embedded_list_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_embedded_list_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_embedded_list_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_embedded_list_write/c/private-common.c b/level_3/fss_embedded_list_write/c/private-common.c index 16c4cbb..c90e4f9 100644 --- a/level_3/fss_embedded_list_write/c/private-common.c +++ b/level_3/fss_embedded_list_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_embedded_list_write_print_signal_received_ + void fss_embedded_list_write_print_signal_received(fss_embedded_list_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_embedded_list_write_print_signal_received_ + +#ifndef _di_fss_embedded_list_write_signal_received_ + f_status_t fss_embedded_list_write_signal_received(fss_embedded_list_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_embedded_list_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_embedded_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/private-common.h b/level_3/fss_embedded_list_write/c/private-common.h index 8029fb0..42f18a8 100644 --- a/level_3/fss_embedded_list_write/c/private-common.h +++ b/level_3/fss_embedded_list_write/c/private-common.h @@ -25,6 +25,36 @@ extern "C" { #define fss_embedded_list_write_common_allocation_small_d 16 #endif // _di_fss_embedded_list_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_embedded_list_write_print_signal_received_ + extern void fss_embedded_list_write_print_signal_received(fss_embedded_list_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_embedded_list_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_embedded_list_write_signal_received_ + extern f_status_t fss_embedded_list_write_signal_received(fss_embedded_list_write_main_t * const main); +#endif // _di_fss_embedded_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c index 66ee733..0e391a3 100644 --- a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c +++ b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c @@ -7,62 +7,62 @@ extern "C" { #endif #ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_ - void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_main_t main) { + void fss_embedded_list_write_error_parameter_same_times_print(fss_embedded_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sMust specify the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_object_s, main.error.notable); - fl_print_format("%[' parameter and the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, main.error.notable); - fl_print_format("%[' parameter the same number of times when not specifying the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_partial_s, main.error.notable); - fl_print_format("%[' parameter.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sMust specify the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_object_s, main->error.notable); + fl_print_format("%[' parameter and the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, main->error.notable); + fl_print_format("%[' parameter the same number of times when not specifying the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_partial_s, main->error.notable); + fl_print_format("%[' parameter.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_embedded_list_write_error_parameter_same_times_print_ #ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_ - void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_main_t main) { + void fss_embedded_list_write_error_parameter_unsupported_eol_print(fss_embedded_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThis standard does not support end of line character '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[\\n%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[' in objects.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThis standard does not support end of line character '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[\\n%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[' in objects.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_ #ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_ - void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) { + void fss_embedded_list_write_error_parameter_value_missing_print(fss_embedded_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, symbol, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, symbol, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_ #ifndef _di_fss_embedded_list_write_process_ - f_status_t fss_embedded_list_write_process(const fss_embedded_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) { + f_status_t fss_embedded_list_write_process(fss_embedded_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_state_t state = macro_f_state_t_initialize(fss_embedded_list_write_common_allocation_large_d, fss_embedded_list_write_common_allocation_small_d, 0, 0, 0, 0, 0); @@ -81,7 +81,7 @@ extern "C" { } if (content) { - if (main.parameters[fss_embedded_list_write_parameter_trim].result == f_console_result_found) { + if (main->parameters[fss_embedded_list_write_parameter_trim].result == f_console_result_found) { complete = f_fss_complete_full_trim; } else { @@ -98,7 +98,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_embedded_list_object_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_embedded_list_object_write_string", F_true); return status; } @@ -108,10 +108,10 @@ extern "C" { range.start = 0; range.stop = content->used - 1; - status = fl_fss_embedded_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main.prepend, ignore, state, &range, buffer); + status = fl_fss_embedded_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main->prepend, ignore, state, &range, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_embedded_list_content_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_embedded_list_content_write_string", F_true); return status; } @@ -121,7 +121,7 @@ extern "C" { status = f_string_append(f_string_eol_s, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -135,7 +135,7 @@ extern "C" { #endif // _di_fss_embedded_list_write_process_ #ifndef _di_fss_embedded_list_write_process_pipe_ - f_status_t fss_embedded_list_write_process_pipe(const fss_embedded_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) { + f_status_t fss_embedded_list_write_process_pipe(fss_embedded_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) { f_status_t status = F_none; f_status_t status_pipe = F_none; @@ -160,6 +160,14 @@ extern "C" { for (;;) { + if (fss_embedded_list_write_signal_received(main)) { + macro_f_string_dynamic_t_delete_simple(block); + macro_f_string_dynamic_t_delete_simple(object); + macro_f_string_dynamic_t_delete_simple(content); + + return F_status_set_error(F_interrupt); + } + if (range.start > range.stop) { if (status_pipe == F_none_eof) break; @@ -168,7 +176,7 @@ extern "C" { status_pipe = f_file_read_block(input, &block); if (F_status_is_error(status_pipe)) { - fll_error_print(main.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); + fll_error_print(main->error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); status_pipe = F_status_set_error(F_pipe); break; @@ -195,7 +203,7 @@ extern "C" { status = f_string_dynamic_increase_by(block.used, &object); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -244,7 +252,7 @@ extern "C" { status = f_string_dynamic_increase_by(total, &content); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -252,8 +260,8 @@ extern "C" { for (; range.start <= range.stop; ++range.start) { if (block.string[range.start] == fss_embedded_list_write_pipe_content_start_s) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context, f_string_eol_s[0]); } status = F_status_set_error(F_supported_not); @@ -276,7 +284,7 @@ extern "C" { if (ignore->used + 1 > ignore->size) { if (ignore->size + F_fss_default_allocation_step_d > F_array_length_t_size_d) { if (ignore->size + 1 > F_array_length_t_size_d) { - fll_error_print(main.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true); + fll_error_print(main->error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true); status = F_status_set_error(F_string_too_large); break; @@ -289,7 +297,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true); + fll_error_print(main->error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true); break; } } @@ -336,7 +344,7 @@ extern "C" { #endif // _di_fss_embedded_list_write_process_pipe_ #ifndef _di_fss_embedded_list_write_process_parameter_ignore_ - f_status_t fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_main_t main, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) { + f_status_t fss_embedded_list_write_process_parameter_ignore(fss_embedded_list_write_main_t * const main, const f_console_arguments_t *arguments, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) { f_status_t status = F_none; @@ -350,9 +358,13 @@ extern "C" { range.start = 0; - for (; i < main.parameters[fss_embedded_list_write_parameter_ignore].locations.used; ++i) { + for (; i < main->parameters[fss_embedded_list_write_parameter_ignore].locations.used; ++i) { + + if (fss_embedded_list_write_signal_received(main)) { + return F_status_set_error(F_interrupt); + } - l = main.parameters[fss_embedded_list_write_parameter_ignore].locations.array[i]; + l = main->parameters[fss_embedded_list_write_parameter_ignore].locations.array[i]; if (l < contents.array[location]) continue; if (location + 1 < contents.used && l > contents.array[location + 1]) continue; @@ -360,7 +372,7 @@ extern "C" { if (ignore->used + 1 > ignore->size) { if (ignore->size + F_fss_default_allocation_step_d > F_array_length_t_size_d) { if (ignore->size + 1 > F_array_length_t_size_d) { - fll_error_print(main.error, F_string_too_large, "fss_embedded_list_write_process_parameter_ignore", F_true); + fll_error_print(main->error, F_string_too_large, "fss_embedded_list_write_process_parameter_ignore", F_true); return F_status_set_error(F_string_too_large); } @@ -371,46 +383,46 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fss_embedded_list_write_process_parameter_ignore", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fss_embedded_list_write_process_parameter_ignore", F_true); return status; } } - index = main.parameters[fss_embedded_list_write_parameter_ignore].values.array[i * 2]; + index = main->parameters[fss_embedded_list_write_parameter_ignore].values.array[i * 2]; range.start = 0; - range.stop = strnlen(arguments.argv[index], f_console_parameter_size) - 1; + range.stop = strnlen(arguments->argv[index], f_console_parameter_size) - 1; // allow and ignore the positive sign. - if (range.stop > 0 && arguments.argv[index][0] == '+') { + if (range.stop > 0 && arguments->argv[index][0] == '+') { range.start = 1; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore_s, arguments->argv[index]); return status; } ignore->array[ignore->used].start = number; - index = main.parameters[fss_embedded_list_write_parameter_ignore].values.array[(i * 2) + 1]; + index = main->parameters[fss_embedded_list_write_parameter_ignore].values.array[(i * 2) + 1]; range.start = 0; - range.stop = strnlen(arguments.argv[index], f_console_parameter_size) - 1; + range.stop = strnlen(arguments->argv[index], f_console_parameter_size) - 1; // allow and ignore the positive sign. - if (range.stop > 0 && arguments.argv[index][0] == '+') { + if (range.stop > 0 && arguments->argv[index][0] == '+') { range.start = 1; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore_s, arguments->argv[index]); return status; } diff --git a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h index f6ce36a..376c9cd 100644 --- a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h +++ b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h @@ -16,41 +16,41 @@ extern "C" { * Print an message about the object and content parameters not being specified the same number of times. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_ - void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_embedded_list_write_error_parameter_same_times_print(fss_embedded_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_error_parameter_same_times_print_ /** * Print an message about a parameter EOL being unsupported. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_ - void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_embedded_list_write_error_parameter_unsupported_eol_print(fss_embedded_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_ /** * Print an message about a parameter missing a value. * * @param main - * The main data. + * The main program data. * @param symbol * The console symbol, such as "--" in "--help". * @param parameter * The parameter name, such as "help" in "--help". */ #ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_ - void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; + void fss_embedded_list_write_error_parameter_value_missing_print(fss_embedded_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_ /** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -73,14 +73,14 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_embedded_list_write_process_ - extern f_status_t fss_embedded_list_write_process(const fss_embedded_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_write_process(fss_embedded_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_process_ /** * Process the pipe, reading from the pipe and writing to the output. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -97,16 +97,16 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_embedded_list_write_process_pipe_ - extern f_status_t fss_embedded_list_write_process_pipe(const fss_embedded_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_write_process_pipe(fss_embedded_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_process_pipe_ /** * Process the ignore parameter associated with a specific content parameter. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param contents * The console parameter locations array for the content parameter. * @param location @@ -119,7 +119,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_embedded_list_write_process_parameter_ignore_ - extern f_status_t fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_main_t main, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; + extern f_status_t fss_embedded_list_write_process_parameter_ignore(fss_embedded_list_write_main_t * const main, const f_console_arguments_t *arguments, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_write_process_parameter_ignore_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_write/data/build/dependencies b/level_3/fss_embedded_list_write/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_embedded_list_write/data/build/dependencies +++ b/level_3/fss_embedded_list_write/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.c b/level_3/fss_extended_list_read/c/fss_extended_list_read.c index 37d5b50..f1ba259 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.c +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.c @@ -117,7 +117,7 @@ extern "C" { #endif // _di_fss_extended_list_read_print_help_ #ifndef _di_fss_extended_list_read_main_ - f_status_t fss_extended_list_read_main(f_console_arguments_t * const arguments, fss_extended_list_read_main_t *main) { + f_status_t fss_extended_list_read_main(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -348,6 +348,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_extended_list_read_parameter_delimit].values.used; ++i) { + if (fss_extended_list_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + location = main->parameters[fss_extended_list_read_parameter_delimit].values.array[i]; length = strnlen(arguments->argv[location], f_console_parameter_size); @@ -469,7 +474,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_extended_list_read_depth_process(arguments, main, &data); + status = fss_extended_list_read_depth_process(main, arguments, &data); } // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. @@ -540,6 +545,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + if (fss_extended_list_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + data.files.array[data.files.used].range.start = data.buffer.used; file.stream = 0; file.id = -1; @@ -601,7 +611,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_extended_list_read_process(arguments, main, &data); + status = fss_extended_list_read_process(main, arguments, &data); } fss_extended_list_read_data_delete_simple(&data); @@ -611,6 +621,14 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_extended_list_read_data_delete_simple(&data); fss_extended_list_read_main_delete(main); diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.h b/level_3/fss_extended_list_read/c/fss_extended_list_read.h index c447478..5149224 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.h +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -213,6 +214,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_extended_list_read_main_t; @@ -224,6 +227,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_extended_list_read_main_t_ @@ -248,10 +252,18 @@ extern "C" { * * Be sure to call fss_extended_list_read_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -261,7 +273,7 @@ extern "C" { * @see fss_extended_list_read_main_delete() */ #ifndef _di_fss_extended_list_read_main_ - extern f_status_t fss_extended_list_read_main(f_console_arguments_t * const arguments, fss_extended_list_read_main_t *main); + extern f_status_t fss_extended_list_read_main(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_extended_list_read_main_ /** @@ -270,7 +282,7 @@ extern "C" { * Be sure to call this after executing fss_extended_list_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. diff --git a/level_3/fss_extended_list_read/c/main.c b/level_3/fss_extended_list_read/c/main.c index 77ef160..9abf610 100644 --- a/level_3/fss_extended_list_read/c/main.c +++ b/level_3/fss_extended_list_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_extended_list_read_main(&arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_extended_list_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_extended_list_read/c/private-common.c b/level_3/fss_extended_list_read/c/private-common.c index 2261f10..97e73b0 100644 --- a/level_3/fss_extended_list_read/c/private-common.c +++ b/level_3/fss_extended_list_read/c/private-common.c @@ -57,6 +57,53 @@ extern "C" { } #endif // _di_fss_extended_list_read_depths_resize_ +#ifndef _di_fss_extended_list_read_print_signal_received_ + void fss_extended_list_read_print_signal_received(fss_extended_list_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_extended_list_read_print_signal_received_ + +#ifndef _di_fss_extended_list_read_signal_received_ + f_status_t fss_extended_list_read_signal_received(fss_extended_list_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_extended_list_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_extended_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/private-common.h b/level_3/fss_extended_list_read/c/private-common.h index 96a81ce..700187f 100644 --- a/level_3/fss_extended_list_read/c/private-common.h +++ b/level_3/fss_extended_list_read/c/private-common.h @@ -249,6 +249,36 @@ extern "C" { extern f_status_t fss_extended_list_read_depths_resize(const f_array_length_t length, fss_extended_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_depths_resize_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_extended_list_read_print_signal_received_ + extern void fss_extended_list_read_print_signal_received(fss_extended_list_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_list_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_extended_list_read_signal_received_ + extern f_status_t fss_extended_list_read_signal_received(fss_extended_list_read_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_list_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c index 74702fe..8aef13b 100644 --- a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c +++ b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c @@ -55,7 +55,7 @@ extern "C" { #endif // _di_fss_extended_list_read_delimit_object_is_ #ifndef _di_fss_extended_list_read_depth_process_ - f_status_t fss_extended_list_read_depth_process(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) { + f_status_t fss_extended_list_read_depth_process(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) { f_status_t status = F_none; @@ -85,6 +85,10 @@ extern "C" { for (f_array_length_t i = 0; i < data->depths.used; ++i) { + if (fss_extended_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + data->depths.array[i].depth = 0; data->depths.array[i].index_at = 0; data->depths.array[i].index_name = 0; @@ -167,6 +171,10 @@ extern "C" { for (f_array_length_t j = i + 1; j < data->depths.used; ++j) { + if (fss_extended_list_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->depths.array[i].depth == data->depths.array[j].depth) { if (main->error.verbosity != f_console_verbosity_quiet) { flockfile(main->error.to.stream); @@ -253,7 +261,7 @@ extern "C" { #endif // _di_fss_extended_list_read_load_ #ifndef _di_fss_extended_list_read_load_number_ - f_status_t fss_extended_list_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, f_number_unsigned_t *number) { + f_status_t fss_extended_list_read_load_number(fss_extended_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) { if (main->parameters[parameter].result == f_console_result_additional) { const f_array_length_t index = main->parameters[parameter].values.array[main->parameters[parameter].values.used - 1]; @@ -275,7 +283,7 @@ extern "C" { #endif // _di_fss_extended_list_read_load_number_ #ifndef _di_fss_extended_list_read_print_at_ - void fss_extended_list_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t * const data) { + void fss_extended_list_read_print_at(fss_extended_list_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_list_read_data_t * const data) { if (at >= data->contents.used) { return; @@ -391,9 +399,9 @@ extern "C" { #endif // _di_fss_extended_list_read_print_zero_ #ifndef _di_fss_extended_list_read_process_ - f_status_t fss_extended_list_read_process(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) { + f_status_t fss_extended_list_read_process(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) { - f_status_t status = fss_extended_list_read_process_option(arguments, main, data); + f_status_t status = fss_extended_list_read_process_option(main, arguments, data); if (F_status_is_error(status)) return status; // This standard does not support multiple content groups. @@ -442,7 +450,7 @@ extern "C" { if (!names[i]) continue; - fss_extended_list_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_list_read_print_at(main, i, *delimits_object, *delimits_content, data); } // for return F_none; @@ -484,7 +492,7 @@ extern "C" { if (data->option & fss_extended_list_read_data_option_line) { f_array_length_t line = 0; - status = fss_extended_list_read_process_at_line(i, *delimits_object, *delimits_content, main, data, &line); + status = fss_extended_list_read_process_at_line(main, i, *delimits_object, *delimits_content, data, &line); if (status == F_success) return F_none; } else if (data->option & fss_extended_list_read_data_option_columns) { @@ -547,7 +555,7 @@ extern "C" { } } else { - fss_extended_list_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_list_read_print_at(main, i, *delimits_object, *delimits_content, data); } return F_none; @@ -599,7 +607,7 @@ extern "C" { #endif // _di_fss_extended_list_read_process_columns_ #ifndef _di_fss_extended_list_read_process_at_line_ - f_status_t fss_extended_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data, f_array_length_t *line) { + f_status_t fss_extended_list_read_process_at_line(fss_extended_list_read_main_t * const main, const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_extended_list_read_data_t *data, f_array_length_t *line) { if (data->option & fss_extended_list_read_data_option_object) { @@ -713,7 +721,7 @@ extern "C" { if (!names[i]) continue; - status = fss_extended_list_read_process_at_line(i, *delimits_object, *delimits_content, main, data, &line); + status = fss_extended_list_read_process_at_line(main, i, *delimits_object, *delimits_content, data, &line); if (status == F_success) break; } // for @@ -748,7 +756,7 @@ extern "C" { #endif // _di_fss_extended_list_read_process_name_ #ifndef _di_fss_extended_list_read_process_option_ - f_status_t fss_extended_list_read_process_option(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) { + f_status_t fss_extended_list_read_process_option(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) { f_status_t status = F_none; @@ -771,7 +779,7 @@ extern "C" { if (main->parameters[fss_extended_list_read_parameter_line].result == f_console_result_additional) { data->option |= fss_extended_list_read_data_option_line; - status = fss_extended_list_read_load_number(fss_extended_list_read_parameter_line, fss_extended_list_read_long_line_s, arguments, main, &data->line); + status = fss_extended_list_read_load_number(main, fss_extended_list_read_parameter_line, fss_extended_list_read_long_line_s, arguments, &data->line); if (F_status_is_error(status)) return status; } @@ -790,7 +798,7 @@ extern "C" { if (main->parameters[fss_extended_list_read_parameter_select].result == f_console_result_additional) { data->option |= fss_extended_list_read_data_option_select; - status = fss_extended_list_read_load_number(fss_extended_list_read_parameter_select, fss_extended_list_read_long_select_s, arguments, main, &data->select); + status = fss_extended_list_read_load_number(main, fss_extended_list_read_parameter_select, fss_extended_list_read_long_select_s, arguments, &data->select); if (F_status_is_error(status)) return status; } diff --git a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h index b08ed21..d41f5e2 100644 --- a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h +++ b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h @@ -49,10 +49,10 @@ extern "C" { * * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed). * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -72,7 +72,7 @@ extern "C" { * @see fss_extended_list_read_depths_resize() */ #ifndef _di_fss_extended_list_read_depth_process_ - extern f_status_t fss_extended_list_read_depth_process(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_read_depth_process(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_depth_process_ /** @@ -99,7 +99,7 @@ extern "C" { * This will print an error message on error. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @@ -124,14 +124,14 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param parameter * An ID representing the parameter. * @param name * The parameter name to print on error. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param number * The location to store the loaded number. * @@ -146,7 +146,7 @@ extern "C" { * @see fss_extended_list_read_depths_resize() */ #ifndef _di_fss_extended_list_read_load_number_ - extern f_status_t fss_extended_list_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_read_load_number(fss_extended_list_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_load_number_ /** @@ -154,26 +154,26 @@ extern "C" { * * Only what is requested to print (Object, Content, both, or neither) will be printed, if there is something to print. * + * @param main + * The main program data. * @param at * The index in the Objects and Contents to print. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content * The delimits to be applied to Content. - * @param main - * The main data. * @param data * The program data. */ #ifndef _di_fss_extended_list_read_print_at_ - extern void fss_extended_list_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t * const data) F_attribute_visibility_internal_d; + extern void fss_extended_list_read_print_at(fss_extended_list_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_list_read_data_t * const data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_print_at_ /** * Explicitly print the Object at the given position. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param at @@ -191,7 +191,7 @@ extern "C" { * This is only used in pipe output mode. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_list_read_print_content_ignore_ extern void fss_extended_list_read_print_content_ignore(fss_extended_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -201,7 +201,7 @@ extern "C" { * Print the end of an Object (which is essentially the start of Content). * * @param main - * The main data. + * The main program data. * @param data * The program data. */ @@ -213,7 +213,7 @@ extern "C" { * Print the number one and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_list_read_print_one_ extern void fss_extended_list_read_print_one(fss_extended_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -223,7 +223,7 @@ extern "C" { * Print the end of an Object/Content set. * * @param main - * The main data. + * The main program data. * @param data * The program data. */ @@ -235,7 +235,7 @@ extern "C" { * Print the number zero and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_list_read_print_zero_ extern void fss_extended_list_read_print_zero(fss_extended_list_read_main_t * const main) F_attribute_visibility_internal_d; @@ -246,10 +246,10 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -263,14 +263,14 @@ extern "C" { * @see fss_extended_list_read_process_option() */ #ifndef _di_fss_extended_list_read_process_ - extern f_status_t fss_extended_list_read_process(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_read_process(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_process_ /** * Process based on at parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -290,7 +290,7 @@ extern "C" { * Process based on columns parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -308,7 +308,7 @@ extern "C" { * Process based on at parameter for some line. * * @param main - * The main data. + * The main program data. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content @@ -324,14 +324,14 @@ extern "C" { * F_success on success and the line was matched (and possibly printed). */ #ifndef _di_fss_extended_list_read_process_at_line_ - extern f_status_t fss_extended_list_read_process_at_line(const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data, f_array_length_t *line) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_read_process_at_line(fss_extended_list_read_main_t * const main, const f_array_length_t at, const f_array_lengths_t delimits_object, const f_array_lengths_t delimits_content, fss_extended_list_read_data_t *data, f_array_length_t *line) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_process_at_line_ /** * Process based on line parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -369,7 +369,7 @@ extern "C" { * @param arguments * The parameters passed to the process. * @param main - * The main data. + * The main program data. * @param data * The program data. * @@ -383,14 +383,14 @@ extern "C" { * @see fss_extended_list_read_load_setting() */ #ifndef _di_fss_extended_list_read_process_option_ - extern f_status_t fss_extended_list_read_process_option(f_console_arguments_t * const arguments, fss_extended_list_read_main_t * const main, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_read_process_option(fss_extended_list_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_list_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_process_option_ /** * Process based on total parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names diff --git a/level_3/fss_extended_list_read/data/build/dependencies b/level_3/fss_extended_list_read/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_extended_list_read/data/build/dependencies +++ b/level_3/fss_extended_list_read/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_extended_list_write/c/fss_extended_list_write.c b/level_3/fss_extended_list_write/c/fss_extended_list_write.c index fc99a8b..33e019a 100644 --- a/level_3/fss_extended_list_write/c/fss_extended_list_write.c +++ b/level_3/fss_extended_list_write/c/fss_extended_list_write.c @@ -60,7 +60,8 @@ extern "C" { #endif // _di_fss_extended_list_write_print_help_ #ifndef _di_fss_extended_list_write_main_ - f_status_t fss_extended_list_write_main(const f_console_arguments_t arguments, fss_extended_list_write_main_t *main) { + f_status_t fss_extended_list_write_main(fss_extended_list_write_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -70,7 +71,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_extended_list_write_parameter_no_color, fss_extended_list_write_parameter_light, fss_extended_list_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -176,15 +177,15 @@ extern "C" { output.id = -1; output.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &output); + status = f_file_stream_open(arguments->argv[location], 0, &output); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } else if (main->parameters[fss_extended_list_write_parameter_file].result == f_console_result_found) { - fss_extended_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_list_write_long_file_s); + fss_extended_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_list_write_long_file_s); status = F_status_set_error(F_parameter); } } @@ -193,15 +194,15 @@ extern "C" { if (main->parameters[fss_extended_list_write_parameter_object].locations.used || main->parameters[fss_extended_list_write_parameter_content].locations.used) { if (main->parameters[fss_extended_list_write_parameter_object].locations.used) { if (main->parameters[fss_extended_list_write_parameter_object].locations.used != main->parameters[fss_extended_list_write_parameter_object].values.used) { - fss_extended_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_list_write_long_object_s); + fss_extended_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_list_write_long_object_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_extended_list_write_parameter_content].locations.used != main->parameters[fss_extended_list_write_parameter_content].values.used) { - fss_extended_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s); + fss_extended_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_extended_list_write_parameter_object].locations.used != main->parameters[fss_extended_list_write_parameter_content].locations.used && main->parameters[fss_extended_list_write_parameter_partial].result == f_console_result_none) { - fss_extended_list_write_error_parameter_same_times_print(*main); + fss_extended_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_extended_list_write_parameter_content].locations.used && main->parameters[fss_extended_list_write_parameter_partial].locations.used) { @@ -259,11 +260,11 @@ extern "C" { } else if (main->parameters[fss_extended_list_write_parameter_content].locations.used) { if (main->parameters[fss_extended_list_write_parameter_content].locations.used != main->parameters[fss_extended_list_write_parameter_content].values.used) { - fss_extended_list_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s); + fss_extended_list_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_extended_list_write_parameter_partial].locations.used) { - fss_extended_list_write_error_parameter_same_times_print(*main); + fss_extended_list_write_error_parameter_same_times_print(main); status = F_status_set_error(F_parameter); } } @@ -317,12 +318,12 @@ extern "C" { } else if (main->parameters[fss_extended_list_write_parameter_prepend].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_extended_list_write_parameter_prepend].values.array[main->parameters[fss_extended_list_write_parameter_prepend].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); if (length) { f_string_range_t range = macro_f_string_range_t_initialize(length); - main->prepend.string = arguments.argv[index]; + main->prepend.string = arguments->argv[index]; main->prepend.used = length; main->prepend.size = length; @@ -419,7 +420,7 @@ extern "C" { f_string_ranges_t ignore = f_string_ranges_t_initialize; if (main->process_pipe) { - status = fss_extended_list_write_process_pipe(*main, output, quote, &buffer, &ignore); + status = fss_extended_list_write_process_pipe(main, output, quote, &buffer, &ignore); if (F_status_is_error(status)) { if (main->error.verbosity != f_console_verbosity_quiet) { @@ -441,25 +442,35 @@ extern "C" { if (main->parameters[fss_extended_list_write_parameter_object].result == f_console_result_additional) { for (f_array_length_t i = 0; i < main->parameters[fss_extended_list_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_extended_list_write_parameter_object].values.array[i]]; + if (fss_extended_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_extended_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - status = fss_extended_list_write_process(*main, output, quote, &object, 0, 0, &buffer); + status = fss_extended_list_write_process(main, output, quote, &object, 0, 0, &buffer); if (F_status_is_error(status)) break; } // for } else { for (f_array_length_t i = 0; i < main->parameters[fss_extended_list_write_parameter_content].values.used; ++i) { - status = fss_extended_list_write_process_parameter_ignore(arguments, *main, main->parameters[fss_extended_list_write_parameter_content].locations, i, &ignore); + if (fss_extended_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status = fss_extended_list_write_process_parameter_ignore(main, arguments, main->parameters[fss_extended_list_write_parameter_content].locations, i, &ignore); if (F_status_is_error(status)) break; - content.string = arguments.argv[main->parameters[fss_extended_list_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_extended_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_extended_list_write_process(*main, output, quote, 0, &content, &ignore, &buffer); + status = fss_extended_list_write_process(main, output, quote, 0, &content, &ignore, &buffer); if (F_status_is_error(status)) break; } // for } @@ -467,18 +478,23 @@ extern "C" { else { for (f_array_length_t i = 0; i < main->parameters[fss_extended_list_write_parameter_object].values.used; ++i) { - status = fss_extended_list_write_process_parameter_ignore(arguments, *main, main->parameters[fss_extended_list_write_parameter_content].locations, i, &ignore); + if (fss_extended_list_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status = fss_extended_list_write_process_parameter_ignore(main, arguments, main->parameters[fss_extended_list_write_parameter_content].locations, i, &ignore); if (F_status_is_error(status)) break; - object.string = arguments.argv[main->parameters[fss_extended_list_write_parameter_object].values.array[i]]; + object.string = arguments->argv[main->parameters[fss_extended_list_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - content.string = arguments.argv[main->parameters[fss_extended_list_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[fss_extended_list_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = fss_extended_list_write_process(*main, output, quote, &object, &content, &ignore, &buffer); + status = fss_extended_list_write_process(main, output, quote, &object, &content, &ignore, &buffer); if (F_status_is_error(status)) break; } // for } @@ -530,6 +546,7 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamic_t_delete_simple(content); fss_extended_list_write_main_delete(main); + return status; } #endif // _di_fss_extended_list_write_main_ diff --git a/level_3/fss_extended_list_write/c/fss_extended_list_write.h b/level_3/fss_extended_list_write/c/fss_extended_list_write.h index d19e628..fbae630 100644 --- a/level_3/fss_extended_list_write/c/fss_extended_list_write.h +++ b/level_3/fss_extended_list_write/c/fss_extended_list_write.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -149,6 +150,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_string_static_t prepend; f_color_context_t context; @@ -162,6 +165,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_static_t_initialize, \ f_color_context_t_initialize, \ } @@ -187,10 +191,18 @@ extern "C" { * * Be sure to call fss_extended_list_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -200,7 +212,7 @@ extern "C" { * @see fss_extended_list_write_main_delete() */ #ifndef _di_fss_extended_list_write_main_ - extern f_status_t fss_extended_list_write_main(const f_console_arguments_t arguments, fss_extended_list_write_main_t *main); + extern f_status_t fss_extended_list_write_main(fss_extended_list_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_extended_list_write_main_ /** @@ -209,7 +221,7 @@ extern "C" { * Be sure to call this after executing fss_extended_list_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. diff --git a/level_3/fss_extended_list_write/c/main.c b/level_3/fss_extended_list_write/c/main.c index 8390830..17615f5 100644 --- a/level_3/fss_extended_list_write/c/main.c +++ b/level_3/fss_extended_list_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_extended_list_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_extended_list_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_extended_list_write/c/private-common.c b/level_3/fss_extended_list_write/c/private-common.c index 4e3d529..af21cd3 100644 --- a/level_3/fss_extended_list_write/c/private-common.c +++ b/level_3/fss_extended_list_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_extended_list_write_print_signal_received_ + void fss_extended_list_write_print_signal_received(fss_extended_list_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_extended_list_write_print_signal_received_ + +#ifndef _di_fss_extended_list_write_signal_received_ + f_status_t fss_extended_list_write_signal_received(fss_extended_list_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_extended_list_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_extended_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/private-common.h b/level_3/fss_extended_list_write/c/private-common.h index 106e55b..1d00bb2 100644 --- a/level_3/fss_extended_list_write/c/private-common.h +++ b/level_3/fss_extended_list_write/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define fss_extended_list_write_common_allocation_small_d 16 #endif // _di_fss_extended_list_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_extended_list_write_print_signal_received_ + extern void fss_extended_list_write_print_signal_received(fss_extended_list_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_list_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_extended_list_write_signal_received_ + extern f_status_t fss_extended_list_write_signal_received(fss_extended_list_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_list_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/private-fss_extended_list_write.c b/level_3/fss_extended_list_write/c/private-fss_extended_list_write.c index 6abcf6c..dc91946 100644 --- a/level_3/fss_extended_list_write/c/private-fss_extended_list_write.c +++ b/level_3/fss_extended_list_write/c/private-fss_extended_list_write.c @@ -7,62 +7,62 @@ extern "C" { #endif #ifndef _di_fss_extended_list_write_error_parameter_same_times_print_ - void fss_extended_list_write_error_parameter_same_times_print(const fss_extended_list_write_main_t main) { + void fss_extended_list_write_error_parameter_same_times_print(fss_extended_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sMust specify the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_object_s, main.error.notable); - fl_print_format("%[' parameter and the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, main.error.notable); - fl_print_format("%[' parameter the same number of times when not specifying the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_partial_s, main.error.notable); - fl_print_format("%[' parameter.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sMust specify the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_object_s, main->error.notable); + fl_print_format("%[' parameter and the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, main->error.notable); + fl_print_format("%[' parameter the same number of times when not specifying the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_partial_s, main->error.notable); + fl_print_format("%[' parameter.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_list_write_error_parameter_same_times_print_ #ifndef _di_fss_extended_list_write_error_parameter_unsupported_eol_print_ - void fss_extended_list_write_error_parameter_unsupported_eol_print(const fss_extended_list_write_main_t main) { + void fss_extended_list_write_error_parameter_unsupported_eol_print(fss_extended_list_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThis standard does not support end of line character '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[\\n%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[' in objects.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThis standard does not support end of line character '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[\\n%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[' in objects.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_list_write_error_parameter_unsupported_eol_print_ #ifndef _di_fss_extended_list_write_error_parameter_value_missing_print_ - void fss_extended_list_write_error_parameter_value_missing_print(const fss_extended_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) { + void fss_extended_list_write_error_parameter_value_missing_print(fss_extended_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, symbol, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, symbol, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_list_write_error_parameter_value_missing_print_ #ifndef _di_fss_extended_list_write_process_ - f_status_t fss_extended_list_write_process(const fss_extended_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) { + f_status_t fss_extended_list_write_process(fss_extended_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_state_t state = macro_f_state_t_initialize(fss_extended_list_write_common_allocation_large_d, fss_extended_list_write_common_allocation_small_d, 0, 0, 0, 0, 0); @@ -81,7 +81,7 @@ extern "C" { } if (content) { - if (main.parameters[fss_extended_list_write_parameter_trim].result == f_console_result_found) { + if (main->parameters[fss_extended_list_write_parameter_trim].result == f_console_result_found) { complete = f_fss_complete_full_trim; } else { @@ -98,7 +98,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_extended_list_object_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_extended_list_object_write_string", F_true); return status; } @@ -108,10 +108,10 @@ extern "C" { range.start = 0; range.stop = content->used - 1; - status = fl_fss_extended_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main.prepend, ignore, state, &range, buffer); + status = fl_fss_extended_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &main->prepend, ignore, state, &range, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_extended_list_content_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_extended_list_content_write_string", F_true); return status; } @@ -121,7 +121,7 @@ extern "C" { status = f_string_append(f_string_eol_s, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -135,7 +135,7 @@ extern "C" { #endif // _di_fss_extended_list_write_process_ #ifndef _di_fss_extended_list_write_process_pipe_ - f_status_t fss_extended_list_write_process_pipe(const fss_extended_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) { + f_status_t fss_extended_list_write_process_pipe(fss_extended_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) { f_status_t status = F_none; f_status_t status_pipe = F_none; @@ -160,6 +160,10 @@ extern "C" { for (;;) { + if (fss_extended_list_write_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (range.start > range.stop) { if (status_pipe == F_none_eof) break; @@ -168,7 +172,7 @@ extern "C" { status_pipe = f_file_read_block(input, &block); if (F_status_is_error(status_pipe)) { - fll_error_print(main.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); + fll_error_print(main->error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); status_pipe = F_status_set_error(F_pipe); break; @@ -195,7 +199,7 @@ extern "C" { status = f_string_dynamic_increase_by(block.used, &object); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -244,7 +248,7 @@ extern "C" { status = f_string_dynamic_increase_by(total, &content); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -252,8 +256,8 @@ extern "C" { for (; range.start <= range.stop; ++range.start) { if (block.string[range.start] == fss_extended_list_write_pipe_content_start_s) { - if (main.error.verbosity != f_console_verbosity_quiet) { - fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context, f_string_eol_s[0]); + if (main->error.verbosity != f_console_verbosity_quiet) { + fll_print_format("%c%[%sThis standard only supports one content per object.%]%c", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context, f_string_eol_s[0]); } status = F_status_set_error(F_supported_not); @@ -276,7 +280,7 @@ extern "C" { if (ignore->used + 1 > ignore->size) { if (ignore->size + F_fss_default_allocation_step_d > F_array_length_t_size_d) { if (ignore->size + 1 > F_array_length_t_size_d) { - fll_error_print(main.error, F_string_too_large, "fss_extended_list_write_process_pipe", F_true); + fll_error_print(main->error, F_string_too_large, "fss_extended_list_write_process_pipe", F_true); status = F_status_set_error(F_string_too_large); break; @@ -289,7 +293,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_string_too_large, "fss_extended_list_write_process_pipe", F_true); + fll_error_print(main->error, F_string_too_large, "fss_extended_list_write_process_pipe", F_true); break; } } @@ -336,7 +340,7 @@ extern "C" { #endif // _di_fss_extended_list_write_process_pipe_ #ifndef _di_fss_extended_list_write_process_parameter_ignore_ - f_status_t fss_extended_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_extended_list_write_main_t main, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) { + f_status_t fss_extended_list_write_process_parameter_ignore(fss_extended_list_write_main_t * const main, const f_console_arguments_t *arguments, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) { f_status_t status = F_none; @@ -350,9 +354,13 @@ extern "C" { range.start = 0; - for (; i < main.parameters[fss_extended_list_write_parameter_ignore].locations.used; ++i) { + for (; i < main->parameters[fss_extended_list_write_parameter_ignore].locations.used; ++i) { - l = main.parameters[fss_extended_list_write_parameter_ignore].locations.array[i]; + if (fss_extended_list_write_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + + l = main->parameters[fss_extended_list_write_parameter_ignore].locations.array[i]; if (l < contents.array[location]) continue; if (location + 1 < contents.used && l > contents.array[location + 1]) continue; @@ -360,7 +368,7 @@ extern "C" { if (ignore->used + 1 > ignore->size) { if (ignore->size + F_fss_default_allocation_step_d > F_array_length_t_size_d) { if (ignore->size + 1 > F_array_length_t_size_d) { - fll_error_print(main.error, F_string_too_large, "fss_extended_list_write_process_parameter_ignore", F_true); + fll_error_print(main->error, F_string_too_large, "fss_extended_list_write_process_parameter_ignore", F_true); return F_status_set_error(F_string_too_large); } @@ -372,45 +380,46 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fss_extended_list_write_process_parameter_ignore", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fss_extended_list_write_process_parameter_ignore", F_true); return status; } } - index = main.parameters[fss_extended_list_write_parameter_ignore].values.array[i * 2]; + index = main->parameters[fss_extended_list_write_parameter_ignore].values.array[i * 2]; range.start = 0; - range.stop = strnlen(arguments.argv[index], f_console_parameter_size) - 1; + range.stop = strnlen(arguments->argv[index], f_console_parameter_size) - 1; // allow and ignore the positive sign. - if (range.stop > 0 && arguments.argv[index][0] == '+') { + if (range.stop > 0 && arguments->argv[index][0] == '+') { range.start = 1; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_extended_list_write_long_ignore_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_extended_list_write_long_ignore_s, arguments->argv[index]); + return status; } ignore->array[ignore->used].start = number; - index = main.parameters[fss_extended_list_write_parameter_ignore].values.array[(i * 2) + 1]; + index = main->parameters[fss_extended_list_write_parameter_ignore].values.array[(i * 2) + 1]; range.start = 0; - range.stop = strnlen(arguments.argv[index], f_console_parameter_size) - 1; + range.stop = strnlen(arguments->argv[index], f_console_parameter_size) - 1; // allow and ignore the positive sign. - if (range.stop > 0 && arguments.argv[index][0] == '+') { + if (range.stop > 0 && arguments->argv[index][0] == '+') { range.start = 1; } - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_extended_list_write_long_ignore_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_extended_list_write_long_ignore_s, arguments->argv[index]); return status; } diff --git a/level_3/fss_extended_list_write/c/private-fss_extended_list_write.h b/level_3/fss_extended_list_write/c/private-fss_extended_list_write.h index 9016cea..1b1377f 100644 --- a/level_3/fss_extended_list_write/c/private-fss_extended_list_write.h +++ b/level_3/fss_extended_list_write/c/private-fss_extended_list_write.h @@ -16,41 +16,41 @@ extern "C" { * Print an message about the object and content parameters not being specified the same number of times. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_list_write_error_parameter_same_times_print_ - void fss_extended_list_write_error_parameter_same_times_print(const fss_extended_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_extended_list_write_error_parameter_same_times_print(fss_extended_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_error_parameter_same_times_print_ /** * Print an message about a parameter EOL being unsupported. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_list_write_error_parameter_unsupported_eol_print_ - void fss_extended_list_write_error_parameter_unsupported_eol_print(const fss_extended_list_write_main_t main) F_attribute_visibility_internal_d; + void fss_extended_list_write_error_parameter_unsupported_eol_print(fss_extended_list_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_error_parameter_unsupported_eol_print_ /** * Print an message about a parameter missing a value. * * @param main - * The main data. + * The main program data. * @param symbol * The console symbol, such as "--" in "--help". * @param parameter * The parameter name, such as "help" in "--help". */ #ifndef _di_fss_extended_list_write_error_parameter_value_missing_print_ - void fss_extended_list_write_error_parameter_value_missing_print(const fss_extended_list_write_main_t main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; + void fss_extended_list_write_error_parameter_value_missing_print(fss_extended_list_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_error_parameter_value_missing_print_ /** * Process a given object and content, printing the FSS if valid or an error if invalid. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -73,14 +73,14 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_list_write_process_ - extern f_status_t fss_extended_list_write_process(const fss_extended_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_write_process(fss_extended_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_process_ /** * Process the pipe, reading from the pipe and writing to the output. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param quote @@ -97,16 +97,16 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_list_write_process_pipe_ - extern f_status_t fss_extended_list_write_process_pipe(const fss_extended_list_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_write_process_pipe(fss_extended_list_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_process_pipe_ /** * Process the ignore parameter associated with a specific content parameter. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param contents * The console parameter locations array for the content parameter. * @param location @@ -119,7 +119,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_list_write_process_parameter_ignore_ - extern f_status_t fss_extended_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_extended_list_write_main_t main, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_list_write_process_parameter_ignore(fss_extended_list_write_main_t * const main, const f_console_arguments_t *arguments, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_write_process_parameter_ignore_ #ifdef __cplusplus diff --git a/level_3/fss_extended_list_write/data/build/dependencies b/level_3/fss_extended_list_write/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_extended_list_write/data/build/dependencies +++ b/level_3/fss_extended_list_write/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_extended_read/c/fss_extended_read.c b/level_3/fss_extended_read/c/fss_extended_read.c index e50f08f..ee14011 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.c +++ b/level_3/fss_extended_read/c/fss_extended_read.c @@ -117,7 +117,8 @@ extern "C" { #endif // _di_fss_extended_read_print_help_ #ifndef _di_fss_extended_read_main_ - f_status_t fss_extended_read_main(f_console_arguments_t * const arguments, fss_extended_read_main_t *main) { + f_status_t fss_extended_read_main(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -199,6 +200,7 @@ extern "C" { fss_extended_read_print_help(main->output.to, main->context); fss_extended_read_main_delete(main); + return status; } @@ -206,6 +208,7 @@ extern "C" { fll_program_print_version(main->output.to, fss_extended_read_program_version_s); fss_extended_read_main_delete(main); + return status; } @@ -349,6 +352,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_extended_read_parameter_delimit].values.used; ++i) { + if (fss_extended_read_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + location = main->parameters[fss_extended_read_parameter_delimit].values.array[i]; length = strnlen(arguments->argv[location], f_console_parameter_size); @@ -469,7 +477,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_extended_read_depth_process(arguments, main, &data); + status = fss_extended_read_depth_process(main, arguments, &data); } // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. @@ -540,6 +548,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + if (fss_extended_read_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + data.files.array[data.files.used].range.start = data.buffer.used; file.stream = 0; file.id = -1; @@ -601,7 +614,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fss_extended_read_process(arguments, main, &data); + status = fss_extended_read_process(main, arguments, &data); } fss_extended_read_data_delete_simple(&data); @@ -611,6 +624,14 @@ extern "C" { status = F_status_set_error(F_parameter); } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_extended_read_data_delete_simple(&data); fss_extended_read_main_delete(main); @@ -619,7 +640,7 @@ extern "C" { #endif // _di_fss_extended_read_main_ #ifndef _di_fss_extended_read_main_delete_ - f_status_t fss_extended_read_main_delete(fss_extended_read_main_t *main) { + f_status_t fss_extended_read_main_delete(fss_extended_read_main_t * const main) { for (f_array_length_t i = 0; i < fss_extended_read_total_parameters_d; ++i) { diff --git a/level_3/fss_extended_read/c/fss_extended_read.h b/level_3/fss_extended_read/c/fss_extended_read.h index 533f633..5694e73 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.h +++ b/level_3/fss_extended_read/c/fss_extended_read.h @@ -32,6 +32,7 @@ #include #include #include +#include // fll-1 includes #include @@ -214,6 +215,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_extended_read_main_t; @@ -225,6 +228,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_extended_read_main_t_ @@ -249,10 +253,18 @@ extern "C" { * * Be sure to call fss_extended_read_main_delete() after executing this. * + * 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 arguments * The parameters passed to the process. * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -262,7 +274,7 @@ extern "C" { * @see fss_extended_read_main_delete() */ #ifndef _di_fss_extended_read_main_ - extern f_status_t fss_extended_read_main(f_console_arguments_t * const arguments, fss_extended_read_main_t *main); + extern f_status_t fss_extended_read_main(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_extended_read_main_ /** @@ -271,7 +283,7 @@ extern "C" { * Be sure to call this after executing fss_extended_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -281,7 +293,7 @@ extern "C" { * @see fss_extended_read_main() */ #ifndef _di_fss_extended_read_main_delete_ - extern f_status_t fss_extended_read_main_delete(fss_extended_read_main_t *main); + extern f_status_t fss_extended_read_main_delete(fss_extended_read_main_t * const main); #endif // _di_fss_extended_read_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_extended_read/c/main.c b/level_3/fss_extended_read/c/main.c index bc4ccec..1c1ce44 100644 --- a/level_3/fss_extended_read/c/main.c +++ b/level_3/fss_extended_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_extended_read_main(&arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_extended_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_extended_read/c/private-common.c b/level_3/fss_extended_read/c/private-common.c index f72a6ca..65b7482 100644 --- a/level_3/fss_extended_read/c/private-common.c +++ b/level_3/fss_extended_read/c/private-common.c @@ -58,6 +58,53 @@ extern "C" { } #endif // _di_fss_extended_read_depths_resize_ +#ifndef _di_fss_extended_read_print_signal_received_ + void fss_extended_read_print_signal_received(fss_extended_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_extended_read_print_signal_received_ + +#ifndef _di_fss_extended_read_signal_received_ + f_status_t fss_extended_read_signal_received(fss_extended_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_extended_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_extended_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/private-common.h b/level_3/fss_extended_read/c/private-common.h index 2986b36..d1e59a9 100644 --- a/level_3/fss_extended_read/c/private-common.h +++ b/level_3/fss_extended_read/c/private-common.h @@ -248,6 +248,36 @@ extern "C" { extern f_status_t fss_extended_read_depths_resize(const f_array_length_t length, fss_extended_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_depths_resize_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_extended_read_print_signal_received_ + extern void fss_extended_read_print_signal_received(fss_extended_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_extended_read_signal_received_ + extern f_status_t fss_extended_read_signal_received(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/private-fss_extended_read.c b/level_3/fss_extended_read/c/private-fss_extended_read.c index b6ae1b5..a8cce6c 100644 --- a/level_3/fss_extended_read/c/private-fss_extended_read.c +++ b/level_3/fss_extended_read/c/private-fss_extended_read.c @@ -59,7 +59,7 @@ extern "C" { #endif // _di_fss_extended_read_delimit_content_is_ #ifndef _di_fss_extended_read_depth_process_ - f_status_t fss_extended_read_depth_process(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) { + f_status_t fss_extended_read_depth_process(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) { f_status_t status = F_none; @@ -89,6 +89,10 @@ extern "C" { for (f_array_length_t i = 0; i < data->depths.used; ++i) { + if (fss_extended_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + data->depths.array[i].depth = 0; data->depths.array[i].index_at = 0; data->depths.array[i].index_name = 0; @@ -171,6 +175,10 @@ extern "C" { for (f_array_length_t j = i + 1; j < data->depths.used; ++j) { + if (fss_extended_read_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (data->depths.array[i].depth == data->depths.array[j].depth) { if (main->error.verbosity != f_console_verbosity_quiet) { flockfile(main->error.to.stream); @@ -259,7 +267,7 @@ extern "C" { #endif // _di_fss_extended_read_load_ #ifndef _di_fss_extended_read_load_number_ - f_status_t fss_extended_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, f_number_unsigned_t *number) { + f_status_t fss_extended_read_load_number(fss_extended_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) { if (main->parameters[parameter].result == f_console_result_additional) { const f_array_length_t index = main->parameters[parameter].values.array[main->parameters[parameter].values.used - 1]; @@ -281,7 +289,7 @@ extern "C" { #endif // _di_fss_extended_read_load_number_ #ifndef _di_fss_extended_read_print_at_ - void fss_extended_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_read_main_t * const main, fss_extended_read_data_t * const data) { + void fss_extended_read_print_at(fss_extended_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_read_data_t * const data) { if (at >= data->contents.used) { return; @@ -373,7 +381,7 @@ extern "C" { #endif // _di_fss_extended_read_print_at_ #ifndef _di_fss_extended_read_print_at_total_ - f_status_t fss_extended_read_print_at_total(const f_array_length_t at, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) { + f_status_t fss_extended_read_print_at_total(fss_extended_read_main_t * const main, const f_array_length_t at, fss_extended_read_data_t *data) { if (data->option & fss_extended_read_data_option_select) { if (data->option & fss_extended_read_data_option_object) { @@ -452,6 +460,7 @@ extern "C" { #ifndef _di_fss_extended_read_print_one_ void fss_extended_read_print_one(fss_extended_read_main_t * const main) { + f_print_character(f_string_ascii_1_s[0], main->output.to.stream); f_print_character(f_string_eol_s[0], main->output.to.stream); } @@ -477,9 +486,9 @@ extern "C" { #endif // _di_fss_extended_read_print_zero_ #ifndef _di_fss_extended_read_process_ - f_status_t fss_extended_read_process(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) { + f_status_t fss_extended_read_process(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) { - f_status_t status = fss_extended_read_process_option(arguments, main, data); + f_status_t status = fss_extended_read_process_option(main, arguments, data); if (F_status_is_error(status)) return status; status = fss_extended_read_load(main, data); @@ -519,7 +528,7 @@ extern "C" { if (!names[i]) continue; - fss_extended_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_read_print_at(main, i, *delimits_object, *delimits_content, data); } // for return F_none; @@ -578,7 +587,7 @@ extern "C" { if (data->line) break; if (data->option & fss_extended_read_data_option_total) { - if (fss_extended_read_print_at_total(i, main, data) == F_none) { + if (fss_extended_read_print_at_total(main, i, data) == F_none) { break; } } @@ -587,7 +596,7 @@ extern "C" { f_print_character_safely(data->quotes_object.array[at] == f_fss_quote_type_single ? f_fss_quote_single_s[0] : f_fss_quote_double_s[0], main->output.to.stream); } - fss_extended_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_read_print_at(main, i, *delimits_object, *delimits_content, data); if ((data->option & fss_extended_read_data_option_raw) && data->quotes_object.array[at]) { f_print_character_safely(data->quotes_object.array[at] == f_fss_quote_type_single ? f_fss_quote_single_s[0] : f_fss_quote_double_s[0], main->output.to.stream); @@ -598,7 +607,7 @@ extern "C" { fll_print_format("%ul%c", main->output.to.stream, data->contents.array[i].used, f_string_eol_s[0]); } else if (data->option & fss_extended_read_data_option_total) { - if (fss_extended_read_print_at_total(i, main, data) == F_none) { + if (fss_extended_read_print_at_total(main, i, data) == F_none) { break; } } @@ -607,7 +616,7 @@ extern "C" { f_print_character_safely(data->quotes_content.array[at].array[i] == f_fss_quote_type_single ? f_fss_quote_single_s[0] : f_fss_quote_double_s[0], main->output.to.stream); } - fss_extended_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_read_print_at(main, i, *delimits_object, *delimits_content, data); if ((data->option & fss_extended_read_data_option_raw) && data->quotes_content.array[at].array[i]) { f_print_character_safely(data->quotes_content.array[at].array[i] == f_fss_quote_type_single ? f_fss_quote_single_s[0] : f_fss_quote_double_s[0], main->output.to.stream); @@ -701,7 +710,7 @@ extern "C" { } if (line == data->line) { - fss_extended_read_print_at(i, *delimits_object, *delimits_content, main, data); + fss_extended_read_print_at(main, i, *delimits_object, *delimits_content, data); break; } @@ -749,7 +758,7 @@ extern "C" { #endif // _di_fss_extended_read_process_name_ #ifndef _di_fss_extended_read_process_option_ - f_status_t fss_extended_read_process_option(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) { + f_status_t fss_extended_read_process_option(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) { f_status_t status = F_none; @@ -772,7 +781,7 @@ extern "C" { if (main->parameters[fss_extended_read_parameter_line].result == f_console_result_additional) { data->option |= fss_extended_read_data_option_line; - status = fss_extended_read_load_number(fss_extended_read_parameter_line, fss_extended_read_long_line_s, arguments, main, &data->line); + status = fss_extended_read_load_number(main, fss_extended_read_parameter_line, fss_extended_read_long_line_s, arguments, &data->line); if (F_status_is_error(status)) return status; } @@ -791,7 +800,7 @@ extern "C" { if (main->parameters[fss_extended_read_parameter_select].result == f_console_result_additional) { data->option |= fss_extended_read_data_option_select; - status = fss_extended_read_load_number(fss_extended_read_parameter_select, fss_extended_read_long_select_s, arguments, main, &data->select); + status = fss_extended_read_load_number(main, fss_extended_read_parameter_select, fss_extended_read_long_select_s, arguments, &data->select); if (F_status_is_error(status)) return status; } diff --git a/level_3/fss_extended_read/c/private-fss_extended_read.h b/level_3/fss_extended_read/c/private-fss_extended_read.h index 54449b9..390b12e 100644 --- a/level_3/fss_extended_read/c/private-fss_extended_read.h +++ b/level_3/fss_extended_read/c/private-fss_extended_read.h @@ -49,10 +49,10 @@ extern "C" { * * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed). * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -72,7 +72,7 @@ extern "C" { * @see fss_extended_read_depths_resize() */ #ifndef _di_fss_extended_read_depth_process_ - extern f_status_t fss_extended_read_depth_process(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_depth_process(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_depth_process_ /** @@ -99,7 +99,7 @@ extern "C" { * This will print an error message on error. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @@ -124,14 +124,14 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param parameter * An ID representing the parameter. * @param name * The parameter name to print on error. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param number * The location to store the loaded number. * @@ -146,7 +146,7 @@ extern "C" { * @see fss_extended_read_depths_resize() */ #ifndef _di_fss_extended_read_load_number_ - extern f_status_t fss_extended_read_load_number(const f_array_length_t parameter, const f_string_t name, f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_load_number(fss_extended_read_main_t * const main, const f_array_length_t parameter, const f_string_t name, const f_console_arguments_t *arguments, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_load_number_ /** @@ -154,28 +154,28 @@ extern "C" { * * Only what is requested to print (Object, Content, both, or neither) will be printed, if there is something to print. * + * @param main + * The main program data. * @param at * The index in the Objects and Contents to print. * @param delimits_object * The delimits to be applied to an Object. * @param delimits_content * The delimits to be applied to Content. - * @param main - * The main data. * @param data * The program data. */ #ifndef _di_fss_extended_read_print_at_ - extern void fss_extended_read_print_at(const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_read_main_t * const main, fss_extended_read_data_t * const data) F_attribute_visibility_internal_d; + extern void fss_extended_read_print_at(fss_extended_read_main_t * const main, const f_array_length_t at, const f_fss_delimits_t delimits_object, const f_fss_delimits_t delimits_content, fss_extended_read_data_t * const data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_print_at_ /** * Print total count at the specified Object/Content position. * + * @param main + * The main program data. * @param at * The Object/Content position. - * @param main - * The main data. * @param data * The program data. * @@ -184,14 +184,14 @@ extern "C" { * F_success on success and something was matched (and total was printed). */ #ifndef _di_fss_extended_read_print_at_total_ - extern f_status_t fss_extended_read_print_at_total(const f_array_length_t at, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_print_at_total(fss_extended_read_main_t * const main, const f_array_length_t at, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_print_at_total_ /** * Print the end of a Content. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_read_print_content_end_ extern void fss_extended_read_print_content_end(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; @@ -201,7 +201,7 @@ extern "C" { * Print the end of an Object (which is essentially the start of Content). * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_read_print_object_end_ extern void fss_extended_read_print_object_end(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; @@ -211,7 +211,7 @@ extern "C" { * Print the number one and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_read_print_one_ extern void fss_extended_read_print_one(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; @@ -221,7 +221,7 @@ extern "C" { * Print the end of an Object/Content set. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_read_print_set_end_ extern void fss_extended_read_print_set_end(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; @@ -231,7 +231,7 @@ extern "C" { * Print the number zero and a newline. * * @param main - * The main data. + * The main program data. */ #ifndef _di_fss_extended_read_print_zero_ extern void fss_extended_read_print_zero(fss_extended_read_main_t * const main) F_attribute_visibility_internal_d; @@ -242,10 +242,10 @@ extern "C" { * * This will print an error message on error. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -259,14 +259,14 @@ extern "C" { * @see fss_extended_read_process_option() */ #ifndef _di_fss_extended_read_process_ - extern f_status_t fss_extended_read_process(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_process(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_process_ /** * Process based on at parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -284,7 +284,7 @@ extern "C" { * Process based on columns parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -302,7 +302,7 @@ extern "C" { * Process based on line parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -321,8 +321,8 @@ extern "C" { * * How an Object name is determined to be used or not is dependent on several parameters, such as --name, --depth, --at, and --line. * - * @param data - * The program data. + * @param main + * The main program data. * @param names * An array of booleans representing whether or not some Object name is to be used. * (If TRUE, then the name is to be used and if FALSE, then the name is not to be used.) @@ -337,10 +337,10 @@ extern "C" { /** * Process the parameters, populating the option property of the program data. * + * @param main + * The main program data. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * @param data * The program data. * @@ -354,14 +354,14 @@ extern "C" { * @see fss_extended_read_load_setting() */ #ifndef _di_fss_extended_read_process_option_ - extern f_status_t fss_extended_read_process_option(f_console_arguments_t * const arguments, fss_extended_read_main_t * const main, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_process_option(fss_extended_read_main_t * const main, const f_console_arguments_t *arguments, fss_extended_read_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_process_option_ /** * Process based on total parameter. * * @param main - * The main data. + * The main program data. * @param data * The program data. * @param names @@ -375,17 +375,11 @@ extern "C" { extern f_status_t fss_extended_read_process_total(fss_extended_read_main_t * const main, fss_extended_read_data_t *data, bool names[]) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_process_total_ - - -/***************************************************************************************************************************************/ - - - /** * Determine if the given depth is to be delimited or not. * * @param main - * The main data. + * The main program data. * @param depth * The depth to check. * @@ -394,16 +388,16 @@ extern "C" { * F_false if not delimited. */ #ifndef _di_fss_extended_read_is_delimited_at_depth_ - extern f_status_t fss_extended_read_is_delimited_at_depth(const fss_extended_read_main_t main, const f_array_length_t depth) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_is_delimited_at_depth(fss_extended_read_main_t * const main, const f_array_length_t depth) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_is_delimited_at_depth_ /** * Process a given file. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. - * @param main - * The main data. * @param file_name * The name of the file being processed. * @param depths @@ -421,7 +415,7 @@ extern "C" { * @see fss_extended_read_main_preprocess_depth() */ #ifndef _di_fss_extended_read_main_process_file_ - extern f_status_t fss_extended_read_main_process_file(const f_console_arguments_t arguments, fss_extended_read_main_t *main, const f_string_t file_name, const fss_extended_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_read_main_process_file(fss_extended_read_main_t * const main, const f_console_arguments_t arguments, const f_string_t file_name, const fss_extended_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_main_process_file_ #ifdef __cplusplus diff --git a/level_3/fss_extended_read/data/build/dependencies b/level_3/fss_extended_read/data/build/dependencies index 7c8767f..25e27eb 100644 --- a/level_3/fss_extended_read/data/build/dependencies +++ b/level_3/fss_extended_read/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_extended_write/c/fss_extended_write.c b/level_3/fss_extended_write/c/fss_extended_write.c index 991b457..9f20684 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.c +++ b/level_3/fss_extended_write/c/fss_extended_write.c @@ -57,7 +57,8 @@ extern "C" { #endif // _di_fss_extended_write_print_help_ #ifndef _di_fss_extended_write_main_ - f_status_t fss_extended_write_main(const f_console_arguments_t arguments, fss_extended_write_main_t *main) { + f_status_t fss_extended_write_main(fss_extended_write_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -67,7 +68,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_extended_write_parameter_no_color, fss_extended_write_parameter_light, fss_extended_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -173,15 +174,15 @@ extern "C" { output.id = -1; output.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &output); + status = f_file_stream_open(arguments->argv[location], 0, &output); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } else if (main->parameters[fss_extended_write_parameter_file].result == f_console_result_found) { - fss_extended_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_write_long_file_s); + fss_extended_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_write_long_file_s); status = F_status_set_error(F_parameter); } } @@ -190,15 +191,15 @@ extern "C" { if (main->parameters[fss_extended_write_parameter_object].locations.used || main->parameters[fss_extended_write_parameter_content].locations.used) { if (main->parameters[fss_extended_write_parameter_object].locations.used) { if (main->parameters[fss_extended_write_parameter_object].locations.used != main->parameters[fss_extended_write_parameter_object].values.used) { - fss_extended_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_write_long_object_s); + fss_extended_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_write_long_object_s); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_extended_write_parameter_content].locations.used != main->parameters[fss_extended_write_parameter_content].values.used) { - fss_extended_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_write_long_content_s); + fss_extended_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_extended_write_parameter_content].locations.used && main->parameters[fss_extended_write_parameter_partial].result == f_console_result_none) { - fss_extended_write_error_parameter_at_least_once(*main); + fss_extended_write_error_parameter_at_least_once(main); status = F_status_set_error(F_parameter); } else if (main->parameters[fss_extended_write_parameter_content].locations.used && main->parameters[fss_extended_write_parameter_partial].locations.used) { @@ -270,11 +271,11 @@ extern "C" { } else if (main->parameters[fss_extended_write_parameter_content].locations.used) { if (main->parameters[fss_extended_write_parameter_content].locations.used != main->parameters[fss_extended_write_parameter_content].values.used) { - fss_extended_write_error_parameter_value_missing_print(*main, f_console_symbol_long_enable_s, fss_extended_write_long_content_s); + fss_extended_write_error_parameter_value_missing_print(main, f_console_symbol_long_enable_s, fss_extended_write_long_content_s); status = F_status_set_error(F_parameter); } else if (!main->parameters[fss_extended_write_parameter_partial].locations.used) { - fss_extended_write_error_parameter_at_least_once(*main); + fss_extended_write_error_parameter_at_least_once(main); status = F_status_set_error(F_parameter); } } @@ -328,12 +329,12 @@ extern "C" { } else if (main->parameters[fss_extended_write_parameter_prepend].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_extended_write_parameter_prepend].values.array[main->parameters[fss_extended_write_parameter_prepend].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); // Even though this standard does not utilize this parameter, provide the validation for consistency. if (length) { f_string_range_t range = macro_f_string_range_t_initialize(length); - const f_string_static_t prepend = macro_f_string_static_t_initialize(arguments.argv[index], length); + const f_string_static_t prepend = macro_f_string_static_t_initialize(arguments->argv[index], length); for (; range.start < length; ++range.start) { @@ -427,7 +428,7 @@ extern "C" { f_string_dynamic_t escaped = f_string_dynamic_t_initialize; if (main->process_pipe) { - status = fss_extended_write_process_pipe(*main, output, quote, &buffer); + status = fss_extended_write_process_pipe(main, output, quote, &buffer); if (F_status_is_error(status)) { if (main->error.verbosity != f_console_verbosity_quiet) { @@ -448,11 +449,16 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[fss_extended_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[fss_extended_write_parameter_object].values.array[i]]; + if (fss_extended_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[fss_extended_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - status = fss_extended_write_process(*main, output, quote, &object, 0, &buffer); + status = fss_extended_write_process(main, output, quote, &object, 0, &buffer); if (F_status_is_error(status)) break; } // for } @@ -473,13 +479,13 @@ extern "C" { for (; i < main->parameters[fss_extended_write_parameter_content].values.used; ++i) { - contents.array[contents.used].string = arguments.argv[main->parameters[fss_extended_write_parameter_content].values.array[i]]; + contents.array[contents.used].string = arguments->argv[main->parameters[fss_extended_write_parameter_content].values.array[i]]; contents.array[contents.used].used = strnlen(contents.array[contents.used].string, f_console_parameter_size); contents.array[contents.used].size = contents.array[contents.used].used; ++contents.used; } // for - status = fss_extended_write_process(*main, output, quote, 0, &contents, &buffer); + status = fss_extended_write_process(main, output, quote, 0, &contents, &buffer); // clear the contents array of the static strings to avoid deallocation attempts on static variables. for (; i < main->parameters[fss_extended_write_parameter_content].values.used; ++i) { @@ -502,13 +508,18 @@ extern "C" { for (; i < main->parameters[fss_extended_write_parameter_object].values.used; ++i) { + if (fss_extended_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + object_current = main->parameters[fss_extended_write_parameter_object].locations.array[i]; if (i + 1 < main->parameters[fss_extended_write_parameter_object].values.used) { object_next = main->parameters[fss_extended_write_parameter_object].locations.array[i + 1]; } - object.string = arguments.argv[main->parameters[fss_extended_write_parameter_object].values.array[i]]; + object.string = arguments->argv[main->parameters[fss_extended_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; @@ -533,7 +544,7 @@ extern "C" { contents.array[contents.used].used = 0; } - status = f_string_append(arguments.argv[main->parameters[fss_extended_write_parameter_content].values.array[j]], strnlen(arguments.argv[main->parameters[fss_extended_write_parameter_content].values.array[j]], f_console_parameter_size), &contents.array[contents.used]); + status = f_string_append(arguments->argv[main->parameters[fss_extended_write_parameter_content].values.array[j]], strnlen(arguments->argv[main->parameters[fss_extended_write_parameter_content].values.array[j]], f_console_parameter_size), &contents.array[contents.used]); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); @@ -545,7 +556,7 @@ extern "C" { if (F_status_is_error(status)) break; - status = fss_extended_write_process(*main, output, quote, &object, &contents, &buffer); + status = fss_extended_write_process(main, output, quote, &object, &contents, &buffer); if (F_status_is_error(status)) break; } // for } @@ -584,10 +595,14 @@ extern "C" { } } - // ensure a newline is always put at the end of the program execution, unless in quiet mode. + // Ensure a newline is always put at the end of the program execution, unless in quiet mode. if (main->error.verbosity != f_console_verbosity_quiet) { if (F_status_is_error(status)) { - fll_print_character(f_string_eol_s[0], main->error.to.stream); + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_terminated(f_string_eol_s, main->output.to.stream); } } @@ -595,12 +610,13 @@ extern "C" { macro_f_string_dynamic_t_delete_simple(object); macro_f_string_dynamics_t_delete_simple(contents); fss_extended_write_main_delete(main); + return status; } #endif // _di_fss_extended_write_main_ #ifndef _di_fss_extended_write_main_delete_ - f_status_t fss_extended_write_main_delete(fss_extended_write_main_t *main) { + f_status_t fss_extended_write_main_delete(fss_extended_write_main_t * const main) { for (f_array_length_t i = 0; i < fss_extended_write_total_parameters_d; ++i) { diff --git a/level_3/fss_extended_write/c/fss_extended_write.h b/level_3/fss_extended_write/c/fss_extended_write.h index 86635d3..7746444 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.h +++ b/level_3/fss_extended_write/c/fss_extended_write.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -147,6 +148,9 @@ extern "C" { fl_print_t output; fl_print_t error; fl_print_t warning; + + f_signal_t signal; + f_string_static_t prepend; f_color_context_t context; @@ -160,6 +164,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_static_t_initialize, \ f_color_context_t_initialize, \ } @@ -185,10 +190,18 @@ extern "C" { * * Be sure to call fss_extended_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -198,7 +211,7 @@ extern "C" { * @see fss_extended_write_main_delete() */ #ifndef _di_fss_extended_write_main_ - extern f_status_t fss_extended_write_main(const f_console_arguments_t arguments, fss_extended_write_main_t *main); + extern f_status_t fss_extended_write_main(fss_extended_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_extended_write_main_ /** @@ -207,7 +220,7 @@ extern "C" { * Be sure to call this after executing fss_extended_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -217,7 +230,7 @@ extern "C" { * @see fss_extended_write_main() */ #ifndef _di_fss_extended_write_main_delete_ - extern f_status_t fss_extended_write_main_delete(fss_extended_write_main_t *main); + extern f_status_t fss_extended_write_main_delete(fss_extended_write_main_t * const main); #endif // _di_fss_extended_write_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_extended_write/c/main.c b/level_3/fss_extended_write/c/main.c index 2ed3a78..3bb3f3a 100644 --- a/level_3/fss_extended_write/c/main.c +++ b/level_3/fss_extended_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_extended_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_extended_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_extended_write/c/private-common.c b/level_3/fss_extended_write/c/private-common.c index 635db9c..dd095ea 100644 --- a/level_3/fss_extended_write/c/private-common.c +++ b/level_3/fss_extended_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_extended_write_print_signal_received_ + void fss_extended_write_print_signal_received(fss_extended_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_extended_write_print_signal_received_ + +#ifndef _di_fss_extended_write_signal_received_ + f_status_t fss_extended_write_signal_received(fss_extended_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_extended_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_extended_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/private-common.h b/level_3/fss_extended_write/c/private-common.h index 9ee310b..2618a78 100644 --- a/level_3/fss_extended_write/c/private-common.h +++ b/level_3/fss_extended_write/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define fss_extended_write_common_allocation_small_d 16 #endif // _di_fss_extended_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_extended_write_print_signal_received_ + extern void fss_extended_write_print_signal_received(fss_extended_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_extended_write_signal_received_ + extern f_status_t fss_extended_write_signal_received(fss_extended_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_extended_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/private-fss_extended_write.c b/level_3/fss_extended_write/c/private-fss_extended_write.c index 14319dc..e5ec11e 100644 --- a/level_3/fss_extended_write/c/private-fss_extended_write.c +++ b/level_3/fss_extended_write/c/private-fss_extended_write.c @@ -7,62 +7,62 @@ extern "C" { #endif #ifndef _di_fss_extended_write_error_parameter_at_least_once_print_ - void fss_extended_write_error_parameter_at_least_once(const fss_extended_write_main_t main) { + void fss_extended_write_error_parameter_at_least_once(fss_extended_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sMust specify the '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_object_s, main.error.notable); - fl_print_format("%[' parameter and the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_content_s, main.error.notable); - fl_print_format("%[' parameter the same number of times when not specifying the '%]", main.error.to.stream, main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%s%s%]", main.error.to.stream, main.error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_partial_s, main.error.notable); - fl_print_format("%[' parameter.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sMust specify the '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_object_s, main->error.notable); + fl_print_format("%[' parameter and the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_content_s, main->error.notable); + fl_print_format("%[' parameter the same number of times when not specifying the '%]", main->error.to.stream, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_extended_write_long_partial_s, main->error.notable); + fl_print_format("%[' parameter.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_write_error_parameter_at_least_once_print_ #ifndef _di_fss_extended_write_error_parameter_value_missing_print_ - void fss_extended_write_error_parameter_value_missing_print(const fss_extended_write_main_t main, const f_string_t symbol, const f_string_t parameter) { + void fss_extended_write_error_parameter_value_missing_print(fss_extended_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe parameter '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%S%S%]", main.error.to.stream, main.error.notable, symbol, parameter, main.error.notable); - fl_print_format("%[' was specified, but no value was given.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe parameter '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%S%S%]", main->error.to.stream, main->error.notable, symbol, parameter, main->error.notable); + fl_print_format("%[' was specified, but no value was given.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_write_error_parameter_value_missing_print_ #ifndef _di_fss_extended_write_error_parameter_unsupported_eol_print_ - void fss_extended_write_error_parameter_unsupported_eol_print(const fss_extended_write_main_t main) { + void fss_extended_write_error_parameter_unsupported_eol_print(fss_extended_write_main_t * const main) { - if (main.error.verbosity == f_console_verbosity_quiet) { + if (main->error.verbosity == f_console_verbosity_quiet) { return; } - flockfile(main.error.to.stream); + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThis standard does not support end of line character '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[\\n%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[' in objects.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThis standard does not support end of line character '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[\\n%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[' in objects.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } #endif // _di_fss_extended_write_error_parameter_unsupported_eol_print_ #ifndef _di_fss_extended_write_process_ - f_status_t fss_extended_write_process(const fss_extended_write_main_t main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_statics_t *contents, f_string_dynamic_t *buffer) { + f_status_t fss_extended_write_process(fss_extended_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_statics_t *contents, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_state_t state = macro_f_state_t_initialize(fss_extended_write_common_allocation_large_d, fss_extended_write_common_allocation_small_d, 0, 0, 0, 0, 0); @@ -81,7 +81,7 @@ extern "C" { } if (contents && contents->used) { - if (main.parameters[fss_extended_write_parameter_trim].result == f_console_result_found) { + if (main->parameters[fss_extended_write_parameter_trim].result == f_console_result_found) { complete = f_fss_complete_full_trim; } else { @@ -98,7 +98,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_extended_object_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_extended_object_write_string", F_true); return F_status_set_error(status); } @@ -126,7 +126,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fl_fss_extended_content_write_string", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fl_fss_extended_content_write_string", F_true); return F_status_set_error(status); } @@ -137,7 +137,7 @@ extern "C" { status = f_string_append(f_string_eol_s, 1, buffer); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_append", F_true); return status; } @@ -151,7 +151,7 @@ extern "C" { #endif // _di_fss_extended_write_process_ #ifndef _di_fss_extended_write_process_pipe_ - f_status_t fss_extended_write_process_pipe(const fss_extended_write_main_t main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { + f_status_t fss_extended_write_process_pipe(fss_extended_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) { f_status_t status = F_none; f_status_t status_pipe = F_none; @@ -176,6 +176,10 @@ extern "C" { for (;;) { + if (fss_extended_write_signal_received(main)) { + return F_status_set_error(F_interrupt); + } + if (range.start > range.stop) { if (status_pipe == F_none_eof) break; @@ -184,7 +188,7 @@ extern "C" { status_pipe = f_file_read_block(input, &block); if (F_status_is_error(status_pipe)) { - fll_error_print(main.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); + fll_error_print(main->error, F_status_set_fine(status_pipe), "f_file_read_block", F_true); status_pipe = F_status_set_error(F_pipe); break; @@ -214,7 +218,7 @@ extern "C" { status = f_string_dynamic_increase_by(block.used, &object); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } @@ -255,7 +259,7 @@ extern "C" { status = f_string_dynamics_increase_by(F_fss_default_allocation_step_d, &contents); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); break; } } @@ -280,7 +284,7 @@ extern "C" { status = f_string_dynamics_increase_by(F_fss_default_allocation_step_d, &contents); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); break; } } @@ -312,7 +316,7 @@ extern "C" { status = f_string_dynamic_increase_by(F_fss_default_allocation_step_d, &contents.array[contents.used - 1]); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true); break; } } diff --git a/level_3/fss_extended_write/c/private-fss_extended_write.h b/level_3/fss_extended_write/c/private-fss_extended_write.h index 32a9477..21e7892 100644 --- a/level_3/fss_extended_write/c/private-fss_extended_write.h +++ b/level_3/fss_extended_write/c/private-fss_extended_write.h @@ -15,22 +15,22 @@ extern "C" { /** * Print an message about the object and content parameters not being specified the correct number of times. * - * @param data - * The main data. + * @param main + * The main program data. * * @return * F_none on success. * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_write_error_parameter_at_least_once_print_ - void fss_extended_write_error_parameter_at_least_once(const fss_extended_write_main_t data) F_attribute_visibility_internal_d; + void fss_extended_write_error_parameter_at_least_once(fss_extended_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_extended_write_error_parameter_at_least_once_print_ /** * Print an message about a parameter missing a value. * - * @param data - * The main data. + * @param main + * The main program data. * @param symbol * The console symbol, such as "--" in "--help". * @param parameter @@ -41,28 +41,28 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_write_error_parameter_value_missing_print_ - void fss_extended_write_error_parameter_value_missing_print(const fss_extended_write_main_t data, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; + void fss_extended_write_error_parameter_value_missing_print(fss_extended_write_main_t * const main, const f_string_t symbol, const f_string_t parameter) F_attribute_visibility_internal_d; #endif // _di_fss_extended_write_error_parameter_value_missing_print_ /** * Print an message about a parameter EOL being unsupported. * - * @param data - * The main data. + * @param main + * The main program data. * * @return * F_none on success. * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_write_error_parameter_unsupported_eol_print_ - void fss_extended_write_error_parameter_unsupported_eol_print(const fss_extended_write_main_t data) F_attribute_visibility_internal_d; + void fss_extended_write_error_parameter_unsupported_eol_print(fss_extended_write_main_t * const main) F_attribute_visibility_internal_d; #endif // _di_fss_extended_write_error_parameter_unsupported_eol_print_ /** * Process a given object and content, printing the FSS if valid or an error if invalid. * - * @param data - * The main data. + * @param main + * The main program data. * @param output * The file to output to. * @param quote @@ -82,14 +82,14 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_write_process_ - extern f_status_t fss_extended_write_process(const fss_extended_write_main_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_statics_t *contents, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_write_process(fss_extended_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_statics_t *contents, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_extended_write_process_ /** * Process the pipe, reading from the pipe and writing to the output. * - * @param data - * The main data. + * @param main + * The main program data. * @param output * The file to output to. * @param quote @@ -103,7 +103,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_fss_extended_write_process_pipe_ - extern f_status_t fss_extended_write_process_pipe(const fss_extended_write_main_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; + extern f_status_t fss_extended_write_process_pipe(fss_extended_write_main_t * const main, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) F_attribute_visibility_internal_d; #endif // _di_fss_extended_write_process_pipe_ #ifdef __cplusplus diff --git a/level_3/fss_extended_write/data/build/dependencies b/level_3/fss_extended_write/data/build/dependencies index e9f562b..64034db 100644 --- a/level_3/fss_extended_write/data/build/dependencies +++ b/level_3/fss_extended_write/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_conversion fl_fss fl_print diff --git a/level_3/fss_identify/c/fss_identify.c b/level_3/fss_identify/c/fss_identify.c index 862fa7d..ba43591 100644 --- a/level_3/fss_identify/c/fss_identify.c +++ b/level_3/fss_identify/c/fss_identify.c @@ -58,7 +58,8 @@ extern "C" { #endif // _di_fss_identify_print_help_ #ifndef _di_fss_identify_main_ - f_status_t fss_identify_main(const f_console_arguments_t arguments, fss_identify_main_t *main) { + f_status_t fss_identify_main(fss_identify_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -68,7 +69,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_identify_parameter_no_color, fss_identify_parameter_light, fss_identify_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -173,12 +174,12 @@ extern "C" { } else if (main->parameters[fss_identify_parameter_line].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_identify_parameter_line].values.array[main->parameters[fss_identify_parameter_line].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strnlen(arguments.argv[index], f_console_parameter_size)); + const f_string_range_t range = macro_f_string_range_t_initialize(strnlen(arguments->argv[index], f_console_parameter_size)); - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &data.line); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &data.line); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_identify_long_line_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_identify_long_line_s, arguments->argv[index]); } } } @@ -226,7 +227,7 @@ extern "C" { } else if (main->parameters[fss_identify_parameter_name].result == f_console_result_additional) { const f_array_length_t index = main->parameters[fss_identify_parameter_name].values.array[main->parameters[fss_identify_parameter_name].values.used - 1]; - const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_array_length_t length = strnlen(arguments->argv[index], f_console_parameter_size); const f_string_range_t range = macro_f_string_range_t_initialize(length); if (length == 0) { @@ -252,7 +253,7 @@ extern "C" { for (f_array_length_t i = range.start; i <= range.stop; ++i) { - status = f_utf_is_word(arguments.argv[index] + i, length, F_true); + status = f_utf_is_word(arguments->argv[index] + i, length, F_true); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "f_utf_is_word", F_true); @@ -263,7 +264,7 @@ extern "C" { flockfile(main->error.to.stream); fl_print_format("%c%[%sThe value '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); - fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, arguments.argv[index], main->error.notable); + fl_print_format("%[%S%]", main->error.to.stream, main->error.notable, arguments->argv[index], main->error.notable); fl_print_format("%[' for the parameter '%]", main->error.to.stream, main->error.context, main->error.context); fl_print_format("%[%s%s%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_identify_long_name_s, main->error.notable); fl_print_format("%[' may only contain word characters.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); @@ -275,7 +276,7 @@ extern "C" { break; } - data.name.string[data.name.used++] = arguments.argv[index][i]; + data.name.string[data.name.used++] = arguments->argv[index][i]; } // for } } @@ -290,10 +291,10 @@ extern "C" { file.stream = F_type_input_d; file.size_read = 512; - status = fss_identify_load_line(*main, file, "-", &buffer, &range); + status = fss_identify_load_line(main, file, "-", &buffer, &range); if (F_status_is_error_not(status)) { - status = fss_identify_process(*main, "-", buffer, &range, &data); + status = fss_identify_process(main, "-", buffer, &range, &data); } } @@ -301,6 +302,11 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { + if (fss_identify_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + if (main->parameters[fss_identify_parameter_line].result == f_console_result_additional) { if (data.current > data.line) break; } @@ -309,16 +315,16 @@ extern "C" { file.size_read = 512; - status = f_file_stream_open(arguments.argv[main->remaining.array[i]], 0, &file); + status = f_file_stream_open(arguments->argv[main->remaining.array[i]], 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[main->remaining.array[i]], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[main->remaining.array[i]], "open", fll_error_file_type_file); } else { - status = fss_identify_load_line(*main, file, arguments.argv[main->remaining.array[i]], &buffer, &range); + status = fss_identify_load_line(main, file, arguments->argv[main->remaining.array[i]], &buffer, &range); if (F_status_is_error_not(status)) { - status = fss_identify_process(*main, arguments.argv[main->remaining.array[i]], buffer, &range, &data); + status = fss_identify_process(main, arguments->argv[main->remaining.array[i]], buffer, &range, &data); } } @@ -336,10 +342,14 @@ extern "C" { } } - // ensure a newline is always put at the end of the program execution, unless in quiet mode. + // Ensure a newline is always put at the end of the program execution, unless in quiet mode. if (main->error.verbosity != f_console_verbosity_quiet) { if (F_status_is_error(status)) { - fll_print_character(f_string_eol_s[0], main->error.to.stream); + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_terminated(f_string_eol_s, main->output.to.stream); } } @@ -351,7 +361,7 @@ extern "C" { #endif // _di_fss_identify_main_ #ifndef _di_fss_identify_main_delete_ - f_status_t fss_identify_main_delete(fss_identify_main_t *main) { + f_status_t fss_identify_main_delete(fss_identify_main_t * const main) { for (f_array_length_t i = 0; i < fss_identify_total_parameters_d; ++i) { diff --git a/level_3/fss_identify/c/fss_identify.h b/level_3/fss_identify/c/fss_identify.h index 5fdf19e..167cfcd 100644 --- a/level_3/fss_identify/c/fss_identify.h +++ b/level_3/fss_identify/c/fss_identify.h @@ -30,6 +30,7 @@ #include #include #include +#include // fll-1 includes #include @@ -132,6 +133,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_identify_main_t; @@ -143,6 +146,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_identify_data_t_ @@ -167,10 +171,18 @@ extern "C" { * * Be sure to call fss_identify_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The program main data. * * @return * F_none on success. @@ -180,7 +192,7 @@ extern "C" { * @see fss_identify_main_delete() */ #ifndef _di_fss_identify_main_ - extern f_status_t fss_identify_main(const f_console_arguments_t arguments, fss_identify_main_t *main); + extern f_status_t fss_identify_main(fss_identify_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_identify_main_ /** @@ -189,7 +201,7 @@ extern "C" { * Be sure to call this after executing fss_identify_main(). * * @param main - * The program main data. + * The main program data. * * @return * F_none on success. @@ -199,7 +211,7 @@ extern "C" { * @see fss_identify_main() */ #ifndef _di_fss_identify_main_delete_ - extern f_status_t fss_identify_main_delete(fss_identify_main_t *main); + extern f_status_t fss_identify_main_delete(fss_identify_main_t * const main); #endif // _di_fss_identify_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_identify/c/main.c b/level_3/fss_identify/c/main.c index b7a473b..23c59a7 100644 --- a/level_3/fss_identify/c/main.c +++ b/level_3/fss_identify/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_identify_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_identify_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/fss_identify/c/private-common.c b/level_3/fss_identify/c/private-common.c index e6d4b34..dcf1eaa 100644 --- a/level_3/fss_identify/c/private-common.c +++ b/level_3/fss_identify/c/private-common.c @@ -14,6 +14,53 @@ extern "C" { } #endif // _di_fss_identify_data_delete_ +#ifndef _di_fss_identify_print_signal_received_ + void fss_identify_print_signal_received(fss_identify_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_identify_print_signal_received_ + +#ifndef _di_fss_identify_signal_received_ + f_status_t fss_identify_signal_received(fss_identify_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_identify_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_identify_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-common.h b/level_3/fss_identify/c/private-common.h index 66ee609..d2a7f50 100644 --- a/level_3/fss_identify/c/private-common.h +++ b/level_3/fss_identify/c/private-common.h @@ -48,6 +48,36 @@ extern "C" { extern void fss_identify_data_delete(fss_identify_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_identify_data_delete_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_identify_print_signal_received_ + extern void fss_identify_print_signal_received(fss_identify_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_identify_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_identify_signal_received_ + extern f_status_t fss_identify_signal_received(fss_identify_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_identify_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-fss_identify.c b/level_3/fss_identify/c/private-fss_identify.c index 6510389..5e49cd0 100644 --- a/level_3/fss_identify/c/private-fss_identify.c +++ b/level_3/fss_identify/c/private-fss_identify.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_fss_identify_load_line_ - f_status_t fss_identify_load_line(const fss_identify_main_t main, const f_file_t file, const f_string_t name, f_string_static_t *buffer, f_string_range_t *range) { + f_status_t fss_identify_load_line(fss_identify_main_t * const main, const f_file_t file, const f_string_t name, f_string_static_t *buffer, f_string_range_t *range) { f_status_t status = F_none; @@ -17,11 +17,16 @@ extern "C" { range->stop = 0; do { + if (fss_identify_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + if (buffer->used + file.size_read > buffer->size) { status = f_string_dynamic_resize(buffer->size + file.size_read, buffer); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_string_dynamic_resize", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); + fll_error_file_print(main->error, F_status_set_fine(status), "f_string_dynamic_resize", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); return status; } @@ -30,7 +35,7 @@ extern "C" { status = f_file_stream_read_block(file, buffer); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "f_file_stream_read_block", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read_block", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); return status; } @@ -53,30 +58,30 @@ extern "C" { #endif // _di_fss_identify_load_line_ #ifndef _di_fss_identify_print_ - void fss_identify_print(const fss_identify_main_t main, f_fll_id_t id) { + void fss_identify_print(fss_identify_main_t * const main, f_fll_id_t id) { - flockfile(main.output.to.stream); + flockfile(main->output.to.stream); - if (main.parameters[fss_identify_parameter_object].result == f_console_result_found || main.parameters[fss_identify_parameter_content].result != f_console_result_found) { - f_print(id.name, id.used, main.output.to.stream); + if (main->parameters[fss_identify_parameter_object].result == f_console_result_found || main->parameters[fss_identify_parameter_content].result != f_console_result_found) { + f_print(id.name, id.used, main->output.to.stream); - if (main.parameters[fss_identify_parameter_object].result != f_console_result_found || main.parameters[fss_identify_parameter_content].result == f_console_result_found) { - f_print_terminated(f_fss_type_header_part5_s, main.output.to.stream); + if (main->parameters[fss_identify_parameter_object].result != f_console_result_found || main->parameters[fss_identify_parameter_content].result == f_console_result_found) { + f_print_terminated(f_fss_type_header_part5_s, main->output.to.stream); } } - if (main.parameters[fss_identify_parameter_object].result != f_console_result_found || main.parameters[fss_identify_parameter_content].result == f_console_result_found) { - fl_print_format("%04_ui", main.output.to.stream, id.type); + if (main->parameters[fss_identify_parameter_object].result != f_console_result_found || main->parameters[fss_identify_parameter_content].result == f_console_result_found) { + fl_print_format("%04_ui", main->output.to.stream, id.type); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); - funlockfile(main.output.to.stream); + funlockfile(main->output.to.stream); } #endif // _di_fss_identify_print_ #ifndef _di_fss_identify_process_ - f_status_t fss_identify_process(const fss_identify_main_t main, const f_string_t name, const f_string_static_t buffer, f_string_range_t *range, fss_identify_data_t *data) { + f_status_t fss_identify_process(fss_identify_main_t * const main, const f_string_t name, const f_string_static_t buffer, f_string_range_t *range, fss_identify_data_t *data) { f_status_t status = F_none; f_fll_ids_t ids = f_fll_ids_t_initialize; @@ -84,14 +89,14 @@ extern "C" { status = fll_fss_identify(buffer.string, range, &ids); if (F_status_is_error(status)) { - fll_error_file_print(main.error, F_status_set_fine(status), "fll_fss_identify", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); + fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_identify", F_true, name ? name : "-", "read", name ? fll_error_file_type_file : fll_error_file_type_pipe); f_type_fll_ids_resize(0, &ids); return status; } - if (main.parameters[fss_identify_parameter_line].result == f_console_result_additional) { + if (main->parameters[fss_identify_parameter_line].result == f_console_result_additional) { for (f_array_length_t i = 0; i < ids.used; ++i, ++data->current) { @@ -102,7 +107,7 @@ extern "C" { } } - if (main.parameters[fss_identify_parameter_total].result == f_console_result_found) { + if (main->parameters[fss_identify_parameter_total].result == f_console_result_found) { ++data->total; } else { @@ -115,7 +120,7 @@ extern "C" { } } // for } - else if (main.parameters[fss_identify_parameter_total].result == f_console_result_found) { + else if (main->parameters[fss_identify_parameter_total].result == f_console_result_found) { if (data->name.used) { for (f_array_length_t i = 0; i < ids.used; ++i, ++data->current) { diff --git a/level_3/fss_identify/c/private-fss_identify.h b/level_3/fss_identify/c/private-fss_identify.h index ba58149..07ec632 100644 --- a/level_3/fss_identify/c/private-fss_identify.h +++ b/level_3/fss_identify/c/private-fss_identify.h @@ -16,7 +16,7 @@ extern "C" { * Load a pipe or a file 1 block at a time untul a newline is found. * * @param main - * The main data. + * The main program data. * @param file * The file or pipe to load from. * @param name @@ -37,26 +37,26 @@ extern "C" { * @see f_string_dynamic_resize() */ #ifndef _di_fss_identify_load_line_ - extern f_status_t fss_identify_load_line(const fss_identify_main_t main, const f_file_t file, const f_string_t name, f_string_static_t *buffer, f_string_range_t *range) F_attribute_visibility_internal_d; + extern f_status_t fss_identify_load_line(fss_identify_main_t * const main, const f_file_t file, const f_string_t name, f_string_static_t *buffer, f_string_range_t *range) F_attribute_visibility_internal_d; #endif // _di_fss_identify_load_line_ /** * Print the given FLL Identifier. * * @param main - * The main data. + * The main program data. * @param id * The Identifier to print. */ #ifndef _di_fss_identify_print_ - extern void fss_identify_print(const fss_identify_main_t main, f_fll_id_t id) F_attribute_visibility_internal_d; + extern void fss_identify_print(fss_identify_main_t * const main, f_fll_id_t id) F_attribute_visibility_internal_d; #endif // _di_fss_identify_print_ /** * Process a given pipe or file. * * @param main - * The main data. + * The main program data. * @param name * The name of the file. * Set to NULL to designate that this is a pipe. @@ -75,7 +75,7 @@ extern "C" { * @see fll_fss_identify() */ #ifndef _di_fss_identify_process_ - extern f_status_t fss_identify_process(const fss_identify_main_t main, const f_string_t name, const f_string_static_t buffer, f_string_range_t *range, fss_identify_data_t *data) F_attribute_visibility_internal_d; + extern f_status_t fss_identify_process(fss_identify_main_t * const main, const f_string_t name, const f_string_static_t buffer, f_string_range_t *range, fss_identify_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_identify_process_ #ifdef __cplusplus diff --git a/level_3/fss_identify/data/build/dependencies b/level_3/fss_identify/data/build/dependencies index 84d8784..65a5dd1 100644 --- a/level_3/fss_identify/data/build/dependencies +++ b/level_3/fss_identify/data/build/dependencies @@ -12,6 +12,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/fss_status_code/c/fss_status_code.c b/level_3/fss_status_code/c/fss_status_code.c index 445cbce..8f68a42 100644 --- a/level_3/fss_status_code/c/fss_status_code.c +++ b/level_3/fss_status_code/c/fss_status_code.c @@ -39,7 +39,8 @@ extern "C" { #endif // _di_fss_status_code_print_help_ #ifndef _di_fss_status_code_main_ - f_status_t fss_status_code_main(const f_console_arguments_t arguments, fss_status_code_main_t *main) { + f_status_t fss_status_code_main(fss_status_code_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -49,7 +50,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { fss_status_code_parameter_no_color, fss_status_code_parameter_light, fss_status_code_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -193,7 +194,12 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = fss_status_code_process_check(*main, arguments.argv[main->remaining.array[i]]); + if (fss_status_code_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status2 = fss_status_code_process_check(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -213,7 +219,12 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = fss_status_code_process_number(*main, arguments.argv[main->remaining.array[i]]); + if (fss_status_code_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status2 = fss_status_code_process_number(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -232,7 +243,13 @@ extern "C" { flockfile(main->output.to.stream); for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = fss_status_code_process_normal(*main, arguments.argv[main->remaining.array[i]]); + + if (fss_status_code_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + status2 = fss_status_code_process_normal(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -243,13 +260,22 @@ extern "C" { } } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + fss_status_code_main_delete(main); + return status; } #endif // _di_fss_status_code_main_ #ifndef _di_fss_status_code_main_delete_ - f_status_t fss_status_code_main_delete(fss_status_code_main_t *main) { + f_status_t fss_status_code_main_delete(fss_status_code_main_t * const main) { for (f_array_length_t i = 0; i < fss_status_code_total_parameters_d; ++i) { diff --git a/level_3/fss_status_code/c/fss_status_code.h b/level_3/fss_status_code/c/fss_status_code.h index d833d08..32cee07 100644 --- a/level_3/fss_status_code/c/fss_status_code.h +++ b/level_3/fss_status_code/c/fss_status_code.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -125,6 +126,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } fss_status_code_main_t; @@ -136,6 +139,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_fss_status_code_main_t_ @@ -160,10 +164,18 @@ extern "C" { * * Be sure to call fss_status_code_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -173,7 +185,7 @@ extern "C" { * @see fss_status_code_main_delete() */ #ifndef _di_fss_status_code_main_ - extern f_status_t fss_status_code_main(const f_console_arguments_t arguments, fss_status_code_main_t *main); + extern f_status_t fss_status_code_main(fss_status_code_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_fss_status_code_main_ /** @@ -182,7 +194,7 @@ extern "C" { * Be sure to call this after executing fss_status_code_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -192,7 +204,7 @@ extern "C" { * @see fss_status_code_main() */ #ifndef _di_fss_status_code_main_delete_ - extern f_status_t fss_status_code_main_delete(fss_status_code_main_t *main); + extern f_status_t fss_status_code_main_delete(fss_status_code_main_t * const main); #endif // _di_fss_status_code_main_delete_ #ifdef __cplusplus diff --git a/level_3/fss_status_code/c/main.c b/level_3/fss_status_code/c/main.c index 71652b8..f759ef3 100644 --- a/level_3/fss_status_code/c/main.c +++ b/level_3/fss_status_code/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = fss_status_code_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = fss_status_code_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status) || status == F_false) { return 1; } diff --git a/level_3/fss_status_code/c/private-common.c b/level_3/fss_status_code/c/private-common.c index 24a88a7..3d12c1e 100644 --- a/level_3/fss_status_code/c/private-common.c +++ b/level_3/fss_status_code/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_fss_status_code_print_signal_received_ + void fss_status_code_print_signal_received(fss_status_code_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_fss_status_code_print_signal_received_ + +#ifndef _di_fss_status_code_signal_received_ + f_status_t fss_status_code_signal_received(fss_status_code_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + fss_status_code_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_fss_status_code_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_status_code/c/private-common.h b/level_3/fss_status_code/c/private-common.h index 9d44e9a..9f3c6bc 100644 --- a/level_3/fss_status_code/c/private-common.h +++ b/level_3/fss_status_code/c/private-common.h @@ -12,6 +12,36 @@ extern "C" { #endif +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_fss_status_code_print_signal_received_ + extern void fss_status_code_print_signal_received(fss_status_code_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_fss_status_code_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_fss_status_code_signal_received_ + extern f_status_t fss_status_code_signal_received(fss_status_code_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_fss_status_code_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_status_code/c/private-fss_status_code.c b/level_3/fss_status_code/c/private-fss_status_code.c index 9eef232..d75d643 100644 --- a/level_3/fss_status_code/c/private-fss_status_code.c +++ b/level_3/fss_status_code/c/private-fss_status_code.c @@ -7,42 +7,42 @@ extern "C" { #endif #ifndef _di_fss_status_code_process_check_ - f_status_t fss_status_code_process_check(const fss_status_code_main_t main, const f_string_t value) { + f_status_t fss_status_code_process_check(fss_status_code_main_t * const main, const f_string_t value) { f_number_unsigned_t number = 0; f_status_t status = fss_status_code_convert_number(main, value, &number); if (F_status_is_error(status)) return status; - if (main.parameters[fss_status_code_parameter_is_error].result == f_console_result_found) { + if (main->parameters[fss_status_code_parameter_is_error].result == f_console_result_found) { if (F_status_is_error(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } - else if (main.parameters[fss_status_code_parameter_is_warning].result == f_console_result_found) { + else if (main->parameters[fss_status_code_parameter_is_warning].result == f_console_result_found) { if (F_status_is_warning(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } - else if (main.parameters[fss_status_code_parameter_is_fine].result == f_console_result_found) { + else if (main->parameters[fss_status_code_parameter_is_fine].result == f_console_result_found) { if (F_status_is_fine(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } return F_none; @@ -50,7 +50,7 @@ extern "C" { #endif // _di_fss_status_code_process_check_ #ifndef _di_fss_status_code_process_number_ - f_status_t fss_status_code_process_number(const fss_status_code_main_t main, const f_string_t value) { + f_status_t fss_status_code_process_number(fss_status_code_main_t * const main, const f_string_t value) { f_status_t status = F_none; @@ -62,13 +62,13 @@ extern "C" { status = fl_conversion_string_to_number_unsigned(value, range, &number); if (status == F_none) { - fl_print_format("%[invalid name%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid name%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return F_status_set_error(F_parameter); } if (status == F_data_not || F_status_set_fine(status) == F_parameter) { - fl_print_format("%[invalid main%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid main%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return status; } @@ -85,10 +85,10 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown name%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown name%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[failed to convert%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[failed to convert%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; @@ -96,19 +96,19 @@ extern "C" { } if (status == F_data) { - fl_print_format("%[unknown code%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown code%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return F_none; } - fl_print_format("%ui%c", main.output.to.stream, code, f_string_eol_s[0]); + fl_print_format("%ui%c", main->output.to.stream, code, f_string_eol_s[0]); return F_none; } #endif // _di_fss_status_code_process_number_ #ifndef _di_fss_status_code_process_normal_ - f_status_t fss_status_code_process_normal(const fss_status_code_main_t main, const f_string_t value) { + f_status_t fss_status_code_process_normal(fss_status_code_main_t * const main, const f_string_t value) { f_number_unsigned_t number = 0; @@ -122,40 +122,40 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown code%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown code%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[failed to convert%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[failed to convert%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; } - fl_print_format("%S%c", main.output.to.stream, string, f_string_eol_s[0]); + fl_print_format("%S%c", main->output.to.stream, string, f_string_eol_s[0]); return F_none; } #endif // _di_fss_status_code_process_normal_ #ifndef _di_fss_status_code_convert_number_ - f_status_t fss_status_code_convert_number(const fss_status_code_main_t main, const f_string_t value, f_number_unsigned_t *number) { + f_status_t fss_status_code_convert_number(fss_status_code_main_t * const main, const f_string_t value, f_number_unsigned_t *number) { const f_string_range_t range = macro_f_string_range_t_initialize(strlen(value)); f_status_t status = fl_conversion_string_to_number_unsigned(value, range, number); if (*number > F_status_size_max_with_signal) { - fl_print_format("%[out of range%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[out of range%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return status; } if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_number_negative) { - fl_print_format("%[out of range%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[out of range%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[invalid number%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid number%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; diff --git a/level_3/fss_status_code/c/private-fss_status_code.h b/level_3/fss_status_code/c/private-fss_status_code.h index 015cbe2..51bb4d2 100644 --- a/level_3/fss_status_code/c/private-fss_status_code.h +++ b/level_3/fss_status_code/c/private-fss_status_code.h @@ -16,7 +16,7 @@ extern "C" { * Perform the 'check' processes, such as --fine or --error. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -34,14 +34,14 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_fss_status_code_process_check_ - extern f_status_t fss_status_code_process_check(const fss_status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_check(fss_status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_check_ /** * Perform the 'number' processes, such as --number. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -56,14 +56,14 @@ extern "C" { * @see fll_fss_status_from_string() */ #ifndef _di_fss_status_code_process_number_ - extern f_status_t fss_status_code_process_number(const fss_status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_number(fss_status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_number_ /** * Perform the normal processes. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -83,14 +83,14 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_fss_status_code_process_normal_ - extern f_status_t fss_status_code_process_normal(const fss_status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_normal(fss_status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_normal_ /** * Convert the value string to the number, reporting any errors. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @param number @@ -111,7 +111,7 @@ extern "C" { * @see fl_console_parameter_to_number_unsigned() */ #ifndef _di_fss_status_code_convert_number_ - extern f_status_t fss_status_code_convert_number(const fss_status_code_main_t main, const f_string_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_convert_number(fss_status_code_main_t * const main, const f_string_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_convert_number_ #ifdef __cplusplus diff --git a/level_3/fss_status_code/data/build/dependencies b/level_3/fss_status_code/data/build/dependencies index 808aad1..bc8b57f 100644 --- a/level_3/fss_status_code/data/build/dependencies +++ b/level_3/fss_status_code/data/build/dependencies @@ -14,6 +14,7 @@ f_file f_fss f_pipe f_print +f_signal fl_console fl_conversion fl_fss diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c index 78024af..858f5c1 100644 --- a/level_3/iki_read/c/iki_read.c +++ b/level_3/iki_read/c/iki_read.c @@ -66,7 +66,8 @@ extern "C" { #endif // _di_iki_read_print_help_ #ifndef _di_iki_read_main_ - f_status_t iki_read_main(const f_console_arguments_t arguments, iki_read_main_t *main) { + f_status_t iki_read_main(iki_read_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -76,7 +77,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { iki_read_parameter_no_color, iki_read_parameter_light, iki_read_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -106,6 +107,7 @@ extern "C" { } iki_read_main_delete(main); + return F_status_set_error(status); } } @@ -122,6 +124,7 @@ extern "C" { fll_error_print(main->error, F_status_set_fine(status), "f_console_parameter_prioritize_right", F_true); iki_read_main_delete(main); + return status; } @@ -154,6 +157,7 @@ extern "C" { iki_read_print_help(main->output.to, main->context); iki_read_main_delete(main); + return F_none; } @@ -161,6 +165,7 @@ extern "C" { fll_program_print_version(main->output.to, iki_read_program_version_s); iki_read_main_delete(main); + return F_none; } @@ -180,14 +185,14 @@ extern "C" { } else if (main->parameters[iki_read_parameter_at].result == f_console_result_additional) { const f_array_length_t index = main->parameters[iki_read_parameter_at].values.array[main->parameters[iki_read_parameter_at].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); f_number_unsigned_t number = 0; - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, F_console_symbol_long_s_enable iki_read_long_at_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, F_console_symbol_long_s_enable iki_read_long_at_s, arguments->argv[index]); status = F_status_set_error(F_parameter); } @@ -226,14 +231,14 @@ extern "C" { } else if (main->parameters[iki_read_parameter_line].result == f_console_result_additional) { const f_array_length_t index = main->parameters[iki_read_parameter_line].values.array[main->parameters[iki_read_parameter_line].values.used - 1]; - const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments.argv[index])); + const f_string_range_t range = macro_f_string_range_t_initialize(strlen(arguments->argv[index])); f_number_unsigned_t number = 0; - status = fl_conversion_string_to_number_unsigned(arguments.argv[index], range, &number); + status = fl_conversion_string_to_number_unsigned(arguments->argv[index], range, &number); if (F_status_is_error(status)) { - fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, F_console_symbol_long_s_enable iki_read_long_line_s, arguments.argv[index]); + fll_error_parameter_integer_print(main->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, F_console_symbol_long_s_enable iki_read_long_line_s, arguments->argv[index]); status = F_status_set_error(F_parameter); } @@ -405,6 +410,7 @@ extern "C" { } iki_read_main_delete(main); + return F_status_set_error(F_parameter); } @@ -419,7 +425,7 @@ extern "C" { fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read", F_true, "-", "process", fll_error_file_type_file); } else { - status = iki_read_process_buffer(arguments, "-", main); + status = iki_read_process_buffer(main, arguments, "-"); } // Clear buffers before continuing. @@ -432,20 +438,26 @@ extern "C" { f_file_t file = f_file_t_initialize; for (; i < main->remaining.used; ++i) { + + if (iki_read_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + macro_f_file_t_reset(file); total = 0; - status = f_file_open(arguments.argv[main->remaining.array[i]], 0, &file); + status = f_file_open(arguments->argv[main->remaining.array[i]], 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[main->remaining.array[i]], "process", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_open", F_true, arguments->argv[main->remaining.array[i]], "process", fll_error_file_type_file); break; } status = f_file_size_by_id(file.id, &total); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments.argv[main->remaining.array[i]], "process", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments->argv[main->remaining.array[i]], "process", fll_error_file_type_file); f_file_stream_close(F_true, &file); break; @@ -462,11 +474,11 @@ extern "C" { f_file_stream_close(F_true, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments.argv[main->remaining.array[i]], "process", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments->argv[main->remaining.array[i]], "process", fll_error_file_type_file); break; } - status = iki_read_process_buffer(arguments, arguments.argv[main->remaining.array[i]], main); + status = iki_read_process_buffer(main, arguments, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status)) break; // Clear buffers before repeating the loop. @@ -485,17 +497,22 @@ extern "C" { // ensure a newline is always put at the end of the program execution, unless in quiet mode. if (main->error.verbosity != f_console_verbosity_quiet) { if (F_status_is_error(status) || !main->mode) { - fll_print_character(f_string_eol_s[0], main->error.to.stream); + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_terminated(f_string_eol_s, main->output.to.stream); } } iki_read_main_delete(main); + return status; } #endif // _di_iki_read_main_ #ifndef _di_iki_read_main_delete_ - f_status_t iki_read_main_delete(iki_read_main_t *main) { + f_status_t iki_read_main_delete(iki_read_main_t * const main) { for (f_array_length_t i = 0; i < iki_read_total_parameters_d; ++i) { diff --git a/level_3/iki_read/c/iki_read.h b/level_3/iki_read/c/iki_read.h index 858c73f..e7c42c3 100644 --- a/level_3/iki_read/c/iki_read.h +++ b/level_3/iki_read/c/iki_read.h @@ -34,6 +34,7 @@ #include #include #include +#include // fll-1 includes #include @@ -202,6 +203,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + uint8_t mode; f_number_unsigned_t at; @@ -222,6 +225,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ 0, \ 0, \ 0, \ @@ -251,10 +255,18 @@ extern "C" { * * Be sure to call iki_read_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -264,7 +276,7 @@ extern "C" { * @see iki_read_main_delete() */ #ifndef _di_iki_read_main_ - extern f_status_t iki_read_main(const f_console_arguments_t arguments, iki_read_main_t *main); + extern f_status_t iki_read_main(iki_read_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_iki_read_main_ /** @@ -273,7 +285,7 @@ extern "C" { * Be sure to call this after executing iki_read_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -283,7 +295,7 @@ extern "C" { * @see iki_read_main() */ #ifndef _di_iki_read_main_delete_ - extern f_status_t iki_read_main_delete(iki_read_main_t *main); + extern f_status_t iki_read_main_delete(iki_read_main_t * const main); #endif // _di_iki_read_main_delete_ #ifdef __cplusplus diff --git a/level_3/iki_read/c/main.c b/level_3/iki_read/c/main.c index d2fb983..5cf5f38 100644 --- a/level_3/iki_read/c/main.c +++ b/level_3/iki_read/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = iki_read_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = iki_read_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/iki_read/c/private-common.c b/level_3/iki_read/c/private-common.c index ea6bcd8..dd4af45 100644 --- a/level_3/iki_read/c/private-common.c +++ b/level_3/iki_read/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_iki_read_print_signal_received_ + void iki_read_print_signal_received(iki_read_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_iki_read_print_signal_received_ + +#ifndef _di_iki_read_signal_received_ + f_status_t iki_read_signal_received(iki_read_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + iki_read_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_iki_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/private-common.h b/level_3/iki_read/c/private-common.h index 0d8304e..9962446 100644 --- a/level_3/iki_read/c/private-common.h +++ b/level_3/iki_read/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define iki_read_common_allocation_small_d 16 #endif // _di_iki_read_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_iki_read_print_signal_received_ + extern void iki_read_print_signal_received(iki_read_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_iki_read_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_iki_read_signal_received_ + extern f_status_t iki_read_signal_received(iki_read_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_iki_read_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/private-iki_read.c b/level_3/iki_read/c/private-iki_read.c index 3bd6b45..ad889f5 100644 --- a/level_3/iki_read/c/private-iki_read.c +++ b/level_3/iki_read/c/private-iki_read.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_iki_read_process_at_ - f_status_t iki_read_process_at(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_string_range_t *range) { + f_status_t iki_read_process_at(iki_read_main_t * const main, const f_string_t file_name, f_string_range_t *range) { if (main->parameters[iki_read_parameter_line].result != f_console_result_additional) { return F_false; @@ -35,7 +35,7 @@ extern "C" { #endif // _di_iki_read_process_at_ #ifndef _di_iki_read_process_buffer_ - f_status_t iki_read_process_buffer(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main) { + f_status_t iki_read_process_buffer(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name) { f_status_t status = F_none; @@ -46,7 +46,7 @@ extern "C" { if (main->parameters[iki_read_parameter_whole].result == f_console_result_found) { f_string_range_t buffer_range = macro_f_string_range_t_initialize(main->buffer.used); - status = iki_read_process_at(arguments, file_name, main, &buffer_range); + status = iki_read_process_at(main, file_name, &buffer_range); if (status == F_true) { if (buffer_range.start > main->buffer.used) { @@ -58,22 +58,22 @@ extern "C" { } if (main->mode == iki_read_mode_content) { - status = iki_read_process_buffer_ranges_whole(arguments, file_name, buffer_range, main, &variable, &vocabulary, &content, &content); + status = iki_read_process_buffer_ranges_whole(main, arguments, file_name, buffer_range, &variable, &vocabulary, &content, &content); } else if (main->mode == iki_read_mode_literal) { - status = iki_read_process_buffer_ranges_whole(arguments, file_name, buffer_range, main, &variable, &vocabulary, &content, &variable); + status = iki_read_process_buffer_ranges_whole(main, arguments, file_name, buffer_range, &variable, &vocabulary, &content, &variable); } else if (main->mode == iki_read_mode_object) { - status = iki_read_process_buffer_ranges_whole(arguments, file_name, buffer_range, main, &variable, &vocabulary, &content, &vocabulary); + status = iki_read_process_buffer_ranges_whole(main, arguments, file_name, buffer_range, &variable, &vocabulary, &content, &vocabulary); } } else if (main->mode == iki_read_mode_total) { - status = iki_read_process_buffer_total(arguments, file_name, main, &variable, &vocabulary, &content); + status = iki_read_process_buffer_total(main, arguments, file_name, &variable, &vocabulary, &content); } else { f_string_range_t buffer_range = macro_f_string_range_t_initialize(main->buffer.used); - status = iki_read_process_at(arguments, file_name, main, &buffer_range); + status = iki_read_process_at(main, file_name, &buffer_range); if (status == F_true) { if (buffer_range.start > main->buffer.used) { @@ -85,26 +85,25 @@ extern "C" { } if (main->mode == iki_read_mode_content) { - status = iki_read_process_buffer_ranges(arguments, file_name, main, &buffer_range, &variable, &vocabulary, &content, &content); + status = iki_read_process_buffer_ranges(main, arguments, file_name, &buffer_range, &variable, &vocabulary, &content, &content); } else if (main->mode == iki_read_mode_literal) { - status = iki_read_process_buffer_ranges(arguments, file_name, main, &buffer_range, &variable, &vocabulary, &content, &variable); + status = iki_read_process_buffer_ranges(main, arguments, file_name, &buffer_range, &variable, &vocabulary, &content, &variable); } else if (main->mode == iki_read_mode_object) { - status = iki_read_process_buffer_ranges(arguments, file_name, main, &buffer_range, &variable, &vocabulary, &content, &vocabulary); + status = iki_read_process_buffer_ranges(main, arguments, file_name, &buffer_range, &variable, &vocabulary, &content, &vocabulary); } } macro_f_iki_variable_t_delete_simple(variable); macro_f_iki_vocabulary_t_delete_simple(vocabulary); macro_f_iki_content_t_delete_simple(content); - return status; } #endif // _di_iki_read_process_buffer_ #ifndef _di_iki_read_process_buffer_ranges_ - f_status_t iki_read_process_buffer_ranges(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_string_range_t *buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) { + f_status_t iki_read_process_buffer_ranges(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_string_range_t *buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) { f_status_t status = F_none; @@ -129,7 +128,7 @@ extern "C" { memset(substitutionss, 0, sizeof(iki_read_substitutions_t) * variable->used); if (main->mode == iki_read_mode_literal || main->mode == iki_read_mode_content) { - status = iki_read_substitutions_identify(arguments, file_name, main, vocabulary, substitutionss); + status = iki_read_substitutions_identify(main, arguments, file_name, vocabulary, substitutionss); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "iki_read_substitutions_identify", F_true); @@ -156,7 +155,7 @@ extern "C" { index = main->parameters[iki_read_parameter_name].values.array[i]; name.used = 0; - status = f_string_append_nulless(arguments.argv[index], strlen(arguments.argv[index]), &name); + status = f_string_append_nulless(arguments->argv[index], strlen(arguments->argv[index]), &name); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "f_string_append_nulless", F_true); @@ -185,7 +184,7 @@ extern "C" { } if (substitutionss[j].used) { - iki_read_substitutions_print(*main, *variable, *content, *ranges, substitutionss[j], j, content_only); + iki_read_substitutions_print(main, *variable, *content, *ranges, substitutionss[j], j, content_only); } else { f_print_dynamic_partial(main->buffer, ranges->array[j], main->output.to.stream); @@ -209,7 +208,7 @@ extern "C" { flockfile(main->output.to.stream); if (substitutionss[main->at].used) { - iki_read_substitutions_print(*main, *variable, *content, *ranges, substitutionss[main->at], main->at, content_only); + iki_read_substitutions_print(main, *variable, *content, *ranges, substitutionss[main->at], main->at, content_only); } else { f_print_dynamic_partial(main->buffer, ranges->array[main->at], main->output.to.stream); @@ -231,7 +230,7 @@ extern "C" { for (f_array_length_t i = 0; i < ranges->used; ++i) { if (substitutionss[i].used) { - iki_read_substitutions_print(*main, *variable, *content, *ranges, substitutionss[i], i, content_only); + iki_read_substitutions_print(main, *variable, *content, *ranges, substitutionss[i], i, content_only); } else { f_print_dynamic_partial(main->buffer, ranges->array[i], main->output.to.stream); @@ -258,7 +257,7 @@ extern "C" { #endif // _di_iki_read_process_buffer_ranges_ #ifndef _di_iki_read_process_buffer_ranges_whole_ - f_status_t iki_read_process_buffer_ranges_whole(const f_console_arguments_t arguments, const f_string_t file_name, const f_string_range_t buffer_range, iki_read_main_t *main, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) { + f_status_t iki_read_process_buffer_ranges_whole(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, const f_string_range_t buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) { f_status_t status = F_none; f_string_range_t range = buffer_range; @@ -288,7 +287,7 @@ extern "C" { memset(substitutionss, 0, sizeof(iki_read_substitutions_t) * variable->used); if (main->mode == iki_read_mode_literal || main->mode == iki_read_mode_content) { - status = iki_read_substitutions_identify(arguments, file_name, main, vocabulary, substitutionss); + status = iki_read_substitutions_identify(main, arguments, file_name, vocabulary, substitutionss); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "iki_read_substitutions_identify", F_true); @@ -317,11 +316,11 @@ extern "C" { for (f_array_length_t index = 0; i < main->parameters[iki_read_parameter_name].values.used; ++i) { index = main->parameters[iki_read_parameter_name].values.array[i]; - length_argument = strnlen(arguments.argv[index], f_console_parameter_size); + length_argument = strnlen(arguments->argv[index], f_console_parameter_size); for (j = 0, name_missed = F_true; j < names.used; ++j) { - status = fl_string_compare(arguments.argv[index], names.array[j].string, length_argument, names.array[j].used); + status = fl_string_compare(arguments->argv[index], names.array[j].string, length_argument, names.array[j].used); if (status == F_equal_to) { name_missed = F_false; @@ -337,7 +336,7 @@ extern "C" { break; } - status = f_string_append_nulless(arguments.argv[index], length_argument, &names.array[names.used]); + status = f_string_append_nulless(arguments->argv[index], length_argument, &names.array[names.used]); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "f_string_append_nulless", F_true); @@ -399,7 +398,7 @@ extern "C" { if (name_missed) { if (substitutionss[j].used) { - iki_read_substitutions_print(*main, *variable, *content, *variable, substitutionss[j], j, F_false); + iki_read_substitutions_print(main, *variable, *content, *variable, substitutionss[j], j, F_false); } else { f_print_dynamic_partial(main->buffer, variable->array[j], main->output.to.stream); @@ -407,7 +406,7 @@ extern "C" { } else { if (substitutionss[j].used) { - iki_read_substitutions_print(*main, *variable, *content, *ranges, substitutionss[j], j, content_only); + iki_read_substitutions_print(main, *variable, *content, *ranges, substitutionss[j], j, content_only); } else { f_print_dynamic_partial(main->buffer, ranges->array[j], main->output.to.stream); @@ -416,7 +415,7 @@ extern "C" { } else { if (substitutionss[j].used) { - iki_read_substitutions_print(*main, *variable, *content, *ranges, substitutionss[j], j, content_only); + iki_read_substitutions_print(main, *variable, *content, *ranges, substitutionss[j], j, content_only); } else { f_print_dynamic_partial(main->buffer, ranges->array[j], main->output.to.stream); @@ -445,12 +444,12 @@ extern "C" { #endif // _di_iki_read_process_buffer_ranges_whole_ #ifndef _di_iki_read_process_buffer_total_ - f_status_t iki_read_process_buffer_total(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content) { + f_status_t iki_read_process_buffer_total(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content) { f_status_t status = F_none; f_string_range_t range = macro_f_string_range_t_initialize(main->buffer.used); - status = iki_read_process_at(arguments, file_name, main, &range); + status = iki_read_process_at(main, file_name, &range); if (status == F_true) { if (range.start > main->buffer.used) { @@ -490,10 +489,16 @@ extern "C" { for (; i < main->parameters[iki_read_parameter_name].values.used; ++i) { + if (iki_read_signal_received(main)) { + macro_f_string_dynamic_t_delete_simple(name); + + return F_status_set_error(F_interrupt); + } + index = main->parameters[iki_read_parameter_name].values.array[i]; name.used = 0; - status = f_string_append_nulless(arguments.argv[index], strlen(arguments.argv[index]), &name); + status = f_string_append_nulless(arguments->argv[index], strlen(arguments->argv[index]), &name); if (F_status_is_error(status)) { fll_error_print(main->error, F_status_set_fine(status), "f_string_append_nulless", F_true); @@ -535,7 +540,7 @@ extern "C" { #endif // _di_iki_read_process_buffer_total_ #ifndef _di_iki_read_substitutions_identify_ - f_status_t iki_read_substitutions_identify(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_iki_vocabulary_t *vocabulary, iki_read_substitutions_t *substitutionss) { + f_status_t iki_read_substitutions_identify(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_iki_vocabulary_t *vocabulary, iki_read_substitutions_t *substitutionss) { if (main->parameters[iki_read_parameter_substitute].result != f_console_result_additional) { return F_none; @@ -556,11 +561,11 @@ extern "C" { for (; i < parameter->values.used; i += 3) { index = parameter->values.array[i]; - length = strnlen(arguments.argv[index], f_console_parameter_size); + length = strnlen(arguments->argv[index], f_console_parameter_size); for (j = 0; j < vocabulary->used; ++j) { - status = fl_string_compare(arguments.argv[index], main->buffer.string + vocabulary->array[j].start, length, (vocabulary->array[j].stop - vocabulary->array[j].start) + 1); + status = fl_string_compare(arguments->argv[index], main->buffer.string + vocabulary->array[j].start, length, (vocabulary->array[j].stop - vocabulary->array[j].start) + 1); if (status == F_equal_to) { macro_f_memory_structure_increment(status, substitutionss[j], 1, F_iki_default_allocation_step_d, macro_iki_read_substitutions_t_resize, F_array_too_large); @@ -568,13 +573,13 @@ extern "C" { index = parameter->values.array[i + 1]; index_2 = substitutionss[j].used; - substitutionss[j].array[index_2].replace.string = arguments.argv[index]; - substitutionss[j].array[index_2].replace.used = strnlen(arguments.argv[index], f_console_parameter_size); + substitutionss[j].array[index_2].replace.string = arguments->argv[index]; + substitutionss[j].array[index_2].replace.used = strnlen(arguments->argv[index], f_console_parameter_size); substitutionss[j].array[index_2].replace.size = substitutionss[j].array[index_2].replace.used; index = parameter->values.array[i + 2]; - substitutionss[j].array[index_2].with.string = arguments.argv[index]; - substitutionss[j].array[index_2].with.used = strnlen(arguments.argv[index], f_console_parameter_size); + substitutionss[j].array[index_2].with.string = arguments->argv[index]; + substitutionss[j].array[index_2].with.used = strnlen(arguments->argv[index], f_console_parameter_size); substitutionss[j].array[index_2].with.size = substitutionss[j].array[index_2].with.used; ++substitutionss[j].used; @@ -587,7 +592,8 @@ extern "C" { #endif // _di_iki_read_substitutions_identify_ #ifndef _di_iki_read_substitutions_print_ - void iki_read_substitutions_print(const iki_read_main_t main, const f_iki_variable_t variable, const f_iki_content_t content, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { + void iki_read_substitutions_print(iki_read_main_t * const main, const f_iki_variable_t variable, const f_iki_content_t content, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { + f_status_t status = F_none; f_array_length_t i = 0; @@ -599,30 +605,30 @@ extern "C" { range.stop = substitutions.array[i].replace.used - 1; - status = fl_string_dynamic_partial_compare(substitutions.array[i].replace, main.buffer, range, content.array[index]); + status = fl_string_dynamic_partial_compare(substitutions.array[i].replace, main->buffer, range, content.array[index]); if (status == F_equal_to) break; } // for if (status == F_equal_to) { if (content_only) { - f_print_dynamic(substitutions.array[i].with, main.output.to.stream); + f_print_dynamic(substitutions.array[i].with, main->output.to.stream); } else { range.start = variable.array[index].start; range.stop = content.array[index].start - 1; - f_print_dynamic_partial(main.buffer, range, main.output.to.stream); + f_print_dynamic_partial(main->buffer, range, main->output.to.stream); - f_print_dynamic(substitutions.array[i].with, main.output.to.stream); + f_print_dynamic(substitutions.array[i].with, main->output.to.stream); range.start = content.array[index].stop + 1; range.stop = variable.array[index].stop; - f_print_dynamic_partial(main.buffer, range, main.output.to.stream); + f_print_dynamic_partial(main->buffer, range, main->output.to.stream); } } else { - f_print_dynamic_partial(main.buffer, ranges.array[index], main.output.to.stream); + f_print_dynamic_partial(main->buffer, ranges.array[index], main->output.to.stream); } } #endif // _di_iki_read_substitutions_print_ diff --git a/level_3/iki_read/c/private-iki_read.h b/level_3/iki_read/c/private-iki_read.h index da7b29f..476369c 100644 --- a/level_3/iki_read/c/private-iki_read.h +++ b/level_3/iki_read/c/private-iki_read.h @@ -18,12 +18,10 @@ extern "C" { * If the --at parameter is not specified in the console arguments, then range is untouched. * The range.start will be greater than main->buffer.used if the --at range is not found before buffer end is reached. * - * @param arguments - * The console arguments passed to the program. + * @param main + * The main program data. * @param file_name * The name of the file being processed. - * @param main - * The main data. * @param range * The range value to represent the --at values. * @@ -35,18 +33,18 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_at_ - extern f_status_t iki_read_process_at(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_string_range_t *range) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_at(iki_read_main_t * const main, const f_string_t file_name, f_string_range_t *range) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_at_ /** * Process a given buffer. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name * The name of the file being processed. - * @param main - * The main data. * * @return * F_none on success. @@ -55,18 +53,18 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_buffer_ - extern f_status_t iki_read_process_buffer(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_buffer(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_buffer_ /** * Process a given buffer, printing the given range. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name * The name of the file being processed. - * @param main - * The main data. * @param buffer_range * The range within the buffer to process. * @param variable @@ -86,7 +84,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_buffer_ranges_ - extern f_status_t iki_read_process_buffer_ranges(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_string_range_t *buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_buffer_ranges(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_string_range_t *buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_buffer_ranges_ /** @@ -94,14 +92,14 @@ extern "C" { * * The entire variable is replaced with the range from the associated ranges. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name * The name of the file being processed. * @param buffer_range * The range within the buffer to process. - * @param main - * The main data. * @param variable * The ranges representing a variable. * @param vocabulary @@ -119,18 +117,18 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_buffer_ranges_whole_ - extern f_status_t iki_read_process_buffer_ranges_whole(const f_console_arguments_t arguments, const f_string_t file_name, const f_string_range_t buffer_range, iki_read_main_t *main, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_buffer_ranges_whole(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, const f_string_range_t buffer_range, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content, f_string_ranges_t *ranges) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_buffer_ranges_whole_ /** * Process a given buffer, printing the total. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name * The name of the file being processed. - * @param main - * The main data. * @param variable * The ranges representing a variable. * @param vocabulary @@ -144,18 +142,18 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_buffer_total_ - extern f_status_t iki_read_process_buffer_total(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_buffer_total(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_iki_variable_t *variable, f_iki_vocabulary_t *vocabulary, f_iki_content_t *content) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_buffer_total_ /** * Process the arguments, associating substitions with a given vocabulary. * + * @param main + * The main program data. * @param arguments * The console arguments passed to the program. * @param file_name * The name of the file being processed. - * @param main - * The main data. * @param vocabulary * The ranges representing a vocabulary. * @param substitutionss @@ -167,14 +165,14 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_substitutions_identify_ - extern f_status_t iki_read_substitutions_identify(const f_console_arguments_t arguments, const f_string_t file_name, iki_read_main_t *main, f_iki_vocabulary_t *vocabulary, iki_read_substitutions_t *substitutionss) F_attribute_visibility_internal_d; + extern f_status_t iki_read_substitutions_identify(iki_read_main_t * const main, const f_console_arguments_t *arguments, const f_string_t file_name, f_iki_vocabulary_t *vocabulary, iki_read_substitutions_t *substitutionss) F_attribute_visibility_internal_d; #endif // _di_iki_read_substitutions_identify_ /** * Print any applicable substition and if there is non then print the given range at the given index. * * @param main - * The main data. + * The main program data. * @param variable * The ranges representing a variable. * @param content @@ -190,7 +188,7 @@ extern "C" { * Set to FALSE to print the entire variable when printing substituted text. */ #ifndef _di_iki_read_substitutions_print_ - extern void iki_read_substitutions_print(const iki_read_main_t main, const f_iki_variable_t variable, const f_iki_content_t content, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; + extern void iki_read_substitutions_print(iki_read_main_t * const main, const f_iki_variable_t variable, const f_iki_content_t content, const f_string_ranges_t ranges, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; #endif // _di_iki_read_substitutions_print_ #ifdef __cplusplus diff --git a/level_3/iki_read/data/build/dependencies b/level_3/iki_read/data/build/dependencies index 285a995..ab4c42e 100644 --- a/level_3/iki_read/data/build/dependencies +++ b/level_3/iki_read/data/build/dependencies @@ -12,6 +12,7 @@ f_file f_iki f_pipe f_print +f_signal fl_console fl_conversion fl_iki diff --git a/level_3/iki_write/c/iki_write.c b/level_3/iki_write/c/iki_write.c index 133a2f1..3a69c7e 100644 --- a/level_3/iki_write/c/iki_write.c +++ b/level_3/iki_write/c/iki_write.c @@ -48,7 +48,7 @@ extern "C" { #endif // _di_iki_write_print_help_ #ifndef _di_iki_write_main_ - f_status_t iki_write_main(const f_console_arguments_t arguments, iki_write_main_t *main) { + f_status_t iki_write_main(iki_write_main_t * const main, const f_console_arguments_t *arguments) { f_status_t status = F_none; @@ -59,7 +59,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { iki_write_parameter_no_color, iki_write_parameter_light, iki_write_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -88,6 +88,7 @@ extern "C" { } iki_write_main_delete(main); + return F_status_set_error(status); } } @@ -135,6 +136,7 @@ extern "C" { iki_write_print_help(main->output.to, main->context); iki_write_main_delete(main); + return F_none; } @@ -142,6 +144,7 @@ extern "C" { fll_program_print_version(main->output.to, iki_write_program_version_s); iki_write_main_delete(main); + return F_none; } @@ -172,10 +175,10 @@ extern "C" { file.id = -1; file.stream = 0; - status = f_file_stream_open(arguments.argv[location], 0, &file); + status = f_file_stream_open(arguments->argv[location], 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file); + fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments->argv[location], "open", fll_error_file_type_file); } } } @@ -295,6 +298,11 @@ extern "C" { for (f_status_t status_pipe = F_none; ; ) { + if (iki_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + if (status_pipe != F_none_eof) { status_pipe = f_file_read(pipe, &buffer); @@ -356,7 +364,7 @@ extern "C" { } } - status = iki_write_process(*main, file, object, content, quote, &escaped); + status = iki_write_process(main, file, object, content, quote, &escaped); if (F_status_is_error(status)) break; fll_print_character(f_string_eol_s[0], file.stream); @@ -408,15 +416,20 @@ extern "C" { for (f_array_length_t i = 0; i < main->parameters[iki_write_parameter_object].values.used; ++i) { - object.string = arguments.argv[main->parameters[iki_write_parameter_object].values.array[i]]; + if (iki_write_signal_received(main)) { + status = F_status_set_error(F_interrupt); + break; + } + + object.string = arguments->argv[main->parameters[iki_write_parameter_object].values.array[i]]; object.used = strnlen(object.string, f_console_parameter_size); object.size = object.used; - content.string = arguments.argv[main->parameters[iki_write_parameter_content].values.array[i]]; + content.string = arguments->argv[main->parameters[iki_write_parameter_content].values.array[i]]; content.used = strnlen(content.string, f_console_parameter_size); content.size = content.used; - status = iki_write_process(*main, file, object, content, quote, &escaped); + status = iki_write_process(main, file, object, content, quote, &escaped); if (F_status_is_error(status)) break; fll_print_character(f_string_eol_s[0], file.stream); @@ -437,20 +450,25 @@ extern "C" { } } - // ensure a newline is always put at the end of the program execution, unless in quiet mode. + // Ensure a newline is always put at the end of the program execution, unless in quiet mode. if (main->error.verbosity != f_console_verbosity_quiet) { if (F_status_is_error(status)) { - fll_print_character(f_string_eol_s[0], main->error.to.stream); + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_character(f_string_eol_s[0], main->output.to.stream); } } iki_write_main_delete(main); + return status; } #endif // _di_iki_write_main_ #ifndef _di_iki_write_main_delete_ - f_status_t iki_write_main_delete(iki_write_main_t *main) { + f_status_t iki_write_main_delete(iki_write_main_t * const main) { for (f_array_length_t i = 0; i < iki_write_total_parameters_d; ++i) { diff --git a/level_3/iki_write/c/iki_write.h b/level_3/iki_write/c/iki_write.h index 03173fd..2682f2e 100644 --- a/level_3/iki_write/c/iki_write.h +++ b/level_3/iki_write/c/iki_write.h @@ -34,6 +34,7 @@ #include #include #include +#include // fll-1 includes #include @@ -137,6 +138,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_string_dynamic_t buffer; f_color_context_t context; @@ -150,6 +153,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_string_dynamic_t_initialize, \ f_color_context_t_initialize, \ } @@ -175,10 +179,18 @@ extern "C" { * * Be sure to call iki_write_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -188,7 +200,7 @@ extern "C" { * @see iki_write_main_delete() */ #ifndef _di_iki_write_main_ - extern f_status_t iki_write_main(const f_console_arguments_t arguments, iki_write_main_t *main); + extern f_status_t iki_write_main(iki_write_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_iki_write_main_ /** @@ -197,7 +209,7 @@ extern "C" { * Be sure to call this after executing iki_write_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -207,7 +219,7 @@ extern "C" { * @see iki_write_main() */ #ifndef _di_iki_write_main_delete_ - extern f_status_t iki_write_main_delete(iki_write_main_t *main); + extern f_status_t iki_write_main_delete(iki_write_main_t * const main); #endif // _di_iki_write_main_delete_ #ifdef __cplusplus diff --git a/level_3/iki_write/c/main.c b/level_3/iki_write/c/main.c index 13590f6..5892694 100644 --- a/level_3/iki_write/c/main.c +++ b/level_3/iki_write/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = iki_write_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = iki_write_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status)) { return 1; } diff --git a/level_3/iki_write/c/private-common.c b/level_3/iki_write/c/private-common.c index f860d81..3eb1880 100644 --- a/level_3/iki_write/c/private-common.c +++ b/level_3/iki_write/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_iki_write_print_signal_received_ + void iki_write_print_signal_received(iki_write_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_iki_write_print_signal_received_ + +#ifndef _di_iki_write_signal_received_ + f_status_t iki_write_signal_received(iki_write_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + iki_write_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_iki_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/private-common.h b/level_3/iki_write/c/private-common.h index da263ec..e2a3d3c 100644 --- a/level_3/iki_write/c/private-common.h +++ b/level_3/iki_write/c/private-common.h @@ -24,6 +24,36 @@ extern "C" { #define iki_write_common_allocation_small_d 16 #endif // _di_iki_write_common_ +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_iki_write_print_signal_received_ + extern void iki_write_print_signal_received(iki_write_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_iki_write_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_iki_write_signal_received_ + extern f_status_t iki_write_signal_received(iki_write_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_iki_write_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/private-iki_write.c b/level_3/iki_write/c/private-iki_write.c index cc4eb1a..c07c395 100644 --- a/level_3/iki_write/c/private-iki_write.c +++ b/level_3/iki_write/c/private-iki_write.c @@ -7,17 +7,17 @@ extern "C" { #endif #ifndef _di_iki_write_process_ - f_status_t iki_write_process(const iki_write_main_t main, const f_file_t output, const f_string_static_t object, const f_string_static_t content, const uint8_t quote, f_string_dynamic_t *escaped) { + f_status_t iki_write_process(iki_write_main_t * const main, const f_file_t output, const f_string_static_t object, const f_string_static_t content, const uint8_t quote, f_string_dynamic_t *escaped) { if (!object.used) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe object is missing, it must not have a length of %]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[0%]", main.error.to.stream, main.error.notable, main.error.notable); - fl_print_format("%[.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe object is missing, it must not have a length of %]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[0%]", main->error.to.stream, main->error.notable, main->error.notable); + fl_print_format("%[.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_status_set_error(F_failure); @@ -26,20 +26,21 @@ extern "C" { f_status_t status = f_iki_object_is(object); if (status == F_false) { - if (main.error.verbosity != f_console_verbosity_quiet) { - flockfile(main.error.to.stream); + if (main->error.verbosity != f_console_verbosity_quiet) { + flockfile(main->error.to.stream); - fl_print_format("%c%[%sThe object '%]", main.error.to.stream, f_string_eol_s[0], main.error.context, main.error.prefix, main.error.context); - fl_print_format("%[%Q%]", main.error.to.stream, main.error.notable, object, main.error.notable); - fl_print_format("%[' is not a valid IKI object.%]%c", main.error.to.stream, main.error.context, main.error.context, f_string_eol_s[0]); + fl_print_format("%c%[%sThe object '%]", main->error.to.stream, f_string_eol_s[0], main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, object, main->error.notable); + fl_print_format("%[' is not a valid IKI object.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); - funlockfile(main.error.to.stream); + funlockfile(main->error.to.stream); } return F_status_set_error(F_failure); } else if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "f_iki_object_is", F_true); + fll_error_print(main->error, F_status_set_fine(status), "f_iki_object_is", F_true); + return F_status_set_error(F_failure); } @@ -48,9 +49,10 @@ extern "C" { status = fll_iki_content_escape(content, quote, escaped); if (F_status_is_error(status)) { - fll_error_print(main.error, F_status_set_fine(status), "fll_iki_content_escape", F_true); + fll_error_print(main->error, F_status_set_fine(status), "fll_iki_content_escape", F_true); macro_f_string_dynamic_t_delete_simple((*escaped)); + return F_status_set_error(F_failure); } diff --git a/level_3/iki_write/c/private-iki_write.h b/level_3/iki_write/c/private-iki_write.h index 576e14a..a987bae 100644 --- a/level_3/iki_write/c/private-iki_write.h +++ b/level_3/iki_write/c/private-iki_write.h @@ -16,7 +16,7 @@ extern "C" { * Process a given object and content, printing the IKI if valid or an error if invalid. * * @param main - * The main data. + * The main program data. * @param output * The file to output to. * @param object @@ -34,7 +34,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_iki_write_process_ - extern f_status_t iki_write_process(const iki_write_main_t main, const f_file_t output, const f_string_static_t object, const f_string_static_t content, const uint8_t quote, f_string_dynamic_t *escaped) F_attribute_visibility_internal_d; + extern f_status_t iki_write_process(iki_write_main_t * const main, const f_file_t output, const f_string_static_t object, const f_string_static_t content, const uint8_t quote, f_string_dynamic_t *escaped) F_attribute_visibility_internal_d; #endif // _di_iki_write_process_ #ifdef __cplusplus diff --git a/level_3/iki_write/data/build/dependencies b/level_3/iki_write/data/build/dependencies index 472223c..3fc06d1 100644 --- a/level_3/iki_write/data/build/dependencies +++ b/level_3/iki_write/data/build/dependencies @@ -11,6 +11,7 @@ f_file f_iki f_pipe f_print +f_signal fl_console fl_iki fl_print diff --git a/level_3/status_code/c/main.c b/level_3/status_code/c/main.c index e757f5a..4775cec 100644 --- a/level_3/status_code/c/main.c +++ b/level_3/status_code/c/main.c @@ -9,17 +9,42 @@ int main(const int argc, const f_string_t *argv) { data.process_pipe = F_true; } - const f_status_t status = status_code_main(arguments, &data); + // Handle signals so that program can cleanly exit, deallocating as appropriate. + { + f_signal_set_empty(&data.signal.set); + f_signal_set_add(F_signal_abort, &data.signal.set); + f_signal_set_add(F_signal_broken_pipe, &data.signal.set); + f_signal_set_add(F_signal_hangup, &data.signal.set); + f_signal_set_add(F_signal_interrupt, &data.signal.set); + f_signal_set_add(F_signal_quit, &data.signal.set); + f_signal_set_add(F_signal_termination, &data.signal.set); + + f_status_t status = f_signal_mask(SIG_BLOCK, &data.signal.set, 0); + + if (F_status_is_error_not(status)) { + status = f_signal_open(&data.signal); + + // If there is an error opening a signal descriptor, then do not handle signals. + if (F_status_is_error(status)) { + f_signal_mask(SIG_UNBLOCK, &data.signal.set, 0); + f_signal_close(&data.signal); + } + } + } + + const f_status_t status = status_code_main(&data, &arguments); - // flush output pipes before closing. + // Flush output pipes before closing. fflush(F_type_output_d); fflush(F_type_error_d); - // close all open file descriptors. + // Close all open file descriptors. close(F_type_descriptor_output_d); close(F_type_descriptor_input_d); close(F_type_descriptor_error_d); + f_signal_close(&data.signal); + if (F_status_is_error(status) || status == F_false) { return 1; } diff --git a/level_3/status_code/c/private-common.c b/level_3/status_code/c/private-common.c index 7540b79..132f650 100644 --- a/level_3/status_code/c/private-common.c +++ b/level_3/status_code/c/private-common.c @@ -5,6 +5,53 @@ extern "C" { #endif +#ifndef _di_status_code_print_signal_received_ + void status_code_print_signal_received(status_code_main_t * const main, const f_status_t signal) { + + if (main->warning.verbosity != f_console_verbosity_verbose) return; + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + fflush(main->warning.to.stream); + + flockfile(main->warning.to.stream); + + fl_print_format("%]%c%c%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s[0], f_string_eol_s[0], main->context.set.warning, main->context.set.warning); + fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); + fl_print_format("%[.%]%c", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s[0]); + + funlockfile(main->warning.to.stream); + } +#endif // _di_status_code_print_signal_received_ + +#ifndef _di_status_code_signal_received_ + f_status_t status_code_signal_received(status_code_main_t * const main) { + + if (!main->signal.id) { + return F_false; + } + + struct signalfd_siginfo information; + + memset(&information, 0, sizeof(struct signalfd_siginfo)); + + if (f_signal_read(main->signal, 0, &information) == F_signal) { + switch (information.ssi_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: + status_code_print_signal_received(main, information.ssi_signo); + + return information.ssi_signo; + } + } + + return F_false; + } +#endif // _di_status_code_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/private-common.h b/level_3/status_code/c/private-common.h index 1b7c102..71f6b3c 100644 --- a/level_3/status_code/c/private-common.h +++ b/level_3/status_code/c/private-common.h @@ -12,6 +12,36 @@ extern "C" { #endif +/** + * Print a message about a process signal being recieved, such as an interrupt signal. + * + * @param main + * The main program data. + * @param signal + * The signal received. + */ +#ifndef _di_status_code_print_signal_received_ + extern void status_code_print_signal_received(status_code_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; +#endif // _di_status_code_print_signal_received_ + +/** + * Check to see if a process signal is received. + * + * Only signals that are blocked via main.signal will be received. + * + * @param main + * The main program data. + * + * @return + * A positive number representing a valid signal on signal received. + * F_false on no signal received. + * + * @see f_signal_read() + */ +#ifndef _di_status_code_signal_received_ + extern f_status_t status_code_signal_received(status_code_main_t * const main) F_attribute_visibility_internal_d; +#endif // _di_status_code_signal_received_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/private-status_code.c b/level_3/status_code/c/private-status_code.c index 67c224f..3218f07 100644 --- a/level_3/status_code/c/private-status_code.c +++ b/level_3/status_code/c/private-status_code.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_status_code_process_check_ - f_status_t status_code_process_check(const status_code_main_t main, const f_string_t value) { + f_status_t status_code_process_check(status_code_main_t * const main, const f_string_t value) { f_number_unsigned_t number = 0; f_status_t status = status_code_convert_number(main, value, &number); @@ -16,35 +16,35 @@ extern "C" { return status; } - if (main.parameters[status_code_parameter_is_error].result == f_console_result_found) { + if (main->parameters[status_code_parameter_is_error].result == f_console_result_found) { if (F_status_is_error(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } - else if (main.parameters[status_code_parameter_is_warning].result == f_console_result_found) { + else if (main->parameters[status_code_parameter_is_warning].result == f_console_result_found) { if (F_status_is_warning(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } - else if (main.parameters[status_code_parameter_is_fine].result == f_console_result_found) { + else if (main->parameters[status_code_parameter_is_fine].result == f_console_result_found) { if (F_status_is_fine(number)) { - f_print_terminated(FL_status_string_true, main.output.to.stream); + f_print_terminated(FL_status_string_true, main->output.to.stream); } else { - f_print_terminated(FL_status_string_false, main.output.to.stream); + f_print_terminated(FL_status_string_false, main->output.to.stream); } - f_print_character(f_string_eol_s[0], main.output.to.stream); + f_print_character(f_string_eol_s[0], main->output.to.stream); } return F_none; @@ -52,7 +52,7 @@ extern "C" { #endif // _di_status_code_process_check_ #ifndef _di_status_code_process_number_ - f_status_t status_code_process_number(const status_code_main_t main, const f_string_t value) { + f_status_t status_code_process_number(status_code_main_t * const main, const f_string_t value) { f_status_t status = F_none; @@ -64,13 +64,13 @@ extern "C" { status = fl_conversion_string_to_number_unsigned(value, range, &number); if (status == F_none) { - fl_print_format("%[invalid name%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid name%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return F_status_set_error(F_parameter); } if (status == F_data_not || F_status_set_fine(status) == F_parameter) { - fl_print_format("%[invalid main%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid main%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return status; } @@ -82,29 +82,29 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown name%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown name%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[failed to convert%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[failed to convert%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; } if (status == F_data) { - fl_print_format("%[unknown code%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown code%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return F_none; } - fl_print_format("%ui%c", main.output.to.stream, code, f_string_eol_s[0]); + fl_print_format("%ui%c", main->output.to.stream, code, f_string_eol_s[0]); return F_none; } #endif // _di_status_code_process_number_ #ifndef _di_status_code_process_normal_ - f_status_t status_code_process_normal(const status_code_main_t main, const f_string_t value) { + f_status_t status_code_process_normal(status_code_main_t * const main, const f_string_t value) { f_number_unsigned_t number = 0; f_status_t status = status_code_convert_number(main, value, &number); @@ -120,40 +120,40 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown code%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[unknown code%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[failed to convert%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[failed to convert%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; } - fl_print_format("%S%c", main.output.to.stream, string, f_string_eol_s[0]); + fl_print_format("%S%c", main->output.to.stream, string, f_string_eol_s[0]); return F_none; } #endif // _di_status_code_process_normal_ #ifndef _di_status_code_convert_number_ - f_status_t status_code_convert_number(const status_code_main_t main, const f_string_t value, f_number_unsigned_t *number) { + f_status_t status_code_convert_number(status_code_main_t * const main, const f_string_t value, f_number_unsigned_t *number) { const f_string_range_t range = macro_f_string_range_t_initialize(strlen(value)); f_status_t status = fl_conversion_string_to_number_unsigned(value, range, number); if (*number > F_status_size_max_with_signal) { - fl_print_format("%[out of range%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[out of range%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); return status; } if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_number_negative) { - fl_print_format("%[out of range%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[out of range%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } else { - fl_print_format("%[invalid number%]%c", main.output.to.stream, main.context.set.error, main.context.set.error, f_string_eol_s[0]); + fl_print_format("%[invalid number%]%c", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s[0]); } return status; diff --git a/level_3/status_code/c/private-status_code.h b/level_3/status_code/c/private-status_code.h index 55c2f64..e499d36 100644 --- a/level_3/status_code/c/private-status_code.h +++ b/level_3/status_code/c/private-status_code.h @@ -16,7 +16,7 @@ extern "C" { * Perform the 'check' processes, such as --fine or --error. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -34,14 +34,14 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_status_code_process_check_ - extern f_status_t status_code_process_check(const status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_check(status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_check_ /** * Perform the 'number' processes, such as --number. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -56,14 +56,14 @@ extern "C" { * @see fll_fss_status_from_string() */ #ifndef _di_status_code_process_number_ - extern f_status_t status_code_process_number(const status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_number(status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_number_ /** * Perform the normal processes. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @@ -83,14 +83,14 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_status_code_process_normal_ - extern f_status_t status_code_process_normal(const status_code_main_t main, const f_string_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_normal(status_code_main_t * const main, const f_string_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_normal_ /** * Convert the value string to the number, reporting any errors. * * @param main - * The main data. + * The main program data. * @param value * The parameter value to process. * @param number @@ -111,7 +111,7 @@ extern "C" { * @see fl_console_parameter_to_number_unsigned() */ #ifndef _di_status_code_convert_number_ - extern f_status_t status_code_convert_number(const status_code_main_t main, const f_string_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t status_code_convert_number(status_code_main_t * const main, const f_string_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_status_code_convert_number_ #ifdef __cplusplus diff --git a/level_3/status_code/c/status_code.c b/level_3/status_code/c/status_code.c index 67c99cf..577225f 100644 --- a/level_3/status_code/c/status_code.c +++ b/level_3/status_code/c/status_code.c @@ -39,7 +39,8 @@ extern "C" { #endif // _di_status_code_print_help_ #ifndef _di_status_code_main_ - f_status_t status_code_main(const f_console_arguments_t arguments, status_code_main_t *main) { + f_status_t status_code_main(status_code_main_t * const main, const f_console_arguments_t *arguments) { + f_status_t status = F_none; { @@ -49,7 +50,7 @@ extern "C" { f_console_parameter_id_t ids[3] = { status_code_parameter_no_color, status_code_parameter_light, status_code_parameter_dark }; const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3); - status = fll_program_parameter_process(arguments, parameters, choices, F_true, &main->remaining, &main->context); + status = fll_program_parameter_process(*arguments, parameters, choices, F_true, &main->remaining, &main->context); main->output.set = &main->context.set; main->error.set = &main->context.set; @@ -73,6 +74,7 @@ extern "C" { if (F_status_is_error(status)) { status_code_main_delete(main); + return F_status_set_error(status); } } @@ -119,6 +121,7 @@ extern "C" { status_code_print_help(main->output.to, main->context); status_code_main_delete(main); + return F_none; } @@ -126,6 +129,7 @@ extern "C" { fll_program_print_version(main->output.to, status_code_progam_version_s); status_code_main_delete(main); + return F_none; } @@ -142,6 +146,7 @@ extern "C" { funlockfile(main->error.to.stream); status_code_main_delete(main); + return F_status_set_error(status); } else if (main->parameters[status_code_parameter_is_fine].result == f_console_result_found) { @@ -156,6 +161,7 @@ extern "C" { funlockfile(main->error.to.stream); status_code_main_delete(main); + return F_status_set_error(status); } } @@ -171,6 +177,7 @@ extern "C" { funlockfile(main->error.to.stream); status_code_main_delete(main); + return F_status_set_error(status); } @@ -178,6 +185,7 @@ extern "C" { fll_print_format("%[You failed to specify a status code.%]%c", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s[0]); status_code_main_delete(main); + return F_status_set_error(F_parameter); } @@ -193,7 +201,12 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = status_code_process_check(*main, arguments.argv[main->remaining.array[i]]); + if (status_code_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + + status2 = status_code_process_check(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -213,7 +226,12 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = status_code_process_number(*main, arguments.argv[main->remaining.array[i]]); + if (status_code_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + + status2 = status_code_process_number(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -233,7 +251,12 @@ extern "C" { for (f_array_length_t i = 0; i < main->remaining.used; ++i) { - status2 = status_code_process_normal(*main, arguments.argv[main->remaining.array[i]]); + if (status_code_signal_received(main)) { + status = F_status_set_error(F_signal); + break; + } + + status2 = status_code_process_normal(main, arguments->argv[main->remaining.array[i]]); if (F_status_is_error(status2) && status == F_none) { status = status2; @@ -244,13 +267,22 @@ extern "C" { } } + if (main->error.verbosity != f_console_verbosity_quiet) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + + fll_print_terminated(f_string_eol_s, main->output.to.stream); + } + } + status_code_main_delete(main); + return status; } #endif // _di_status_code_main_ #ifndef _di_status_code_main_delete_ - f_status_t status_code_main_delete(status_code_main_t *main) { + f_status_t status_code_main_delete(status_code_main_t * const main) { for (f_array_length_t i = 0; i < status_code_total_parameters_d; ++i) { diff --git a/level_3/status_code/c/status_code.h b/level_3/status_code/c/status_code.h index 8f93ee3..f73c768 100644 --- a/level_3/status_code/c/status_code.h +++ b/level_3/status_code/c/status_code.h @@ -26,6 +26,7 @@ #include #include #include +#include // fll-1 includes #include @@ -124,6 +125,8 @@ extern "C" { fl_print_t error; fl_print_t warning; + f_signal_t signal; + f_color_context_t context; } status_code_main_t; @@ -135,6 +138,7 @@ extern "C" { fl_print_t_initialize, \ macro_fl_print_t_initialize_error(), \ macro_fl_print_t_initialize_warning(), \ + f_signal_t_initialize, \ f_color_context_t_initialize, \ } #endif // _di_status_code_main_t_ @@ -159,10 +163,18 @@ extern "C" { * * Be sure to call status_code_main_delete() after executing this. * + * 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. * @param arguments * The parameters passed to the process. - * @param main - * The main data. * * @return * F_none on success. @@ -172,7 +184,7 @@ extern "C" { * @see status_code_main_delete() */ #ifndef _di_status_code_main_ - extern f_status_t status_code_main(const f_console_arguments_t arguments, status_code_main_t *main); + extern f_status_t status_code_main(status_code_main_t * const main, const f_console_arguments_t *arguments); #endif // _di_status_code_main_ /** @@ -181,7 +193,7 @@ extern "C" { * Be sure to call this after executing status_code_main(). * * @param main - * The main data. + * The main program data. * * @return * F_none on success. @@ -191,7 +203,7 @@ extern "C" { * @see status_code_main() */ #ifndef _di_status_code_main_delete_ - extern f_status_t status_code_main_delete(status_code_main_t *main); + extern f_status_t status_code_main_delete(status_code_main_t * const main); #endif // _di_status_code_main_delete_ #ifdef __cplusplus diff --git a/level_3/status_code/data/build/dependencies b/level_3/status_code/data/build/dependencies index 4ad511e..6238cab 100644 --- a/level_3/status_code/data/build/dependencies +++ b/level_3/status_code/data/build/dependencies @@ -11,6 +11,7 @@ f_conversion f_file f_pipe f_print +f_signal fl_console fl_conversion fl_print -- 1.8.3.1