]> Kevux Git Server - fll/commitdiff
Update: Signal related updates, consistency improvements, and miscellaneous code...
authorKevin Day <thekevinday@gmail.com>
Fri, 12 Nov 2021 05:04:37 +0000 (23:04 -0600)
committerKevin Day <thekevinday@gmail.com>
Fri, 12 Nov 2021 05:16:40 +0000 (23:16 -0600)
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.

183 files changed:
level_0/f_signal/c/signal.c
level_0/f_signal/c/signal.h
level_1/fl_print/c/private-print.c
level_1/fl_signal/c/signal.c
level_3/byte_dump/c/byte_dump.c
level_3/byte_dump/c/byte_dump.h
level_3/byte_dump/c/main.c
level_3/byte_dump/c/private-byte_dump.c
level_3/byte_dump/c/private-byte_dump.h
level_3/byte_dump/c/private-common.c
level_3/byte_dump/c/private-common.h
level_3/byte_dump/data/build/dependencies
level_3/control/c/control.c
level_3/control/c/control.h
level_3/control/c/main.c
level_3/control/c/private-common.c
level_3/control/c/private-common.h
level_3/control/data/build/dependencies
level_3/controller/c/controller.c
level_3/controller/c/controller.h
level_3/controller/c/main.c
level_3/controller/c/private-common.c
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.h
level_3/controller/c/private-controller_print.c
level_3/controller/c/private-controller_print.h
level_3/controller/c/private-entry.c
level_3/controller/c/private-lock.c
level_3/controller/c/private-lock.h
level_3/controller/c/private-lock_print.c
level_3/controller/c/private-lock_print.h
level_3/controller/c/private-process.c
level_3/controller/c/private-process.h
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/c/private-thread.c
level_3/controller/c/private-thread.h
level_3/controller/c/private-thread_entry.c
level_3/fake/c/fake.c
level_3/fake/c/fake.h
level_3/fake/c/main.c
level_3/fake/c/private-build.c
level_3/fake/c/private-build.h
level_3/fake/c/private-clean.c
level_3/fake/c/private-clean.h
level_3/fake/c/private-common.c
level_3/fake/c/private-common.h
level_3/fake/c/private-fake.c
level_3/fake/c/private-fake.h
level_3/fake/c/private-make.c
level_3/fake/c/private-make.h
level_3/fake/c/private-print.c
level_3/fake/c/private-print.h
level_3/fake/c/private-skeleton.c
level_3/fake/c/private-skeleton.h
level_3/firewall/c/firewall.c
level_3/firewall/c/firewall.h
level_3/firewall/c/main.c
level_3/firewall/c/private-common.c
level_3/firewall/c/private-common.h
level_3/firewall/c/private-firewall.c
level_3/firewall/c/private-firewall.h
level_3/firewall/data/build/dependencies
level_3/fss_basic_list_read/c/fss_basic_list_read.c
level_3/fss_basic_list_read/c/fss_basic_list_read.h
level_3/fss_basic_list_read/c/main.c
level_3/fss_basic_list_read/c/private-common.c
level_3/fss_basic_list_read/c/private-common.h
level_3/fss_basic_list_read/c/private-fss_basic_list_read.c
level_3/fss_basic_list_read/c/private-fss_basic_list_read.h
level_3/fss_basic_list_read/data/build/dependencies
level_3/fss_basic_list_write/c/fss_basic_list_write.c
level_3/fss_basic_list_write/c/fss_basic_list_write.h
level_3/fss_basic_list_write/c/main.c
level_3/fss_basic_list_write/c/private-common.c
level_3/fss_basic_list_write/c/private-common.h
level_3/fss_basic_list_write/c/private-fss_basic_list_write.c
level_3/fss_basic_list_write/c/private-fss_basic_list_write.h
level_3/fss_basic_list_write/data/build/dependencies
level_3/fss_basic_read/c/fss_basic_read.c
level_3/fss_basic_read/c/fss_basic_read.h
level_3/fss_basic_read/c/main.c
level_3/fss_basic_read/c/private-common.c
level_3/fss_basic_read/c/private-common.h
level_3/fss_basic_read/c/private-fss_basic_read.c
level_3/fss_basic_read/c/private-fss_basic_read.h
level_3/fss_basic_read/data/build/dependencies
level_3/fss_basic_write/c/fss_basic_write.c
level_3/fss_basic_write/c/fss_basic_write.h
level_3/fss_basic_write/c/main.c
level_3/fss_basic_write/c/private-common.c
level_3/fss_basic_write/c/private-common.h
level_3/fss_basic_write/c/private-fss_basic_write.c
level_3/fss_basic_write/c/private-fss_basic_write.h
level_3/fss_basic_write/data/build/dependencies
level_3/fss_embedded_list_read/c/fss_embedded_list_read.c
level_3/fss_embedded_list_read/c/fss_embedded_list_read.h
level_3/fss_embedded_list_read/c/main.c
level_3/fss_embedded_list_read/c/private-common.c
level_3/fss_embedded_list_read/c/private-common.h
level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c
level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h
level_3/fss_embedded_list_read/data/build/dependencies
level_3/fss_embedded_list_write/c/fss_embedded_list_write.c
level_3/fss_embedded_list_write/c/fss_embedded_list_write.h
level_3/fss_embedded_list_write/c/main.c
level_3/fss_embedded_list_write/c/private-common.c
level_3/fss_embedded_list_write/c/private-common.h
level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c
level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h
level_3/fss_embedded_list_write/data/build/dependencies
level_3/fss_extended_list_read/c/fss_extended_list_read.c
level_3/fss_extended_list_read/c/fss_extended_list_read.h
level_3/fss_extended_list_read/c/main.c
level_3/fss_extended_list_read/c/private-common.c
level_3/fss_extended_list_read/c/private-common.h
level_3/fss_extended_list_read/c/private-fss_extended_list_read.c
level_3/fss_extended_list_read/c/private-fss_extended_list_read.h
level_3/fss_extended_list_read/data/build/dependencies
level_3/fss_extended_list_write/c/fss_extended_list_write.c
level_3/fss_extended_list_write/c/fss_extended_list_write.h
level_3/fss_extended_list_write/c/main.c
level_3/fss_extended_list_write/c/private-common.c
level_3/fss_extended_list_write/c/private-common.h
level_3/fss_extended_list_write/c/private-fss_extended_list_write.c
level_3/fss_extended_list_write/c/private-fss_extended_list_write.h
level_3/fss_extended_list_write/data/build/dependencies
level_3/fss_extended_read/c/fss_extended_read.c
level_3/fss_extended_read/c/fss_extended_read.h
level_3/fss_extended_read/c/main.c
level_3/fss_extended_read/c/private-common.c
level_3/fss_extended_read/c/private-common.h
level_3/fss_extended_read/c/private-fss_extended_read.c
level_3/fss_extended_read/c/private-fss_extended_read.h
level_3/fss_extended_read/data/build/dependencies
level_3/fss_extended_write/c/fss_extended_write.c
level_3/fss_extended_write/c/fss_extended_write.h
level_3/fss_extended_write/c/main.c
level_3/fss_extended_write/c/private-common.c
level_3/fss_extended_write/c/private-common.h
level_3/fss_extended_write/c/private-fss_extended_write.c
level_3/fss_extended_write/c/private-fss_extended_write.h
level_3/fss_extended_write/data/build/dependencies
level_3/fss_identify/c/fss_identify.c
level_3/fss_identify/c/fss_identify.h
level_3/fss_identify/c/main.c
level_3/fss_identify/c/private-common.c
level_3/fss_identify/c/private-common.h
level_3/fss_identify/c/private-fss_identify.c
level_3/fss_identify/c/private-fss_identify.h
level_3/fss_identify/data/build/dependencies
level_3/fss_status_code/c/fss_status_code.c
level_3/fss_status_code/c/fss_status_code.h
level_3/fss_status_code/c/main.c
level_3/fss_status_code/c/private-common.c
level_3/fss_status_code/c/private-common.h
level_3/fss_status_code/c/private-fss_status_code.c
level_3/fss_status_code/c/private-fss_status_code.h
level_3/fss_status_code/data/build/dependencies
level_3/iki_read/c/iki_read.c
level_3/iki_read/c/iki_read.h
level_3/iki_read/c/main.c
level_3/iki_read/c/private-common.c
level_3/iki_read/c/private-common.h
level_3/iki_read/c/private-iki_read.c
level_3/iki_read/c/private-iki_read.h
level_3/iki_read/data/build/dependencies
level_3/iki_write/c/iki_write.c
level_3/iki_write/c/iki_write.h
level_3/iki_write/c/main.c
level_3/iki_write/c/private-common.c
level_3/iki_write/c/private-common.h
level_3/iki_write/c/private-iki_write.c
level_3/iki_write/c/private-iki_write.h
level_3/iki_write/data/build/dependencies
level_3/status_code/c/main.c
level_3/status_code/c/private-common.c
level_3/status_code/c/private-common.h
level_3/status_code/c/private-status_code.c
level_3/status_code/c/private-status_code.h
level_3/status_code/c/status_code.c
level_3/status_code/c/status_code.h
level_3/status_code/data/build/dependencies

index d046c87fa2d925c45d01f3392aa07712343421db..0bdeb856d39df9f69b14eb4dec666c26288c49cb 100644 (file)
@@ -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);
index 98003cff4c93a3e3b0c588946e81c85f73871d17..cb0c19801213527311375bb8d276cea73dd65fce 100644 (file)
@@ -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_
 
 /**
index dc5353958dbac7e12c1e6366624a51345e2f139e..d8dbd3b53e103536fdda89289bc32021dafe35c0 100644 (file)
@@ -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) {
index e83164709995dbcce8395240cd46254a422a2dc6..f0a81a62bed7ef8a6db1138771d2a43f994d82b6 100644 (file)
@@ -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]) {
index 57bca1dbb59b539d32522b7dcd4e819542f27806..95985e1c2038eeeca89431c14476feb393cdc4b0 100644 (file)
@@ -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;
   }
index 5c2f7389f90af5d5a78a7292481b711511e3c97d..3df9f94beec4ad25b0353cdfa37f6c28b14672fc 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 2e16cbdcfd5eccd6c1445ad6d356cd25d3b1f034..9389a8989d847e0288c57b3d29e017c2eca9617b 100644 (file)
@@ -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;
   }
index f0399c38bd94aba94d20b60669df4a75843efee5..0291150d430de560ef636c6f07b1fc9fff75e8da 100644 (file)
@@ -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_
 
index 0a083093dd63f081e79fa6af0d9f2a4c0b4fb19a..8e434b6ce553dba4a427d65c96a83f99e5151bd7 100644 (file)
@@ -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
index 820be9031957c1b49c779545c20abb52682caebe..15a0a169e57a7963f0829add43adb10df04cdb8c 100644 (file)
@@ -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
index 6604c7ef307940933f53ceac73f83fe34a0db824..9200a5b5082921d90787b69514eda9d8dc720a43 100644 (file)
@@ -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
index f48f7f0a7b0d4667d76540c67b65de46a875c9ab..fa075534070aea21727be3fcc1013b9429cf073b 100644 (file)
@@ -11,6 +11,7 @@ f_conversion
 f_file
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_print
index eafccdf5a69806a1bd01e3e063a6a91af523c054..a4c18eb36d193925fe2427bdeafd88ea338272e2 100644 (file)
@@ -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) {
 
index d07caaf7278002ddbe3997f687411cbdeb4b8a0d..c78da9d440f2dba6a6964c2384f0d607658548eb 100644 (file)
@@ -27,6 +27,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 8976711dfd1b28ae08ee37e34c6901557be56c81..4d2c962d439e8ae1eb2bf8fbfa2924d43e63b118 100644 (file)
@@ -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;
   }
index d8697886a9cdfb3ae12586673f94eb149853dc82..92941dab70a022a66191b661edbe843e0bc4bea3 100644 (file)
@@ -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
index 58879a3c111d7c9c97a5ba6d8b49dab0a08f14bd..00ae16052870c8c659fca8c26d55cb667d0d2d08 100644 (file)
 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
index 95b9fce41301c416eebe32c05195022300198bfa..7eeec9a6803538ee27b96dcd47e3b113cf317b00 100644 (file)
@@ -10,6 +10,7 @@ f_console
 f_file
 f_pipe
 f_print
+f_signal
 fl_console
 fl_print
 fl_string
index 145045d6ef051c88be0f76f246b8cc3dc08997eb..e4f46bb39810a6626b123b195b82cc0eb2fbf330 100644 (file)
@@ -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) {
 
index ec535d50040d7952aabea003abfe7dc51fae6f89..bfe398c79f7bb565217f3ebd07ca428caa5a728f 100644 (file)
@@ -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
index 352d08ea12a417c3a663158d9aa456bfba445c24..d82171efbe174c2ec1e9c6d53b7348dde39b92d2 100644 (file)
@@ -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;
index 1fa0ada6ba8f35e57e0df7a937120494ca1cb979..26d2d25a432f7dc8467bc28684d586d754e007ac 100644 (file)
@@ -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);
index 8fd7e5a544f70560d4437a9441e54aef2f7fa331..2d1b1949928c7eeed20340d597ef4552ad837bd7 100644 (file)
@@ -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
index 75c4ca82acaa1d672f1c934ccc2b20d56ece21b5..76b02c5b48cf3ccb450939e6f621403d20231412 100644 (file)
@@ -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
index 546e10e3f7dbc715497b00ce50667a8bab869425..2615b1eb3be075527d4be7e11e6d3ffa4ebfee97 100644 (file)
@@ -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
index 78365f018fb794a313398b3891d5713b6a1a188c..0a0bf088ca8968ed232985d68ed18d40da20850d 100644 (file)
@@ -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
index 120215f4788c156ee487a1db535546f845db0e48..aa5098b8b367b17d6398de4cb138e8ae9dd42205 100644 (file)
@@ -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];
index a4d06b010ead1ce2294a237e83fa2af29ea8bc72..8ff399d23328d282fb5f669835fe43d1f621940d 100644 (file)
@@ -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 {
index 27fb83bc755f53d43e8012d4aef53a37cbdaabcf..cb17fe4dd61e3af56dc1de894a505a6570ef0d27 100644 (file)
@@ -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().
index 21115219fc99e371b5b71fb17501b552c3c7ce66..4f78afdbab7ce8ac4b660a64a6395534d8c0ca3c 100644 (file)
@@ -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);
index 1c7645cb9df48037c404adc00fcb0a744483114a..c0e0410459bef52c477f8c29c9e5815742463906 100644 (file)
@@ -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.
index d5bb3dd130ec9937642d2863f5160399b8cc92a6..5f9dfc92aba9d1dd6a3c42de856e1183fa636e08 100644 (file)
@@ -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) {
index 795dd1acbc1947e368863445dc29f2e10604b21c..c4345f4cd7bd3f8e5f235ba8dd2ea7fe1ea2db15 100644 (file)
@@ -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().
  *
index ebce3ff90903bf4b1ec62ca4be5379c238076edc..ab11d7d788a11c114c20444c06f88e415bb1c4a8 100644 (file)
@@ -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;
     }
 
index fa2f4e499fc3c73928aaf671b154e60ce1d70935..23ae316bb7317fb9a4176edbc059964a4be4ce35 100644 (file)
@@ -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().
index f37db1715c23b2acb37569036d1b1f226dd88037..f0df2a80c64fc301d32412ebcfba5f42a5c9123b 100644 (file)
@@ -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;
index f297e1fbf2ddb8080d42efeb1a922a140ef9e03a..713c3435920966d9f84ec7dbf25f1a410356691b 100644 (file)
@@ -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;
index 21a38d7164e869475bdc375859d9ea348ca3c170..e196952274db86709c1e54e4e7cf89dbece49b04 100644 (file)
@@ -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) {
index 3b510e74817dc71fea6a72ebbd1870c67e728219..e4cb8ae4a0ffe47856463e51e7de824f446a2e6e 100644 (file)
@@ -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);
index 2ef527eb293d692f294df993c454c223bbfc3343..d081bdec67ff9588f8adba23a09bfc5a55a791eb 100644 (file)
@@ -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
index cae110fec17c8c0950604c7c67bbac2f56d75f4e..6ae536676f55581b9abc62a9b4a100b874f79852 100644 (file)
@@ -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);
index 86fa951d843221437de8cfba750f0fe0f791bfb1..18e9b1a6f9ea4048a174af6c3904c3d171b644d7 100644 (file)
@@ -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_
index c8f8025b991f2d53a2882717320c15bf0ec6b3fe..92fe6661d19085bfd139853d99aad6f90185c8ef 100644 (file)
@@ -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
index 974ce9907076b3c6f8efd36d293088d33f251cc0..294856aae317eade19b1ef108ec13ffdec463976 100644 (file)
@@ -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;
     }
index df483b39bcd486738b2ef3c0b9325d7e905c1688..69eb65f34789b7d8691951b03c4bfd5fdfec005e 100644 (file)
@@ -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_
 
 /**
index b6c8072ccf652f0b5f94a17bd3249ecc7b8d0e8c..1a537852bc298f2773eb91ceb25d127bf26d9533 100644 (file)
@@ -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
index 15d34558e2058a10fac33af735474dc758cd9fd3..e15d01abb7264257513330319840dbea510d7656 100644 (file)
@@ -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
index 8b2b7353b2ebc50aa353234500b063c97084e44b..d50cdd80519ec39552a2802b2ab022b415ab0e73 100644 (file)
@@ -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, &parameter, 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);
       }
index 47844d9459fa35cc0aefbe7d2a13e5b5bccf996b..fdfd5a58f25d561f0073dfd862ccd424e83a1fc8 100644 (file)
@@ -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_
 
 /**
index 6433a2ca269da7d23a68309e3c686bc9534a9024..478a084fe9a6f255ba673ea6d0ec8a16c9bfdb25 100644 (file)
@@ -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, &section_stack, &status);
+      const int result = fake_make_operate_section(main, data_make.main, &data_make, &section_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, &parameter, 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;
 
index 34671bca87df983425aa01518e284838efee866e..53da9e7a2558bfcfb1b41625aa8e747d2804ab83 100644 (file)
@@ -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
index c5b1b289c8b5f280c32051665a54561e77cca871..fdfea528eed455e846e35e7feb3c67af54433ecf 100644 (file)
@@ -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_
 
index 77d9204ab9c877d45df9c80defd5a496161ecd0f..d385b9a0d10c87c65ddd327a3e37eff4b955458f 100644 (file)
@@ -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
index 4c138fccfb6737c494d8b417c1e450a75f4649e4..1a05d665979f5632c80111c53e9e06164cde4edf 100644 (file)
@@ -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;
     }
index c56ede7c5d7a507e03b63ac931d19bb74b7a1a85..b28af741f3d05a220b8a96835c7683d57c39d2a2 100644 (file)
@@ -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
index 53f8df02718b5940118e0ba3bd9cef8998067726..aba852ec2ddb455c66841d32c6c01891e0aeabdf 100644 (file)
@@ -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) {
 
index 7cfc095cb417cf30e246740c6dfbf7c6a9282229..c4e263d5ab5ed4b3f0bd0786c6b2fcfbb23506f2 100644 (file)
@@ -31,6 +31,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 6b3f60bdc10f65153ada8d27ed81438763ac7065..2d0568f99dc69040e2fb0c99ca0d8623009a547c 100644 (file)
@@ -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;
   }
 
index 1104364620524835e4fec65a31138fdf74045861..07a4227ad55ce2be3da4de9fb3a8802652455a85 100644 (file)
@@ -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
index 8b250ed2a239c39cd4fa8985a2d265d03cb72148..8b3327b71a9bb6f1af01ce060c40eb502aa80931 100644 (file)
@@ -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
index c67abb3434af46f4ebbce98f18cc501c8a2eae7d..7f94ce613c6495da956809958a84e36a5f47dcc4 100644 (file)
@@ -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;
index 2fe49f19b200a577d284dd04e651be2419ff5112..f9bf05a92dade668454bcf2b02e1e78aa040394c 100644 (file)
@@ -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"
index 590d654f449758b02dc5aa2ef8792e16feec2414..c5cb46bfbbca88f35e4c83919895c76dfcfe15ca 100644 (file)
@@ -19,6 +19,7 @@ f_fss
 f_path
 f_pipe
 f_print
+f_signal
 fl_console
 fl_control_group
 fl_conversion
index 00d2167d52944f5966eed97bc3ca0ba1ffc9314d..67822a33f7120e52ce3945aaecb83733c3a3cb40 100644 (file)
@@ -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) {
 
index c7dc94254fb0461ca8d1050e3203bd16ec3f86ca..b38bb54392b80f690f8e021ad3337dcae813caa6 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 236fc472713f4ed4aabaa7c6c09e181cbb357372..80d3a03b39ca659d4c169bc8a2f5b60ca59b21d5 100644 (file)
@@ -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;
   }
index ed0361e2eaff43878de9df5e47b97e29aaf8d262..aa8bfbb72e81815f52a1f3b81dfbad3164d6c412 100644 (file)
@@ -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
index b17a52bd946fd8e45b25ee17ca8896e1d4e1eee9..2378dda8d77d373c8a47ecfaac1252b4418e4f50 100644 (file)
@@ -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
index a309dcab0d0a1e78aa81a6d9f3e7ff00da10c6b1..8a565f5a6cbf812ac03d6a72d9446a4ed2b1bb15 100644 (file)
@@ -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;
       }
index 8fdc38ba60da9d2a734d08651a16be655dcf483f..f5544b7d5582b50af604001af74571eaddc09e75 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index bc0acc80aee97ab205e16773f1c88224df7929ea..6e97da5aa278b5e67d45246c094abc65d2c968c4 100644 (file)
@@ -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) {
 
index 1b02e890fa660bd2640f062f37b2a4da5a25e88d..b0d031b897e54415eab763dc35f9d6bf03d58f57 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 9c53f816739e533afc6f04ea076aa3ef9434f542..28f7cf64410befb681dec7504144075b708fb4bd 100644 (file)
@@ -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;
   }
index 19754919242208ed1bfda68152dfa5f8108aee05..5cea2285783f76fabef64d423415084241ebe2e3 100644 (file)
@@ -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
index 2f8c5981ce1c1c15ac8dcf3fee9f3879ca3dc63a..42499d3cfe4f4bd18213bf53bf9fa875d1be0587 100644 (file)
@@ -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
index 90f1d769e3ecc12596e6730476f6af7a4e9fde8d..ce64de56b6179c3e553e2c8029aa30f0deb4638a 100644 (file)
@@ -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_
index de4156cc63d62f1c5fe8ad2eff53fef8aaadbc01..f350c6a08a51dced6f3d2bd983c9fd6e27b8dae7 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index ad237e46b44c1394afff56a79ea5fdd3d717d5db..ca8ac6d443da09d20ab78ecc13572b006eaae5da 100644 (file)
@@ -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) {
 
index f808cc5e74d22b9db69f1eb1890e437c7fc2b836..204f060e7ca88a17990fa16ef40ee6b255282bf9 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index eac565f1979c417e2db5898d32dac4df6b41a877..56d401dd7e465ceb4537ffa9d8eb68052d54c0e0 100644 (file)
@@ -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;
   }
index fc3c4b71fd698a3d2cb736db7e1acedc1bcd7ee3..26d9f3befe217d217ac00068b30e9bc180829649 100644 (file)
@@ -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
index b769cdc8e44dea09f4966e6ae69f36a47d28f329..4e64856f834ecaa664ed587ef0ee3e08d5508688 100644 (file)
@@ -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
index 9584e55aadb199bcdc5615ec1e039adb02616a21..0e8ec27cf95d105d64b054291698cac582f3cf20 100644 (file)
@@ -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;
index 5c1f896e0ad0860c00fb16450db9527037f8de57..bc7d85876d39b9cd6126e28dc76cadd41b760d25 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 4218e5cb2fb661ccc22f079b44bc537f683f546b..0bad5fc4b5f985ccf9e3e6e6724a990c01aef9ba 100644 (file)
@@ -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) {
 
index b2609be22475aa75094382c0151c5954e9164d61..3a3df385ebd5b476adf5d75d51eae6c3e828abe7 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 97f1f005d062a95bfd40aae04e8e50c9d2d8fab1..1e8da75b3469865e12d05760c2ebfa3ce7efb2d8 100644 (file)
@@ -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;
   }
index d1c0ac4f2bdbfcf279796f087988b4ebadb9d7e0..66cad09c4179b80f9d17654d288f3b273cd8793f 100644 (file)
@@ -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
index e583676e7b4911d7885bee095aa16e1de291d984..3fa1f5a276d2c1ef6950686849f0271ab4c2e907 100644 (file)
@@ -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
index f9abab2a50cfd2666a6060dcfc7c37ce77b7cf4e..09808373bd7da1f274ebd5da5e49590fc97fd7dd 100644 (file)
@@ -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_
index 72bd3ef1d4aad2f7cc7f4a3db9430f43389c60f5..f27e70264c9365970a820e1952b6195ec650ede5 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 9cfcd54299552a4434e5420b8b6c6027b1e884a1..10217636e46a0737e5b1322836cf814d941ce787 100644 (file)
@@ -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) {
 
index 6eb8a95e8e264934706a6bb36cb2e875bed73acf..82ab44aecfe888385b18a0e4344a70588a2e7fbd 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index a874c211628c695cf7be799905ac5321d612ba4f..37877e95b9d56b97b918acde0ce70a2d990f5a07 100644 (file)
@@ -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;
   }
index d62fdfaf04e8c3fa6edec6ec0355e5459e8e43b3..68cb82a09404e22761ba822415e5a05a1154aadb 100644 (file)
@@ -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
index 4ce89d9910057347842310b21387846f7020e79f..d410fd0da611419ff70bba8ca25a0719089a9628 100644 (file)
@@ -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
index d41b0b59bcdde4a8cf169bcd3e0e9ed19992075c..b79a1af18ba6b25df696e1c0e79882881ddbe98e 100644 (file)
@@ -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) {
 
index a16a73220404ab295dcd01d9a4f33d7552e070b0..c63047dc2e11a5251d25cd32a90d14bcf3e02458 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 3c49f4b9034a20d6553907438896c7a1bb2a7477..1541118eed012cd3a585f54ea84ab329a23f4a41 100644 (file)
@@ -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) {
 
index 8bc527ea7632bae3152ff761ff9d66be25485c62..3fd24b810bce48e39498032ed46444dd18310160 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 6f25d2816f20e9c3014c03abf48bfe9258676723..bba3014c4f3ba84e56da7f7a1d046ddbf13ebd85 100644 (file)
@@ -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;
   }
index 16c4cbb6d18c45410d811255b3fdd40ea65c696a..c90e4f9ce47726ff001d03c4ed6952f8de962aab 100644 (file)
@@ -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
index 8029fb0e5ef768a3e575509ede621c0b5694b5dc..42f18a881b07c869fbfce1621779d1b3dcec1570 100644 (file)
@@ -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
index 66ee7338131a6e2b3a90b9056202bc16b2d1a6ad..0e391a358ad65384e7b3cad613f1173cf251635e 100644 (file)
@@ -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;
       }
index f6ce36a85c26a18b3d1f2045ac3c5c31c0371fed..376c9cd0d9f6b14dd52cce3aca4097d5bc6ba287 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 37d5b504a8e21fddf080838b21eca8a440c34194..f1ba25947406b40f427be04b619b325bdb082feb 100644 (file)
@@ -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);
 
index c4474781fff8b0657f298eda75d28a6ff55c9172..514922437d832537f1c65265220853422f7dbff8 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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.
index 77ef1601311804a5dbcdce77da5c32494798235f..9abf61049735b50e90b289884a1832185d5d61e5 100644 (file)
@@ -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;
   }
index 2261f10b64fc7becf1f1bd80bcd5861ba5a04fb4..97e73b0ec74e7ec8ef27224bc6946eb005b940cf 100644 (file)
@@ -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
index 96a81ceeafa42a229b09ededb5fd1923c68e7181..700187fdddc775bf70fa4e62f6a9c65f25109b4f 100644 (file)
@@ -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
index 74702fe0c53b0fc57b85255c27c115896b05d20b..8aef13b47978f8c2ff19bbac7a24db3618811cd4 100644 (file)
@@ -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;
     }
 
index b08ed21d9759879e0b159c82e42bb3ea04c542a5..d41f5e2b6f4503e37e1e7fcdaabd65761e7473b9 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index fc99a8b9dcbf18d950b6a024aaf7429426a66617..33e019a52ef10f0bd812b797f853a232fe1a1cf3 100644 (file)
@@ -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_
index d19e628630d1e380f02673cdf97f6c986d3dd895..fbae63071bf72575df7990110486831e18134097 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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.
index 83908309df316171e307ef09b33e17d812844fda..17615f5e9ee5505485bfb005903e0b3e739e1322 100644 (file)
@@ -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;
   }
index 4e3d529db13861ad051e494791193c6dec2cc7d4..af21cd3716d3e5fe950d62a935a2a04da2b8dbe3 100644 (file)
@@ -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
index 106e55b307d924c60cf9bc251478fbda72967a22..1d00bb29936020b59e50195db14b99b145ef4f93 100644 (file)
@@ -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
index 6abcf6c4f2ba7036b153ab71a1ba1ae84e93b74a..dc91946b6aa597da58068505cf705b120d1c3d3c 100644 (file)
@@ -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;
       }
index 9016cea987d424b200115b05e9fa8578ef622f13..1b1377f5fec3b8a7ccc05145f8861921a48e9788 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index e50f08f981df8ef9f8e11447c8fde123c720d29c..ee1401102ae3defc405df55f489bcfcf7ba27334 100644 (file)
@@ -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) {
 
index 533f633101a960295b68141d18ec39bacbb88c06..5694e73f7fde0b3b6ac45a71f5ea8c76e24f48ad 100644 (file)
@@ -32,6 +32,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index bc4ccece8f9d350ab1af5402a5c83c42afcd57d8..1c1ce4424bef59596119ca93cd4a98f475d0fa4e 100644 (file)
@@ -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;
   }
index f72a6ca997de7a03a15e3c0a96e6c934e3f9f614..65b74822ed5d3300d19f0983d11e90ff66b44758 100644 (file)
@@ -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
index 2986b36f50d915d5d4f82788f16b8b85c69b3ad4..d1e59a990d3eaa3a89bbe37f661894568d016606 100644 (file)
@@ -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
index b6ae1b53121758ac363f0033e74127f64f57c45c..a8cce6cd5c366056109abe7944d40c9eb3e1a4b9 100644 (file)
@@ -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;
     }
 
index 54449b91d66e532930d29fdb623c97896941dccf..390b12e41f18d92053c471406292c08bb8343f41 100644 (file)
@@ -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
index 7c8767f784011486c9c90ddc550843f692e0987a..25e27eba1db6114bb62bc99f7629d30468c14264 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 991b4576cc6562382d9ca7ddac303234f55dfc07..9f2068484fb48999c196aa30ebd2bbd273e16544 100644 (file)
@@ -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) {
 
index 86635d3236de4dced6ce578606d85ea2f5422e8b..77464448330c1c7f043446d4d830698a2cfa39e6 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/status.h>
@@ -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
index 2ed3a78025e9b4e725dcefaddde873d0e336b090..3bb3f3a98b5a4ce47ce5a2e614e0be6f5831ba0d 100644 (file)
@@ -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;
   }
index 635db9c186e2b2c7747efffede84965aa2a53441..dd095ea7bc0f3a21895e0fd5a66d937cbee28e30 100644 (file)
@@ -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
index 9ee310bbf6deab327af4908dbb668257f5acceb5..2618a785dde6716073a33718903a13f11d60ed13 100644 (file)
@@ -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
index 14319dc5b3420752d976a2dc6cc61c096e8de276..e5ec11e0b1799fac45cf6e7ec4f5757aca426859 100644 (file)
@@ -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;
               }
             }
index 32a9477ae2c94de54c4e61b5553bb5eb6160f150..21e789211e05dde6ffb61fe8d1ed5ceca3ced6e5 100644 (file)
@@ -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
index e9f562b9e0006fba54342e2c47fdf52bcb76cb8c..64034db803ab4915180a2be747f308730b8de781 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_conversion
 fl_fss
 fl_print
index 862fa7dd04bf056733dc9aa3b14a22621987941f..ba435911fef777ba4891b9c2d18f9fb969e3dab8 100644 (file)
@@ -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) {
 
index 5fdf19e134340fc67b0c63d178a867be853301b7..167cfcd45dd149b9771aa4e23c676054355bd450 100644 (file)
@@ -30,6 +30,7 @@
 #include <fll/level_0/file.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index b7a473bd1f9c8c44a807b23f927993353b29293e..23c59a7243fc4ee56e443290464913750eb45024 100644 (file)
@@ -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;
   }
index e6d4b34c02bb76f96e5ea3e44ebcc91361d32a49..dcf1eaab009fd3c4f088bc4cac0f4f3bc61a32d9 100644 (file)
@@ -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
index 66ee609f1772e240dc81737a420c26a7c34ebb1b..d2a7f50bf006fdb861b45d697b612a90c86a8ffa 100644 (file)
@@ -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
index 65103895d35de5cb19c8a26249b0a770ce6da08e..5e49cd0b669cf64dec9a01c1ce77b9d0ff013f1e 100644 (file)
@@ -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) {
index ba5814918d817c4d54de0c26c729c384f753136e..07ec632c783ca35b6fef3a6f8c647ee2419c73c1 100644 (file)
@@ -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
index 84d8784e974b20424562bcc56a9af219f7bbda3e..65a5dd1bd2d77b56a6a2789c3e613c80bea8a153 100644 (file)
@@ -12,6 +12,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 445cbce2387b2a4391ba34f7ed1e1ead99f7ac8c..8f68a42c632ef59a835be6e445956cb4092f16de 100644 (file)
@@ -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) {
 
index d833d08e42b2071d99b97d99d0a7f362d027a14a..32cee07c4225a9ed8842f0469be3a059fcecc293 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/console.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 71652b893c732a0050ac254ae8ed4152ad3c5b65..f759ef379bcaf062d0a49499de00e45865f9c407 100644 (file)
@@ -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;
   }
index 24a88a74b6eb1e502a7e583fb9168c0b6dc5a5b3..3d12c1e407ac4d93ef8916200ede63c5c158ae79 100644 (file)
@@ -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
index 9d44e9ad3a1053d7754f6adf51ca5109e4c02cfb..9f3c6bce900a86a6d6bd23c0eb875cb53e430682 100644 (file)
 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
index 9eef232384ea9de05abc461b7e51b1f8f2aaf125..d75d64314a93ba7872767640421708be0efe9a6e 100644 (file)
@@ -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;
index 015cbe2f632213990f05863a3fd9afb8675a9e8f..51bb4d2e657dd1791b4da6215a2a02645e8d9cb7 100644 (file)
@@ -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
index 808aad1d716874763d72d34765c5a607121d1db8..bc8b57f53aadb7f84e92366fca1d06f049d03f21 100644 (file)
@@ -14,6 +14,7 @@ f_file
 f_fss
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_fss
index 78024afd9777725acf7cb9ca05880ba86a8c34f4..858f5c1f2454f3ef11a3cee78f796332d496204e 100644 (file)
@@ -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) {
 
index 858c73f34d1f679b5164de78237f845d1a1376c6..e7c42c3d0b21a7fb9e375880508047b828cb5780 100644 (file)
@@ -34,6 +34,7 @@
 #include <fll/level_0/iki.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index d2fb983956ee2aee1fdc021f27bc37568285021a..5cf5f381d451f76789c2d671dfbd16b4f6e3f444 100644 (file)
@@ -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;
   }
index ea6bcd80c6d7e57afd6c387ee8f8ab468de5fcb5..dd4af45bf30446126362926d23e2f6c3678b15f0 100644 (file)
@@ -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
index 0d8304e379694b409958154e5c1097f12d6ed34f..9962446ff9c1e8b1fd98d9f72c40c9a92dd38e74 100644 (file)
@@ -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
index 3bd6b450a7c848f15ba9e872a06354095da9de9e..ad889f5d8156b26343725485cf1f229916e9ff42 100644 (file)
@@ -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_
index da7b29ff780627d763395f46202c71a5da68eed4..476369cd4bcf3c9d87d087bb7d9acec9407bc78e 100644 (file)
@@ -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
index 285a99515149ad5a17367ce93ac0c3388f20fe8e..ab4c42e54e8c885b5de5d64242fffa97bf55d729 100644 (file)
@@ -12,6 +12,7 @@ f_file
 f_iki
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_iki
index 133a2f11ef19b893ba6799463980291c035c46af..3a69c7e99ccb7edf9a9a369850fd10501234aefd 100644 (file)
@@ -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) {
 
index 03173fdc0345dbff24d0611b730cd207c4880986..2682f2e2fed33a45773c96e6ac705ec4316c1bfb 100644 (file)
@@ -34,6 +34,7 @@
 #include <fll/level_0/iki.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 13590f619ee8f05b499ed7fac8a6a073ff1a748c..5892694e2c3f1df458e87cdf8f08df98e78b75b1 100644 (file)
@@ -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;
   }
index f860d81060770eaf3d0720f022f3c0229834be46..3eb18806caa7d132472c619ab410e63cafa609ba 100644 (file)
@@ -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
index da263ece6862cd39d50e40da0324e09a0a24ef33..e2a3d3cb7d2ce8b79ebe842a670a34cbcf9b7ee9 100644 (file)
@@ -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
index cc4eb1a75741095eb0ca1bf08d75a582938129c9..c07c395e9d78c94890f0cd4cdce16556d1643861 100644 (file)
@@ -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);
     }
 
index 576e14a1b1091415857a13227f770b33290d5f64..a987bae76e54680af494d439b079743a6cea183a 100644 (file)
@@ -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
index 472223cfa113669faa92f268871cbe8a9a62b657..3fc06d18c99b3dcb97b7c82e547d0d71622881d6 100644 (file)
@@ -11,6 +11,7 @@ f_file
 f_iki
 f_pipe
 f_print
+f_signal
 fl_console
 fl_iki
 fl_print
index e757f5a4833919c49e8c6732a784f865af15ac75..4775cecd38d3fcb1c71b8ef6abaea77a114c4c9b 100644 (file)
@@ -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;
   }
index 7540b79d0cb01c1393604db98794a1b6cf6d449d..132f650a343f9f8fd3232e7a6c46924fe0aa2fc7 100644 (file)
@@ -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
index 1b7c102970ac5d0ab29387457351701f352d1b20..71f6b3ca40db23e06974f735dc9fcd4d0f1cb1ad 100644 (file)
 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
index 67c224f07c9ccf2009e356ab90e14bbf3fae349b..3218f07987a83ee5df47367b9b767de9ac578dde 100644 (file)
@@ -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;
index 55c2f6480ad877be72212de89ff25de87e1e54c9..e499d36241297d21afeabbbcf244a2bc80799213 100644 (file)
@@ -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
index 67c99cfe2ba884a57a926d2c099f1539ba93485d..577225ff460a377711dfb0c76995eea5a1397fbd 100644 (file)
@@ -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) {
 
index 8f93ee3c091c775b91153440350a3291cbc1c6be..f73c76865ed7db534816e4f41176bf583484db85 100644 (file)
@@ -26,6 +26,7 @@
 #include <fll/level_0/console.h>
 #include <fll/level_0/pipe.h>
 #include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
 
 // fll-1 includes
 #include <fll/level_1/console.h>
@@ -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
index 4ad511e667ae22ba650c5ae69a1eb8a2cca22498..6238cab9bf2e27db2916cf3d76d2cd6f4b5785e1 100644 (file)
@@ -11,6 +11,7 @@ f_conversion
 f_file
 f_pipe
 f_print
+f_signal
 fl_console
 fl_conversion
 fl_print