]> Kevux Git Server - fll/commitdiff
Progress: controller program.
authorKevin Day <thekevinday@gmail.com>
Sun, 6 Dec 2020 04:48:43 +0000 (22:48 -0600)
committerKevin Day <thekevinday@gmail.com>
Sun, 6 Dec 2020 04:59:56 +0000 (22:59 -0600)
Change "timeout" property to the more generic "number".
This can then be used for types "timeout" and "item", whereas the "item" number represents the location within the items list.
This is not known until all entry items are loaded and is therefore updated during the pre-process phase.

This implements the pre-process phase after the load phase.
The pre-process will perform additional checks, such as determining if "ready" is set somewhere in the active chain.
This makes sure recursion to an item already on the stack is not allowed.

Do some cleanups, reducing the if/then nesting by adding "do nothing" comment and letting the "else" condition handle the case appropriately.

Internally, line counting starts at 0, but when dealing with presenting the lines to users, the lines start at 1.
Change the behavior to increase the line number appropriately for entries.
The same will likely need to be done for rules.

Have the default.entry provide "ready".

level_3/controller/c/controller.c
level_3/controller/c/controller.h
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-controller.h
level_3/controller/c/private-entry.c
level_3/controller/c/private-entry.h
level_3/controller/data/build/dependencies
level_3/controller/data/build/settings
level_3/controller/data/settings/entries/default.entry

index 0d5c040cda5fad133bee80180336d4a0bc8f67c7..71fb7250f4a024632cff82c9bc2becc9847f9025 100644 (file)
@@ -228,16 +228,12 @@ extern "C" {
       }
     }
 
-    // @todo create pid file but not until "ready", so be sure to add this after pre-processing the entry file.
-    if (setting.ready) {
-      controller_file_pid_create(*data, setting.path_pid);
-    }
-
     if (F_status_is_error_not(status)) {
-      status = controller_preprocess_rules(*data, &setting, &cache);
+      status = controller_preprocess_items(*data, &setting, &cache);
     }
 
     if (F_status_is_error_not(status)) {
+
       if (data->parameters[controller_parameter_test].result == f_console_result_found || data->parameters[controller_parameter_validate].result == f_console_result_found) {
         // @todo validate happens first, report and handle validation problems or success.
 
@@ -248,6 +244,18 @@ extern "C" {
       else {
         // @todo check to see if the standard pid file exists before attempting to start (when in normal operation mode).
         // @todo real execution.
+
+        // @todo create pid file but not until "ready", so be sure to add this after pre-processing the entry file.
+        if (setting.ready) {
+          controller_file_pid_create(*data, setting.path_pid);
+        }
+
+        // @todo when everything is ready, wait here until told to quit.
+        // @todo clear cache periodically while waiting and no commands.
+        // controller_macro_cache_t_delete_simple(cache);
+
+        // @todo on failures that prevent normal execution: trigger failsafe/fallback execution, if defined
+        // @todo otherwise, set ready to controller_setting_ready_done.
       }
     }
 
index 6d97acf97a9c633151fb301e2602ac4ddd36128e..cb95cd9fa01a31f3bc558da470a7531abfc2de68 100644 (file)
@@ -40,6 +40,7 @@
 #include <level_1/console.h>
 #include <level_1/fss.h>
 #include <level_1/string.h>
+#include <level_1/type.h>
 
 // fll-2 includes
 #include <level_2/error.h>
@@ -68,7 +69,7 @@ extern "C" {
 
 #ifndef _di_controller_defines_
 
-  // must be at least 2.
+  // This specifically must be at least 2 for this project.
   #define controller_default_allocation_step 4
 
   #define controller_path_pid      "/var/run/controller/controller.pid"
index 82f9b6aef37d2b281406fae30ced36fa992f8550..5d7200a9f539270c3c9c5c41ea8b9108a8a9121a 100644 (file)
@@ -318,7 +318,7 @@ extern "C" {
     uint8_t code;
 
     f_string_length_t line;
-    f_number_unsigned_t timeout;
+    f_number_unsigned_t number;
 
     f_status_t status;
 
@@ -430,6 +430,7 @@ extern "C" {
     controller_setting_ready_no = 0,
     controller_setting_ready_wait,
     controller_setting_ready_yes,
+    controller_setting_ready_done,
   };
 
   typedef struct {
@@ -467,6 +468,8 @@ extern "C" {
 
     f_string_range_t range_action;
 
+    f_array_lengths_t ats;
+
     f_fss_comments_t comments;
     f_fss_delimits_t delimits;
 
@@ -490,6 +493,7 @@ extern "C" {
       0, \
       0, \
       f_string_range_t_initialize, \
+      f_array_lengths_t_initialize, \
       f_fss_comments_t_initialize, \
       f_fss_delimits_t_initialize, \
       f_fss_content_t_initialize, \
@@ -506,6 +510,7 @@ extern "C" {
     }
 
   #define controller_macro_cache_t_delete_simple(cache) \
+    f_macro_array_lengths_t_delete_simple(cache.ats) \
     f_macro_fss_comments_t_delete_simple(cache.comments) \
     f_macro_fss_delimits_t_delete_simple(cache.delimits) \
     f_macro_fss_content_t_delete_simple(cache.content_action) \
index 481d56fba5a92f1a33ba2dfe6d48f88a1ab1ccc1..3733dc55411e546a3d823afbb42f57f1b2c90ec2 100644 (file)
@@ -9,6 +9,49 @@
 extern "C" {
 #endif
 
+#ifndef _di_controller_entry_action_type_name_
+  f_string_static_t controller_entry_action_type_name(const uint8_t type) {
+
+    f_string_static_t buffer = f_string_static_t_initialize;
+
+    switch (type) {
+      case controller_entry_action_type_consider:
+        buffer.string = controller_string_consider;
+        buffer.used = controller_string_consider_length;
+        break;
+
+      case controller_entry_action_type_failsafe:
+        buffer.string = controller_string_failsafe;
+        buffer.used = controller_string_failsafe_length;
+        break;
+
+      case controller_entry_action_type_item:
+        buffer.string = controller_string_item;
+        buffer.used = controller_string_item_length;
+        break;
+
+      case controller_entry_action_type_ready:
+        buffer.string = controller_string_ready;
+        buffer.used = controller_string_ready_length;
+        break;
+
+      case controller_entry_action_type_rule:
+        buffer.string = controller_string_rule;
+        buffer.used = controller_string_rule_length;
+        break;
+
+      case controller_entry_action_type_timeout:
+        buffer.string = controller_string_timeout;
+        buffer.used = controller_string_timeout_length;
+        break;
+    }
+
+    buffer.size = buffer.used;
+
+    return buffer;
+  }
+#endif // _di_controller_entry_action_type_name_
+
 #ifndef _di_controller_file_load_
   f_return_status controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, f_string_dynamic_t *path_file, f_string_dynamic_t *buffer) {
     f_status_t status = F_none;
@@ -170,12 +213,258 @@ extern "C" {
   }
 #endif // _di_controller_file_pid_delete_
 
-#ifndef _di_controller_preprocess_rules_
-  f_return_status controller_preprocess_rules(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) {
-    // @todo
-    return F_none;
+#ifndef _di_controller_preprocess_items_
+  f_return_status controller_preprocess_items(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) {
+    f_status_t status = F_none;
+    f_status_t status2 = F_none;
+
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+
+    f_array_length_t at_i = 0;
+    f_array_length_t at_j = 1;
+
+    controller_entry_actions_t *actions = 0;
+
+    uint8_t error_has = F_false;
+
+    setting->ready = controller_setting_ready_no;
+
+    cache->ats.used = 0;
+
+    status = fl_type_array_lengths_increase_by(controller_default_allocation_step, &cache->ats);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fl_type_array_lengths_increase_by", F_true);
+      return status;
+    }
+
+    cache->ats.array[0] = 0;
+    cache->ats.array[1] = 0;
+    cache->ats.used = 2;
+
+    cache->line_item = setting->entry.items.array[0].line;
+    cache->name_item.used = 0;
+
+    status = fl_string_dynamic_append(setting->entry.items.array[0].name, &cache->name_item);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_append", F_true);
+      controller_entry_error_print(data.error, *cache);
+
+      return status;
+    }
+
+    status = fl_string_dynamic_terminate_after(&cache->name_item);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true);
+      controller_entry_error_print(data.error, *cache);
+
+      return status;
+    }
+
+    for (;;) {
+
+      actions = &setting->entry.items.array[cache->ats.array[at_i]].actions;
+
+      for (; cache->ats.array[at_j] < actions->used; ++cache->ats.array[at_j]) {
+
+        cache->line_action = actions->array[cache->ats.array[at_j]].line;
+        cache->name_action.used = 0;
+
+        status2 = fl_string_dynamic_append(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->name_action);
+
+        if (F_status_is_error(status2)) {
+          fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_append", F_true);
+          controller_entry_error_print(data.error, *cache);
+
+          return status2;
+        }
+
+        status2 = fl_string_dynamic_terminate_after(&cache->name_action);
+
+        if (F_status_is_error(status2)) {
+          fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_terminate_after", F_true);
+          controller_entry_error_print(data.error, *cache);
+
+          return status2;
+        }
+
+        if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready) {
+
+          if (setting->ready == controller_setting_ready_wait) {
+            if (data.warning.verbosity == f_console_verbosity_debug) {
+              fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
+              fprintf(data.warning.to.stream, "%s%sMultiple '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "");
+              fprintf(data.warning.to.stream, "%s%s%s%s", data.warning.context.after->string, data.warning.notable.before->string, controller_string_ready, data.warning.notable.after->string);
+              fprintf(data.warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol[0]);
+
+              controller_entry_error_print(data.warning, *cache);
+            }
+          }
+
+          // the pre-process currently only looks for "ready", so once found, pre-process is complete.
+          setting->ready = controller_setting_ready_wait;
+        }
+        else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item) {
+          error_has = F_false;
+
+          if (fl_string_dynamic_compare_string(controller_string_main, actions->array[cache->ats.array[at_j]].parameters.array[0], controller_string_main_length) == F_equal_to) {
+            continue;
+          }
+
+          // walk though each items and check to see if the item actually exists (skipping main).
+          for (i = 1; i < setting->entry.items.used; ++i) {
+
+            if (fl_string_dynamic_compare(setting->entry.items.array[i].name, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
+
+              // check to see if "i" is already in the stack (to prevent recursion) (skipping main).
+              for (j = 2; j < cache->ats.used; j += 2) {
+
+                if (cache->ats.array[j] == i) {
+                  if (data.error.verbosity != f_console_verbosity_quiet) {
+                    fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+                    fprintf(data.error.to.stream, "%s%sThe entry item named '", data.error.context.before->string, data.error.prefix ? data.error.prefix : "");
+                    fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, setting->entry.items.array[i].name.string, data.error.notable.after->string);
+                    fprintf(data.error.to.stream, "%s' cannot be executed because recursion is not allowed.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol[0]);
+                  }
+
+                  controller_entry_error_print(data.error, *cache);
+
+                  if (F_status_is_error_not(status)) {
+                    status = F_status_set_error(F_recurse);
+                  }
+
+                  error_has = F_true;
+                  break;
+                }
+              } // for
+
+              if (error_has) break;
+
+              status2 = fl_type_array_lengths_increase_by(controller_default_allocation_step, &cache->ats);
+
+              if (F_status_is_error(status2)) {
+                fll_error_print(data.error, F_status_set_fine(status2), "fl_type_array_lengths_increase_by", F_true);
+                controller_entry_error_print(data.error, *cache);
+
+                return status2;
+              }
+
+              // save the value so to avoid string comparison during normal operation.
+              actions->array[cache->ats.array[at_j]].number = i;
+
+              // continue into the requested item.
+              at_i = cache->ats.used;
+              at_j = cache->ats.used + 1;
+
+              cache->ats.array[at_i] = i;
+              cache->ats.array[at_j] = 0;
+              cache->ats.used += 2;
+
+              cache->name_action.used = 0;
+              cache->line_action = 0;
+
+              cache->name_item.used = 0;
+              cache->line_item = setting->entry.items.array[i].line;
+
+              status2 = fl_string_dynamic_append(setting->entry.items.array[i].name, &cache->name_item);
+
+              if (F_status_is_error(status2)) {
+                fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_append", F_true);
+                controller_entry_error_print(data.error, *cache);
+
+                return status2;
+              }
+
+              status2 = fl_string_dynamic_terminate_after(&cache->name_item);
+
+              if (F_status_is_error(status2)) {
+                fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_terminate_after", F_true);
+                controller_entry_error_print(data.error, *cache);
+
+                return status2;
+              }
+
+              break;
+            }
+          } // for
+
+          if (error_has || i >= setting->entry.items.used) {
+            if (i >= setting->entry.items.used) {
+              if (data.error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+                fprintf(data.error.to.stream, "%s%sThe entry item named '", data.error.context.before->string, data.error.prefix ? data.error.prefix : "");
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, actions->array[cache->ats.array[at_j]].parameters.array[0].string, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s' does not exist.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol[0]);
+              }
+
+              controller_entry_error_print(data.error, *cache);
+
+              if (F_status_is_error_not(status)) {
+                status = F_status_set_error(F_valid_not);
+              }
+            }
+          }
+          else {
+            break;
+          }
+        }
+      } // for
+
+      cache->line_action = 0;
+      cache->name_action.used = 0;
+
+      // end of actions found, so drop to previous loop in stack.
+      if (cache->ats.array[at_j] == actions->used) {
+
+        // all actions for "main" are processed so there is nothing left to do.
+        if (at_i == 0) break;
+
+        at_i -= 2;
+        at_j -= 2;
+
+        cache->ats.used -= 2;
+        cache->ats.array[at_j]++;
+
+        cache->line_item = setting->entry.items.array[cache->ats.array[at_i]].line;
+        cache->name_item.used = 0;
+
+        status2 = fl_string_dynamic_append(setting->entry.items.array[cache->ats.array[at_i]].name, &cache->name_item);
+
+        if (F_status_is_error(status2)) {
+          fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_append", F_true);
+          controller_entry_error_print(data.error, *cache);
+
+          return status2;
+        }
+
+        status2 = fl_string_dynamic_terminate_after(&cache->name_item);
+
+        if (F_status_is_error(status2)) {
+          fll_error_print(data.error, F_status_set_fine(status2), "fl_string_dynamic_terminate_after", F_true);
+          controller_entry_error_print(data.error, *cache);
+
+          return status2;
+        }
+      }
+    } // for
+
+    // if ready was never found in the entry, then default to always ready.
+    if (setting->ready == controller_setting_ready_no) {
+      setting->ready = controller_setting_ready_yes;
+    }
+
+    cache->ats.used = 0;
+    cache->line_action = 0;
+    cache->line_item = 0;
+    cache->name_action.used = 0;
+    cache->name_item.used = 0;
+
+    return status;
   }
-#endif // _di_controller_preprocess_rules_
+#endif // _di_controller_preprocess_items_
 
 #ifndef _di_controller_status_simplify_
   f_return_status controller_status_simplify(const f_status_t status) {
@@ -200,7 +489,7 @@ extern "C" {
       return F_status_set_error(F_number);
     }
 
-    if (status == F_parameter || status == F_found_not || status == F_interrupt) {
+    if (status == F_parameter || status == F_found_not || status == F_interrupt || status == F_supported_not) {
       return F_status_set_error(status);
     }
 
index 0cd4dec3aaa9c38a0bd84eda6ae3c36d88dfd902..4615ce1e6a8f34b3746b16dbc4e85a171277cc58 100644 (file)
 #ifdef __cplusplus
 extern "C" {
 #endif
+/**
+ * Get a string representing the entry action type.
+ *
+ * @param type
+ *   The entry action type code.
+ *
+ * @return
+ *   The string with used > 0 on success.
+ *   The string with used == 0 if no match was found.
+ */
+#ifndef _di_controller_entry_action_type_name_
+  extern f_string_static_t controller_entry_action_type_name(const uint8_t type) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_entry_action_type_name_
 
 /**
  * Load a file from the controller settings directory.
@@ -99,9 +112,9 @@ extern "C" {
  * @return
  *   F_none on success.
  */
-#ifndef _di_controller_preprocess_rules_
-  extern f_return_status controller_preprocess_rules(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_preprocess_rules_
+#ifndef _di_controller_preprocess_items_
+  extern f_return_status controller_preprocess_items(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_preprocess_items_
 
 /**
  * Given a wide range of status codes, simplify them down to a small subset.
index 61cf9c5be65cfcfa06a632ed0c1ba27a279954c9..4f56c6a22e6f3b256e79cd10abc15ac4753d0bc6 100644 (file)
@@ -97,8 +97,8 @@ extern "C" {
       action = &actions->array[actions->used];
       action->type = 0;
       action->code = 0;
-      action->line = cache->line_action;
-      action->timeout = 0;
+      action->line = 0;
+      action->number = 0;
       action->status = F_known_not;
       action->parameters.used = 0;
 
@@ -109,6 +109,9 @@ extern "C" {
         break;
       }
 
+      cache->line_action++;
+      action->line = cache->line_action;
+
       status = fl_string_dynamic_rip_nulless(cache->buffer_file, cache->object_actions.array[i], &cache->name_action);
 
       if (F_status_is_error(status)) {
@@ -387,39 +390,61 @@ extern "C" {
               }
             } // for
           }
+          else if (action->type == controller_entry_action_type_item) {
+            if (fl_string_dynamic_compare_string(controller_string_main, action->parameters.array[0], controller_string_main_length) == F_equal_to) {
+              action->status = F_status_set_error(F_supported_not);
+
+              if (F_status_is_error_not(status_action)) {
+                status_action = action->status;
+              }
+
+              if (data.error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+                fprintf(data.error.to.stream, "%s%sThe entry item action may not specify the reserved item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : "");
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol[0]);
+              }
+            }
+          }
           else if (action->type == controller_entry_action_type_timeout) {
-            if (fl_string_dynamic_compare_string(controller_string_kill, action->parameters.array[0], controller_string_kill_length) == F_equal_to_not) {
-              if (fl_string_dynamic_compare_string(controller_string_start, action->parameters.array[0], controller_string_start_length) == F_equal_to_not) {
-                if (fl_string_dynamic_compare_string(controller_string_stop, action->parameters.array[0], controller_string_stop_length) == F_equal_to_not) {
-                  action->status = F_status_set_error(F_supported_not);
+            if (fl_string_dynamic_compare_string(controller_string_kill, action->parameters.array[0], controller_string_kill_length) == F_equal_to) {
+              // do nothing
+            }
+            else if (fl_string_dynamic_compare_string(controller_string_start, action->parameters.array[0], controller_string_start_length) == F_equal_to) {
+              // do nothing
+            }
+            else if (fl_string_dynamic_compare_string(controller_string_stop, action->parameters.array[0], controller_string_stop_length) == F_equal_to) {
+              // do nothing
+            }
+            else {
+              action->status = F_status_set_error(F_supported_not);
 
-                  if (F_status_is_error_not(status_action)) {
-                    status_action = action->status;
-                  }
+              if (F_status_is_error_not(status_action)) {
+                status_action = action->status;
+              }
 
-                  if (data.error.verbosity != f_console_verbosity_quiet) {
-                    fprintf(data.error.to.stream, "%c", f_string_eol[0]);
-                    fprintf(data.error.to.stream, "%s%sThe entry item action must have one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : "");
-                    fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_kill, data.error.notable.after->string);
-                    fprintf(data.error.to.stream, "%s', '", data.error.context.before->string);
-                    fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_start, data.error.notable.after->string);
-                    fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string);
-                    fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_stop, data.error.notable.after->string);
-                    fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string);
-                    fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string);
-                    fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol[0]);
-                  }
-                }
+              if (data.error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+                fprintf(data.error.to.stream, "%s%sThe entry item action must have one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : "");
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_kill, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s', '", data.error.context.before->string);
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_start, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string);
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_stop, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string);
+                fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string);
+                fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol[0]);
               }
             }
 
             if (action->status == F_none) {
               const f_string_range_t range = f_macro_string_range_t_initialize(action->parameters.array[1].used);
-              f_number_unsigned_t number = 0;
 
-              status = fl_conversion_string_to_number_unsigned(action->parameters.array[1].string, &number, range);
+              status = fl_conversion_string_to_number_unsigned(action->parameters.array[1].string, &action->number, range);
 
               if (F_status_is_error(status) || status == F_data_not) {
+                action->number = 0;
+
                 if (status == F_data_not) {
                   action->status = F_status_set_error(F_number);
                 }
@@ -573,6 +598,7 @@ extern "C" {
         fll_error_print(data.error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true);
       }
       else {
+
         // 0x1 = main found, 0x2 = found existing.
         uint8_t code = 0;
 
@@ -635,10 +661,12 @@ extern "C" {
             break;
           }
 
+          cache->line_item++;
+
           for (j = (code & 0x1) ? 1 : 0; j < entry->items.used; ++j) {
 
             if (fl_string_dynamic_compare(entry->items.array[j].name, cache->name_item) == F_equal_to) {
-              if (data.warning.verbosity != f_console_verbosity_quiet) {
+              if (data.warning.verbosity == f_console_verbosity_debug) {
                 fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
                 fprintf(data.warning.to.stream, "%s%sIgnoring duplicate entry item '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "");
                 fprintf(data.warning.to.stream, "%s%s%s%s", data.warning.context.after->string, data.warning.notable.before->string, cache->name_file.string, data.warning.notable.after->string);
index 3423ac964c7c8dd54dc7cb4a15e2293bfbde0344..81f8ad56b38c81847744b4cf45e6633fcb59b3f1 100644 (file)
@@ -45,8 +45,8 @@ extern "C" {
  *   The range in the list buffer representing the content.
  * @param cache
  *   A structure for containing and caching relevant data.
- * @param list
- *   The processed list.
+ * @param actions
+ *   The processed actions.
  *
  * @return
  *   F_none on success.
@@ -70,7 +70,7 @@ extern "C" {
  * @see fll_fss_extended_read()
  */
 #ifndef _di_controller_entry_actions_read_
-  extern f_return_status controller_entry_actions_read(const controller_data_t data, const controller_setting_t setting, const f_string_range_t content_range, controller_cache_t *cache, controller_entry_actions_t *items) f_gcc_attribute_visibility_internal;
+  extern f_return_status controller_entry_actions_read(const controller_data_t data, const controller_setting_t setting, const f_string_range_t content_range, controller_cache_t *cache, controller_entry_actions_t *actions) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_entry_actions_read_
 
 /**
index 739d2da0723fd446e2f200c68056ac19190c4bec..548bde98b863a0e0ccdd72348c1eb2315ebfdbb8 100644 (file)
@@ -21,6 +21,7 @@ fl_conversion
 fl_fss
 fl_iki
 fl_string
+fl_type
 fll_error
 fll_fss
 fll_path
index 6ebae0de1d529c6029d48d98dc3a58722e0870c3..2b063b6bfd0a45df9dd364d6731b7f1c831715f7 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_error -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_fss -lfl_iki -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
+build_libraries-individual -lfll_error -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_type -lf_console -lf_conversion -lf_directory -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library controller.c private-control.c private-controller.c private-entry.c private-rule.c
index 2a67c98d7f33d085a60a5edab68e676c083bee58..ff056934f07d7ed9f356446bc50625eb7cc44cb4 100644 (file)
@@ -24,6 +24,8 @@ boot:
   rule service logger wait
   rule service dbus asynchronous
 
+  ready
+
 net:
   rule net all asynchronous