]> Kevux Git Server - fll/commitdiff
Progress: Changes to fll_program functions.
authorKevin Day <thekevinday@gmail.com>
Thu, 11 Aug 2022 03:58:16 +0000 (22:58 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 11 Aug 2022 03:58:16 +0000 (22:58 -0500)
Reduce needed arguments to fll_program_parameter_process().

The color loaded is now handled in fll_program_parameter_process().

Add fll_program_parameter_process_verbosity().

Rename fll_program_standard_setdown() to fll_program_standard_set_down() and accept fll_program_data_t rather than f_signal_t.
Rename fll_program_standard_setup() to fll_program_standard_set_up() and accept fll_program_data_t rather than f_signal_t.

The fll_program_standard_set_down() now handles closing all file descriptors, incliding standard ones.

Change "bool process_pipe" to "uint8_t pipe" in fll_program_data_t to allow for multiple bits to be used.
Add "fl_print_t message" and "fl_print_t debug" to fll_program_data_t to give caller more control over different possible buffers.

level_2/fll_program/c/program.c
level_2/fll_program/c/program.h
level_2/fll_program/c/program/common.h

index 54575535c2840696db1f98196b552a87ad90b411..902e7ca9ddbc629aa0eb4653917424138ef028ad 100644 (file)
@@ -73,38 +73,61 @@ extern "C" {
 #endif // _di_fll_program_print_version_
 
 #ifndef _di_fll_program_parameter_process_
-  f_status_t fll_program_parameter_process(const f_console_arguments_t arguments, f_console_parameters_t * const parameters, const f_console_parameter_ids_t choices, const bool right, f_color_context_t * const context) {
+  f_status_t fll_program_parameter_process(const f_console_arguments_t arguments, const f_console_parameter_ids_t choices, const bool right, fll_program_data_t * const main) {
 
-    f_status_t status = F_none;
-
-    status = f_console_parameter_process(arguments, parameters);
+    f_status_t status = f_console_parameter_process(arguments, &main->parameters);
     if (F_status_is_error(status)) return status;
 
-    f_console_parameter_id_t decision = choices.id[2];
+    {
+      f_console_parameter_id_t decision = choices.id[2];
 
-    if (right) {
-      status = f_console_parameter_prioritize_right(*parameters, choices, &decision);
-    }
-    else {
-      status = f_console_parameter_prioritize_left(*parameters, choices, &decision);
+      if (right) {
+        status = f_console_parameter_prioritize_right(main->parameters, choices, &decision);
+      }
+      else {
+        status = f_console_parameter_prioritize_left(main->parameters, choices, &decision);
+      }
+
+      if (F_status_is_error(status)) return status;
+
+      // Load colors unless told not to.
+      if (decision == choices.id[0]) {
+        main->context.mode = F_color_mode_no_color_d;
+      }
+      else {
+        // @todo update this once macro_f_color_context_t_new is turned into a function.
+        macro_f_color_context_t_new(status, main->context);
+        if (F_status_is_error(status)) return status;
+
+        status = f_color_load_context(decision == choices.id[1], &main->context);
+      }
     }
 
-    if (F_status_is_error(status)) return status;
+    main->message.set = &main->context.set;
+    main->output.set = &main->context.set;
+    main->error.set = &main->context.set;
+    main->warning.set = &main->context.set;
+
+    if (main->context.set.error.before) {
+      main->message.context = f_color_set_empty_s;
+      main->message.notable = main->context.set.notable;
 
-    // Load colors unless told not to.
-    if (decision == choices.id[0]) {
-      context->mode = F_color_mode_no_color_d;
+      main->output.context = f_color_set_empty_s;
+      main->output.notable = main->context.set.notable;
+
+      main->error.context = main->context.set.error;
+      main->error.notable = main->context.set.notable;
+
+      main->warning.context = main->context.set.warning;
+      main->warning.notable = main->context.set.notable;
     }
     else {
-      f_status_t allocation_status = F_none;
-
-      macro_f_color_context_t_new(allocation_status, (*context));
-      if (F_status_is_error(status)) return status;
+      f_color_set_t *sets[] = { &main->message.context, &main->message.notable, &main->output.context, &main->output.notable, &main->error.context, &main->error.notable, &main->warning.context, &main->warning.notable, 0 };
 
-      status = f_color_load_context(decision == choices.id[1], context);
+      fll_program_parameter_process_empty(&main->context, sets);
     }
 
-    return status;
+    return F_none;
   }
 #endif // _di_fll_program_parameter_process_
 
@@ -125,11 +148,31 @@ extern "C" {
     if (sets) {
       for (f_array_length_t i = 0; sets[i]; ++i) {
         *sets[i] = f_color_set_empty_s;
-      }
+      } // for
     }
   }
 #endif // _di_fll_program_parameter_process_empty_
 
+#ifndef _di_fll_program_parameter_process_verbosity_
+  f_status_t fll_program_parameter_process_verbosity(const f_console_parameter_ids_t choices, const bool right, const uint8_t verbosity[], fll_program_data_t * const main) {
+
+    f_console_parameter_id_t choice = 0;
+
+    const f_status_t status = right ?
+      f_console_parameter_prioritize_right(main->parameters, choices, &choice) :
+      f_console_parameter_prioritize_left(main->parameters, choices, &choice);
+
+    if (F_status_is_error(status)) return status;
+
+    main->message.verbosity = verbosity[choice];
+    main->output.verbosity = verbosity[choice];
+    main->error.verbosity = verbosity[choice];
+    main->warning.verbosity = verbosity[choice];
+
+    return F_none;
+  }
+#endif // _di_fll_program_parameter_process_verbosity_
+
 #ifndef _di_fll_program_parameter_additional_append_
   f_status_t fll_program_parameter_additional_append(const f_string_static_t * const arguments, const f_array_lengths_t values, f_string_dynamics_t * const destination) {
     #ifndef _di_level_2_parameter_checking_
@@ -161,9 +204,7 @@ extern "C" {
       }
     } // for
 
-    if (status == F_none && start == destination->used) {
-      return F_data_not;
-    }
+    if (status == F_none && start == destination->used) return F_data_not;
 
     return status;
   }
@@ -188,9 +229,7 @@ extern "C" {
       }
     } // for
 
-    if (status == F_none && start == destination->used) {
-      return F_data_not;
-    }
+    if (status == F_none && start == destination->used) return F_data_not;
 
     return status;
   }
@@ -226,9 +265,7 @@ extern "C" {
       }
     } // for
 
-    if (status == F_none && start == destination->used) {
-      return F_data_not;
-    }
+    if (status == F_none && start == destination->used) return F_data_not;
 
     return status;
   }
@@ -263,9 +300,7 @@ extern "C" {
 
     f_string_dynamic_resize(0, &ripped);
 
-    if (status == F_none && start == destination->used) {
-      return F_data_not;
-    }
+    if (status == F_none && start == destination->used) return F_data_not;
 
     return status;
   }
@@ -288,53 +323,259 @@ extern "C" {
   }
 #endif // _di_fll_program_parameter_long_print_cannot_use_with_
 
-#ifndef _di_fll_program_standard_setdown_
-  f_status_t fll_program_standard_setdown(f_signal_t * const signal) {
+#ifndef _di_fll_program_standard_set_down_
+  f_status_t fll_program_standard_set_down(fll_program_data_t * const main) {
     #ifndef _di_level_2_parameter_checking_
       if (!signal) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
+    // The fclose() calls have undefined behavior when closing an already closed file.
+    // Avoid this by explicitly checking every permutation to make sure each descriptor is not a duplicat descriptor.
+    // 0x1 = message stream, 0x2 = output stream, 0x4 = error stream, 0x8 = warning stream, 0x10 = debug stream.
+    // 0x20 = message descriptor, 0x40 = output descriptor, 0x80 = error descriptor, 0x100 = warning descriptor, 0x200 = debug descriptor.
+    uint16_t flag = 0;
+
+    if (main->message.to.id == -1) {
+      if (main->message.to.stream != 0 && main->message.to.stream != F_type_error_d && main->message.to.stream != F_type_input_d && main->message.to.stream != F_type_output_d) {
+        f_file_stream_flush(&main->message.to);
+
+        flag |= 0x1;
+      }
+    }
+    else {
+      if (main->message.to.id != F_type_descriptor_error_d && main->message.to.id != F_type_descriptor_input_d && main->message.to.id != F_type_descriptor_output_d) {
+        f_file_flush(main->message.to);
+
+        flag |= 0x20;
+      }
+    }
+
+    if (main->output.to.id == -1) {
+      if (main->output.to.stream && main->output.to.stream != main->message.to.stream) {
+        if (main->output.to.stream != F_type_error_d && main->output.to.stream != F_type_input_d && main->output.to.stream != F_type_output_d) {
+          f_file_stream_flush(&main->output.to);
+
+          flag |= 0x2;
+        }
+      }
+    }
+    else if (main->output.to.id != main->message.to.id) {
+      if (main->output.to.id != F_type_descriptor_error_d && main->output.to.id != F_type_descriptor_input_d && main->output.to.id != F_type_descriptor_output_d) {
+        f_file_flush(main->output.to);
+
+        flag |= 0x40;
+      }
+    }
+
+    if (main->error.to.id == -1) {
+      if (main->error.to.stream && main->error.to.stream != main->message.to.stream && main->error.to.stream != main->output.to.stream) {
+        if (main->error.to.stream != F_type_error_d && main->error.to.stream != F_type_input_d && main->error.to.stream != F_type_output_d) {
+          f_file_stream_flush(&main->error.to);
+
+          flag |= 0x4;
+        }
+      }
+    }
+    else if (main->error.to.id != main->message.to.id && main->error.to.id != main->output.to.id) {
+      if (main->error.to.id != F_type_descriptor_error_d && main->error.to.id != F_type_descriptor_input_d && main->error.to.id != F_type_descriptor_output_d) {
+        f_file_flush(main->error.to);
+
+        flag |= 0x80;
+      }
+    }
+
+    if (main->warning.to.id == -1) {
+      if (main->warning.to.stream && main->warning.to.stream != main->message.to.stream && main->warning.to.stream != main->output.to.stream && main->warning.to.stream != main->error.to.stream) {
+        if (main->warning.to.stream != F_type_error_d && main->warning.to.stream != F_type_input_d && main->warning.to.stream != F_type_output_d) {
+          f_file_stream_flush(&main->warning.to);
+
+          flag |= 0x8;
+        }
+      }
+    }
+    else if (main->warning.to.id != main->message.to.id && main->warning.to.id != main->output.to.id && main->warning.to.id != main->error.to.id) {
+      if (main->warning.to.id != F_type_descriptor_error_d && main->warning.to.id != F_type_descriptor_input_d && main->warning.to.id != F_type_descriptor_output_d) {
+        f_file_flush(main->warning.to);
+
+        flag |= 0x100;
+      }
+    }
+
+
+    if (main->debug.to.id == -1) {
+      if (main->debug.to.stream && main->debug.to.stream != main->message.to.stream && main->debug.to.stream != main->output.to.stream && main->debug.to.stream != main->error.to.stream && main->debug.to.stream != main->warning.to.stream) {
+        if (main->debug.to.stream != F_type_error_d && main->debug.to.stream != F_type_input_d && main->debug.to.stream != F_type_output_d) {
+          f_file_stream_flush(&main->debug.to);
+
+          flag |= 0x10;
+        }
+      }
+    }
+    else if (main->debug.to.id != main->message.to.id && main->debug.to.id != main->output.to.id && main->debug.to.id != main->error.to.id && main->debug.to.id != main->warning.to.id) {
+      if (main->debug.to.id != F_type_descriptor_error_d && main->debug.to.id != F_type_descriptor_input_d && main->debug.to.id != F_type_descriptor_output_d) {
+        f_file_flush(main->debug.to);
+
+        flag |= 0x200;
+      }
+    }
+
+    if (flag & 0x1) {
+      f_file_stream_close(&main->message.to);
+    }
+
+    if (flag & 0x2) {
+      f_file_stream_close(&main->output.to);
+    }
 
-    // Flush output pipes before closing.
-    fflush(F_type_output_d);
-    fflush(F_type_error_d);
+    if (flag & 0x4) {
+      f_file_stream_close(&main->error.to);
+    }
 
-    // Close all open file descriptors.
-    close(F_type_descriptor_output_d);
-    close(F_type_descriptor_input_d);
-    close(F_type_descriptor_error_d);
+    if (flag & 0x8) {
+      f_file_stream_close(&main->warning.to);
+    }
 
-    const f_status_t status = f_signal_close(signal);
+    if (flag & 0x10) {
+      f_file_stream_close(&main->debug.to);
+    }
 
+    if (flag & 0x20) {
+      f_file_close(&main->message.to);
+    }
+
+    if (flag & 0x40) {
+      f_file_close(&main->output.to);
+    }
+
+    if (flag & 0x80) {
+      f_file_close(&main->error.to);
+    }
+
+    if (flag & 0x100) {
+      f_file_close(&main->warning.to);
+    }
+
+    if (flag & 0x200) {
+      f_file_close(&main->debug.to);
+    }
+
+    // 0x1 = output stream, 0x2 = error stream, 0x4 = input stream.
+    // 0x10 = output descriptor, 0x20 = error descriptor, 0x40 = input descriptor.
+    flag = 0;
+
+    f_file_t file = f_file_t_initialize;
+
+    if (F_type_output_d) {
+      file.stream = F_type_output_d;
+      flag |= 0x1;
+
+      f_file_stream_flush(&file);
+    }
+    else {
+      if (F_type_descriptor_output_d != -1) {
+        file.id = F_type_descriptor_output_d;
+        flag |= 0x20;
+
+        f_file_flush(file);
+      }
+    }
+
+    if (F_type_error_d) {
+      file.stream = F_type_error_d;
+      flag |= 0x2;
+
+      f_file_stream_flush(&file);
+    }
+    else {
+      if (F_type_descriptor_error_d != -1) {
+        file.id = F_type_descriptor_output_d;
+        flag |= 0x40;
+
+        f_file_flush(file);
+      }
+    }
+
+    if (F_type_input_d) {
+      file.stream = F_type_input_d;
+      flag |= 0x4;
+
+      f_file_stream_flush(&file);
+    }
+    else {
+      if (F_type_descriptor_input_d != -1) {
+        file.id = F_type_descriptor_input_d;
+        flag |= 0x80;
+
+        f_file_flush(file);
+      }
+    }
+
+    if (flag & 0x1) {
+      file.stream = F_type_output_d;
+
+      f_file_stream_close(&file);
+    }
+
+    if (flag & 0x2) {
+      file.stream = F_type_error_d;
+
+      f_file_stream_close(&file);
+    }
+
+    if (flag & 0x4) {
+      file.stream = F_type_input_d;
+
+      f_file_stream_close(&file);
+    }
+
+    if (flag & 0x10) {
+      file.id = F_type_descriptor_output_d;
+
+      f_file_close(&file);
+    }
+
+    if (flag & 0x20) {
+      file.id = F_type_descriptor_error_d;
+
+      f_file_close(&file);
+    }
+
+    if (flag & 0x40) {
+      file.id = F_type_descriptor_input_d;
+
+      f_file_close(&file);
+    }
+
+    const f_status_t status = f_signal_close(&main->signal);
     if (F_status_is_error(status)) return status;
 
     return F_none;
   }
-#endif // _di_fll_program_standard_setdown_
+#endif // _di_fll_program_standard_set_down_
 
-#ifndef _di_fll_program_standard_setup_
-  f_status_t fll_program_standard_setup(f_signal_t * const signal) {
+#ifndef _di_fll_program_standard_set_up_
+  f_status_t fll_program_standard_set_up(fll_program_data_t * const main) {
     #ifndef _di_level_2_parameter_checking_
-      if (!signal) return F_status_set_error(F_parameter);
+      if (!main) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
-    f_signal_set_empty(&signal->set);
-    f_signal_set_add(F_signal_abort, &signal->set);
-    f_signal_set_add(F_signal_broken_pipe, &signal->set);
-    f_signal_set_add(F_signal_hangup, &signal->set);
-    f_signal_set_add(F_signal_interrupt, &signal->set);
-    f_signal_set_add(F_signal_quit, &signal->set);
-    f_signal_set_add(F_signal_termination, &signal->set);
+    f_signal_set_empty(&main->signal.set);
+    f_signal_set_add(F_signal_abort, &main->signal.set);
+    f_signal_set_add(F_signal_broken_pipe, &main->signal.set);
+    f_signal_set_add(F_signal_hangup, &main->signal.set);
+    f_signal_set_add(F_signal_interrupt, &main->signal.set);
+    f_signal_set_add(F_signal_quit, &main->signal.set);
+    f_signal_set_add(F_signal_termination, &main->signal.set);
 
-    f_status_t status = f_signal_mask(SIG_BLOCK, &signal->set, 0);
+    f_status_t status = f_signal_mask(SIG_BLOCK, &main->signal.set, 0);
     if (F_status_is_error(status)) return status;
 
-    status = f_signal_open(signal);
+    status = f_signal_open(&main->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, &signal->set, 0);
-      f_signal_close(signal);
+      f_signal_mask(SIG_UNBLOCK, &main->signal.set, 0);
+      f_signal_close(&main->signal);
 
       return status;
     }
@@ -342,29 +583,27 @@ extern "C" {
     // Unblock all other signals.
     sigset_t set;
 
-    memset(&set, 0, sizeof(sigset_t));
+    memset(&main->signal.set, 0, sizeof(sigset_t));
 
-    f_signal_set_fill(&signal->set);
-    f_signal_set_delete(F_signal_abort, &signal->set);
-    f_signal_set_delete(F_signal_broken_pipe, &signal->set);
-    f_signal_set_delete(F_signal_hangup, &signal->set);
-    f_signal_set_delete(F_signal_interrupt, &signal->set);
-    f_signal_set_delete(F_signal_quit, &signal->set);
-    f_signal_set_delete(F_signal_termination, &signal->set);
+    f_signal_set_fill(&main->signal.set);
+    f_signal_set_delete(F_signal_abort, &main->signal.set);
+    f_signal_set_delete(F_signal_broken_pipe, &main->signal.set);
+    f_signal_set_delete(F_signal_hangup, &main->signal.set);
+    f_signal_set_delete(F_signal_interrupt, &main->signal.set);
+    f_signal_set_delete(F_signal_quit, &main->signal.set);
+    f_signal_set_delete(F_signal_termination, &main->signal.set);
 
-    status = f_signal_mask(SIG_UNBLOCK, &set, 0);
+    status = f_signal_mask(SIG_UNBLOCK, &main->signal.set, 0);
     if (F_status_is_error(status)) return status;
 
     return F_none;
   }
-#endif // _di_fll_program_standard_setup_
+#endif // _di_fll_program_standard_set_up_
 
 #ifndef _di_fll_program_standard_signal_received_
   f_status_t fll_program_standard_signal_received(fll_program_data_t * const main) {
 
-    if (!main || main->signal.id == -1) {
-      return F_false;
-    }
+    if (!main || main->signal.id == -1) return F_false;
 
     struct signalfd_siginfo information;
 
@@ -396,10 +635,7 @@ extern "C" {
     }
 
     f_state_t *state_ptr = (f_state_t *) state;
-
-    if (!state_ptr->custom) {
-      return F_interrupt_not;
-    }
+    if (!state_ptr->custom) return F_interrupt_not;
 
     fll_program_data_t *custom = (fll_program_data_t *) state_ptr->custom;
 
index 5bc7a15f32fdad2e081886032451028266cbf4c8..078456afb6b67db919ac972b5b197dd1a8092bdd 100644 (file)
@@ -190,15 +190,14 @@ extern "C" {
  *
  * @param arguments
  *   The parameters passed to the process.
- * @param parameters
- *   The console parameters to look for.
  * @param choices
  *   A set of the color options: no-color option, light-color option, dark-color option.
  *   This must have its used size set to 3 and the ids are expected to be in this order: no_color, light, and dark.
  * @param right
- *   Set to TRUE for right priortization and FALSE for left prioritization.
- * @param context
- *   The color context.
+ *   If TRUE, use the right-most parameter on conflict.
+ *   If FALSE, use the left-most parameter on conflict.
+ * @param main
+ *   The main program data.
  *
  * @return
  *   F_none on success.
@@ -218,7 +217,7 @@ extern "C" {
  * @see f_color_load_context()
  */
 #ifndef _di_fll_program_parameter_process_
-  extern f_status_t fll_program_parameter_process(const f_console_arguments_t arguments, f_console_parameters_t * const parameters, const f_console_parameter_ids_t choices, const bool right, f_color_context_t * const context);
+  extern f_status_t fll_program_parameter_process(const f_console_arguments_t arguments, const f_console_parameter_ids_t choices, const bool right, fll_program_data_t * const main);
 #endif // _di_fll_program_parameter_process_
 
 /**
@@ -237,6 +236,34 @@ extern "C" {
 #endif // _di_fll_program_parameter_process_empty_
 
 /**
+ * Determine the verbosity from the parameters and then set the verbosity based on the choice.
+ *
+ * @param choices
+ *   The available choices based on parameter ids.
+ * @param right
+ *   If TRUE, use the right-most parameter on conflict.
+ *   If FALSE, use the left-most parameter on conflict.
+ * @param verbosity
+ *   An array designating what to set the verbosity to based on the choice made.
+ *   This must exactly match the size of the choices array.
+ *   No bounds checking is performed.
+ * @param main
+ *   The main program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Errors (with error bit) from: f_console_parameter_prioritize_left().
+ *   Errors (with error bit) from: f_console_parameter_prioritize_right().
+ *
+ * @see f_console_parameter_prioritize_left()
+ * @see f_console_parameter_prioritize_right()
+ */
+#ifndef _di_fll_program_parameter_process_verbosity_
+  extern f_status_t fll_program_parameter_process_verbosity(const f_console_parameter_ids_t choices, const bool right, const uint8_t verbosity[], fll_program_data_t * const main);
+#endif // _di_fll_program_parameter_process_verbosity_
+
+/**
  * Allocate new strings from all of the provided locations.
  *
  * These new strings are appended onto the destination.
@@ -377,15 +404,17 @@ extern "C" {
 #endif // _di_fll_program_parameter_long_print_cannot_use_with_
 
 /**
- * This provides a standard program setdown operations used by FLL programs.
+ * This provides a standard program set down operations used by FLL programs.
  *
  * This does the following:
+ *   - Flushes program data files.
  *   - Flushes standard outputs.
+ *   - Closes program data files.
  *   - Closes standard inputs and outputs.
  *   - Closes the signal handler.
  *
- * @param signal
- *   The signal structure.
+ * @param main
+ *   The main program data.
  *
  * @return
  *   F_none on success.
@@ -394,20 +423,24 @@ extern "C" {
  *
  *   Errors (with error bit) from: f_signal_close().
  *
+ * @see f_file_close()
+ * @see f_file_flush()
+ * @see f_file_stream_close()
+ * @see f_file_stream_flush()
  * @see f_signal_close()
  */
-#ifndef _di_fll_program_standard_setdown_
-  extern f_status_t fll_program_standard_setdown(f_signal_t * const signal);
-#endif // _di_fll_program_standard_setdown_
+#ifndef _di_fll_program_standard_set_down_
+  extern f_status_t fll_program_standard_set_down(fll_program_data_t * const main);
+#endif // _di_fll_program_standard_set_down_
 
 /**
- * This provides a standard program setup operations used by FLL programs.
+ * This provides a standard program set up operations used by FLL programs.
  *
  * This does the following:
- *   - Handle signals so that program can cleanly exit, deallocating as appropriate.
+ *   - Handle signals so that program can cleanly exit, de-allocating as appropriate.
  *
- * @param signal
- *   The signal structure.
+ * @param main
+ *   The main program data.
  *
  * @return
  *   F_none on success.
@@ -424,9 +457,9 @@ extern "C" {
  * @see f_signal_set_empty()
  * @see f_signal_set_fill()
  */
-#ifndef _di_fll_program_standard_setup_
-  extern f_status_t fll_program_standard_setup(f_signal_t * const signal);
-#endif // _di_fll_program_standard_setup_
+#ifndef _di_fll_program_standard_set_up_
+  extern f_status_t fll_program_standard_set_up(fll_program_data_t * const main);
+#endif // _di_fll_program_standard_set_up_
 
 /**
  * Check to see if a process signal is received.
@@ -437,7 +470,6 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- *   The main->signal must be used to designate blocked signals.
  *
  * @return
  *   A positive number representing a valid signal on signal received.
index b8109e84b30d7a8b2672f9cae023088590f19cad..b31c7106e4b9513fcc231167b9d2a33c8a72c8dc 100644 (file)
@@ -28,6 +28,26 @@ extern "C" {
 #endif // _di_fll_program_parameters_
 
 /**
+ * Program data pipe codes.
+ *
+ * These are bit-wise codes used to designate that a particular pipe exists and is to be used.
+ *
+ * fll_program_data_pipe_*_e:
+ *   - none:   No pipes are available for use.
+ *   - error:  Error pipe is available for use.
+ *   - input:  Input pipe is available for use.
+ *   - output: Output pipe is available for use.
+ */
+#ifndef _di_fll_program_data_pipe_e_
+  enum {
+    fll_program_data_pipe_none_e   = 0x0,
+    fll_program_data_pipe_error_e  = 0x1,
+    fll_program_data_pipe_input_e  = 0x2,
+    fll_program_data_pipe_output_e = 0x4,
+  };
+#endif // _di_fll_program_data_pipe_e_
+
+/**
  * A common program structure to be used by simple programs needing no special structure.
  *
  * Complex programs or programs that need more data passed via the main should implement their own version of this.
@@ -35,18 +55,23 @@ extern "C" {
  * The umask() has design flaws as per specification that requires the umask be changed to read the value!
  * As a work-around, a umask variable is provided here so that umask() only ever need be called once.
  *
- * child:           Reserved for a child process, often representing the child return status or the child process ID.
- * context:         The color context.
- * error:           The output file for error printing.
- * output:          The output file for general printing.
- * parameters:      The state of pre-defined parameters passed to the program.
- * pid:             The PID of the program.
- * process_pipe:    Designate whether or not to process the input pipe.
- * signal:          The process signal management structure.
+ * parameters: The state of pre-defined parameters passed to the program.
+ *
+ * umask: The umask settings, needed for avoiding calls to umask() to read the current umask.
+ * pid:   The PID of the program.
+ * child: Reserved for a child process, often representing the child return status or the child process ID.
+ * pipe:  Designate that a pipe exists and is available for use.
+ *
  * signal_check:    A counter used to map to for reducing the amount of actual signal check calls.
  * signal_received: The signal received (if 0, then no signal is received).
- * umask:           The umask settings, needed for avoiding calls to umask() to read the current umask.
- * warning:         The output file for warning printing.
+ * signal:          The process signal management structure.
+ *
+ * message: The output file for normal output messages (often stdout).
+ * output:  The output file for normal/non-message output (often stdout or a file).
+ * error:   The output file for error output messages.
+ * warning: The output file for warning output messages.
+ *
+ * context: The color context.
  */
 #ifndef _di_fll_program_data_t_
   typedef struct {
@@ -55,15 +80,17 @@ extern "C" {
     mode_t umask;
     pid_t pid;
     int child;
-    bool process_pipe;
+    uint8_t pipe;
 
     int signal_received;
     uint16_t signal_check;
     f_signal_t signal;
 
+    fl_print_t message;
     fl_print_t output;
     fl_print_t error;
     fl_print_t warning;
+    fl_print_t debug;
 
     f_color_context_t context;
   } fll_program_data_t;
@@ -74,27 +101,31 @@ extern "C" {
       0, \
       0, \
       0, \
-      F_false, \
+      fll_program_data_pipe_none_e, \
       0, \
       0, \
       f_signal_t_initialize, \
       fl_print_t_initialize, \
+      fl_print_t_initialize, \
       macro_fl_print_t_initialize_error(), \
       macro_fl_print_t_initialize_warning(), \
+      macro_fl_print_t_initialize_debug(), \
       f_color_context_t_initialize, \
     }
 
-  #define macro_fll_program_data_t_initialize(umask, pid, child, process_pipe, signal_received, signal_check, signal, output, error, warning, context) { \
+  #define macro_fll_program_data_t_initialize(umask, pid, child, pipe, signal_received, signal_check, signal, message, output, error, warning, debug, context) { \
     umask, \
     pid, \
     child, \
-    process_pipe, \
+    pipe, \
     signal_received, \
     signal_check, \
     signal, \
+    message, \
     output, \
     error, \
     warning, \
+    debug, \
     context, \
   }
 #endif // _di_fll_program_data_t_