]> Kevux Git Server - fll/commitdiff
Progress: controller.
authorKevin Day <thekevinday@gmail.com>
Sat, 14 Nov 2020 05:03:51 +0000 (23:03 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 14 Nov 2020 05:03:51 +0000 (23:03 -0600)
Begin prototyping and writing the controller code.
While working on this I suddenly realized that I accidentally treated FSS-0003 (Extended List) as FSS-0008 (Embedded List)!
This needs to be fixed so I am saving the progress as-is with all the note and other mess and will correct the FSS-0003 accident.

13 files changed:
level_3/controller/c/controller.c
level_3/controller/c/controller.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-entry.c [new file with mode: 0644]
level_3/controller/c/private-entry.h [new file with mode: 0644]
level_3/controller/c/private-rule.c [new file with mode: 0644]
level_3/controller/c/private-rule.h [new file with mode: 0644]
level_3/controller/data/build/settings
level_3/controller/documents/rule.txt
level_3/controller/specifications/rule.txt
specifications/fss-000D.txt
specifications/fss-000E.txt [deleted file]
specifications/fss.txt

index 74daabcd115500e95e449577ce069280d05308d7..3e0fb2f4dd975b6a0302e9ec33cba0a155c7c262 100644 (file)
@@ -1,5 +1,7 @@
 #include "controller.h"
 #include "private-controller.h"
+#include "private-entry.h"
+#include "private-rule.h"
 
 #ifdef __cplusplus
 extern "C" {
index 7f069bf0ba49a5eec3f0c545951cfd56762a5677..8ecf7e82cfd3b74c77fda7347dd56c49348c054e 100644 (file)
@@ -53,6 +53,39 @@ extern "C" {
 #endif // _di_controller_name_
 
 #ifndef _di_controller_defines_
+  #define controller_string_create      "create"
+  #define controller_string_command     "command"
+  #define controller_string_define      "define"
+  #define controller_string_environment "environment"
+  #define controller_string_group       "group"
+  #define controller_string_name        "name"
+  #define controller_string_pid         "pid"
+  #define controller_string_program     "program"
+  #define controller_string_restart     "restart"
+  #define controller_string_reload      "reload"
+  #define controller_string_script      "script"
+  #define controller_string_service     "service"
+  #define controller_string_settings    "settings"
+  #define controller_string_start       "start"
+  #define controller_string_stop        "stop"
+  #define controller_string_user        "user"
+
+  #define controller_string_create_length      6
+  #define controller_string_command_length     7
+  #define controller_string_define_length      6
+  #define controller_string_environment_length 11
+  #define controller_string_group_length       5
+  #define controller_string_name_length        4
+  #define controller_string_pid_length         3
+  #define controller_string_program_length     7
+  #define controller_string_restart_length     7
+  #define controller_string_reload_length      6
+  #define controller_string_script_length      6
+  #define controller_string_service_length     7
+  #define controller_string_settings_length    8
+  #define controller_string_start_length       5
+  #define controller_string_stop_length        4
+  #define controller_string_user_length        4
 
   enum {
     controller_parameter_help,
@@ -106,6 +139,82 @@ extern "C" {
     }
 #endif // _di_controller_data_t_
 
+#ifndef _di_controller_rule_item_t_
+  enum {
+    controller_rule_item_type_single = 1,
+    controller_rule_item_type_multiple,
+  };
+
+  enum {
+    controller_rule_item_intent_create = 1,
+    controller_rule_item_intent_program,
+    controller_rule_item_intent_group,
+    controller_rule_item_intent_restart,
+    controller_rule_item_intent_reload,
+    controller_rule_item_intent_start,
+    controller_rule_item_intent_stop,
+    controller_rule_item_intent_user,
+  };
+
+  // @fixme rule_item needs to contain a list of actions which is essentially what rule_item is currently acting as.
+  typedef struct {
+    uint8_t type;
+    uint8_t intent;
+
+    f_string_length_t line;
+
+    f_string_dynamic_t name;
+    f_string_dynamic_t content;
+  } controller_rule_item_t;
+
+  #define controller_rule_item_t_initialize \
+    { \
+      0, \
+      0, \
+      0, \
+      f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
+    }
+
+  #define f_macro_controller_rule_item_t_delete_simple(rule_item) \
+    f_macro_string_dynamic_t_delete_simple(rule_item.name) \
+    f_macro_string_dynamic_t_delete_simple(rule_item.content)
+#endif // _di_controller_rule_item_t_
+
+#ifndef _di_controller_rule_items_t_
+  typedef struct {
+    f_string_length_t line;
+    f_string_dynamic_t name;
+
+    controller_rule_item_t *array;
+
+    f_array_length_t size;
+    f_array_length_t used;
+  } controller_rule_items_t;
+
+  #define controller_rule_items_initialize \
+    { \
+      0, \
+      f_string_dynamic_t_initialize, \
+      0, \
+      0, \
+      0, \
+    }
+
+  #define f_macro_controller_rule_items_t_delete_simple(items) \
+    items.used = items.size; \
+    while (items.used > 0) { \
+      items.used--; \
+      f_macro_controller_rule_item_t_delete_simple(items.array[items.used]); \
+      if (!items.used) { \
+        if (f_memory_delete((void **) & items.array, sizeof(f_string_dynamic_t), items.size)) { \
+          items.size = 0; \
+        } \
+      } \
+    } \
+    f_macro_string_dynamic_t_delete_simple(items.name);
+#endif // _di_controller_rule_items_t_
+
 /**
  * Print help.
  *
index fbcc4b82a22f85b9220b55b23b6ebfe36861aab8..9a980358305a52626acc15a20def57f098bc3fe8 100644 (file)
@@ -1,2 +1,12 @@
 #include "controller.h"
 #include "private-controller.h"
+#include "private-entry.h"
+#include "private-rule.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c
new file mode 100644 (file)
index 0000000..96460e0
--- /dev/null
@@ -0,0 +1,10 @@
+#include "controller.h"
+#include "private-entry.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/controller/c/private-entry.h b/level_3/controller/c/private-entry.h
new file mode 100644 (file)
index 0000000..7e9eb6e
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_entry_h
+#define _PRIVATE_entry_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_entry_h
diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c
new file mode 100644 (file)
index 0000000..b738dd4
--- /dev/null
@@ -0,0 +1,285 @@
+#include "controller.h"
+#include "private-rule.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_controller_rule_items_increase_by_
+  f_return_status controller_rule_items_increase_by(const f_array_length_t amount, controller_rule_items_t *items) {
+    f_status_t status = F_none;
+    f_string_length_t size = items->size + amount;
+
+    if (size > f_array_length_t_size) {
+      if (items->size == f_array_length_t_size) {
+        return F_status_set_error(F_array_too_large);
+      }
+
+      size = items->size;
+      status = F_array_too_large;
+    }
+
+    const f_status_t status_resize = f_memory_resize((void **) & items.array, sizeof(controller_rule_items_t), items.size, size);
+    if (F_status_is_error(status_resize)) return status_resize;
+
+    items.size = size;
+    return status;
+  }
+#endif // _di_controller_rule_items_increase_by_
+
+#ifndef _di_controller_rule_read_
+  f_return_status controller_rule_read(const controller_data_t data, const f_string_static_t file_name, controller_rule_items_t *items) {
+    f_status_t status = F_none;
+    f_string_dynamic_t buffer = f_string_dynamic_t_initialize;
+
+    items->used = 0;
+
+    {
+      f_file_t file = f_file_t_initialize;
+
+      status = f_file_stream_open(arguments.argv[data->remaining.array[i]], 0, &file);
+
+      if (F_status_is_error(status)) {
+        fll_error_file_print(data->error, F_status_set_fine(status), "f_file_stream_open", F_true, file_name.string, "open", fll_error_file_type_file);
+      }
+      else {
+        status = f_file_stream_read(file, 1, &buffer);
+
+        if (F_status_is_error(status)) {
+          fll_error_file_print(data->error, F_status_set_fine(status), "f_file_stream_read", F_true, file_name.string, "read", fll_error_file_type_file);
+        }
+      }
+
+      f_file_stream_close(F_true, &file);
+
+      if (F_status_is_error(status)) {
+        f_macro_string_dynamic_t_delete_simple(buffer);
+        return F_false;
+      }
+    }
+
+    f_fss_objects_t objects = f_fss_objects_t_initialize;
+    f_fss_contents_t contents = f_fss_contents_t_initialize;
+
+    if (buffer.used) {
+      f_string_range_t range = f_macro_string_range_t_initialize(buffer.used);
+      f_fss_delimits_t delimits = f_fss_delimits_t_initialize;
+      f_fss_comments_t comments = f_fss_comments_t_initialize;
+
+      status = fll_fss_basic_list_read(&data_make->buffer, &range, &objects, &contents, &delimits, 0, &comments);
+
+      if (F_status_is_error(status)) {
+        fake_print_error_fss(data, status, "fll_fss_basic_list_read", data.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(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
+        }
+      }
+
+      f_macro_fss_delimits_t_delete_simple(delimits);
+      f_macro_fss_comments_t_delete_simple(comments);
+    }
+
+    if (F_status_is_error_not(status) && objects.used) {
+      status = controller_rule_items_increase_by(objects.used, items);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true);
+      }
+      else {
+        f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+        for (f_array_length_t i = 0; i < objects.used; ++i) {
+
+          status = f_fss_count_lines(buffer, objects.array[i], &items->array[items->used].line);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
+            break;
+          }
+
+          status = fl_string_dynamic_partial_append_nulless(buffer, objects.array[i], items->array[items->used].name);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+            break;
+          }
+
+          status = fl_string_dynamic_terminate_after(items->array[items->used].name);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true);
+            break;
+          }
+
+          content.used = 0;
+          status = fl_string_dynamic_partial_append(buffer, contents.array[i].array[0], &content);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append", F_true);
+            break;
+          }
+
+          status = controller_rule_read_content(data, file_name, items->array[items->used].line, &content, items);
+          if (F_status_is_error(status)) break;
+
+          items->used++;
+        } // for
+
+        f_macro_fss_content_t_delete_simple(content);
+      }
+    }
+
+    f_macro_fss_objects_t_delete_simple(objects);
+    f_macro_fss_contents_t_delete_simple(contents);
+    f_macro_string_dynamic_t_delete_simple(buffer);
+
+    return status;
+  }
+#endif // _di_controller_rule_read_
+
+#ifndef _di_controller_rule_read_content_
+  f_return_status controller_rule_read_content(const controller_data_t data, const f_string_static_t file_name, const f_string_length_t line, f_string_static_t *content, controller_rule_items_t *items) {
+    f_status_t status = F_none;
+
+    f_string_range_t range = f_macro_string_range_t_initialize(content->used);
+    f_string_length_t last = 0;
+
+    f_fss_delimits_t delimits = f_fss_delimits_t_initialize;
+    f_fss_comments_t comments = f_fss_comments_t_initialize;
+    f_fss_object_t child_object = f_fss_object_t_initialize;
+    f_fss_content_t child_content = f_fss_content_t_initialize;
+    f_fss_quote_t quote = f_fss_quote_t_initialize;
+
+    uint8_t type = 0;
+
+    for (range.start = 0; range.start < content->used; last = range.start, type = 0) {
+
+      delimits.used = 0;
+      status = fl_fss_extended_list_object_read(content, &range, &child_object, &delimits);
+
+      if (F_status_is_error(status)) {
+        fll_error_file_print(data->error, F_status_set_fine(status), "fl_fss_extended_list_object_read", F_true, file_name.string, "read", fll_error_file_type_file);
+        break;
+      }
+
+      if (range.start >= range.stop || range.start >= content->used) {
+        if (status == FL_fss_found_object || status == FL_fss_found_object_content_not) {
+          if (error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+            fprintf(data.error.to.stream, "%s%sUnterminated FSS Extended List at end of file '", 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, file_name.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]);
+          }
+
+          status = F_status_set_error(FL_fss_found_object_content_not);
+        }
+
+        break;
+      }
+
+      if (status == FL_fss_found_object) {
+        // @fixme I just noticed that Extended List wasn't intended to be recursive, this will be updated.
+        comments.used = 0;
+        status = fl_fss_extended_list_content_read(content, &range, &child_content, &delimits, &comments);
+
+        if (F_status_is_error(status)) {
+          fll_error_file_print(data->error, F_status_set_fine(status), "fl_fss_extended_list_content_read", F_true, file_name.string, "read", fll_error_file_type_file);
+          break;
+        }
+
+        if (status == FL_fss_found_content) {
+          type = controller_rule_item_type_multiple;
+        }
+      }
+      else {
+        status = fl_fss_basic_object_read(content, &range, &child_object, &quote, &delimits);
+
+        if (F_status_is_error(status)) {
+          fll_error_file_print(data->error, F_status_set_fine(status), "fl_fss_basic_object_read", F_true, file_name.string, "read", fll_error_file_type_file);
+          break;
+        }
+
+        if (range.start >= range.stop || range.start >= content->used) {
+          // in this case, if status is FL_fss_found_object or FL_fss_found_object_content_not, there is no content so do not save this item.
+          break;
+        }
+
+        if (status == FL_fss_found_object) {
+          status = fl_fss_basic_content_read(content, &range, &child_content, &delimits);
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "fl_fss_basic_content_read", F_true, file_name.string, "read", fll_error_file_type_file);
+            break;
+          }
+
+          if (status == FL_fss_found_content) {
+            type = controller_rule_item_type_single;
+          }
+        }
+      }
+
+      if (type) {
+        status = fl_fss_apply_delimit(delimits, &data_make->buffer);
+
+        if (F_status_is_error(status)) {
+          fll_error_file_print(data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, file_name.string, "read", fll_error_file_type_file);
+          break;
+        }
+
+        status = f_fss_count_lines(buffer, contents.array[i], &items->array[items->used].line);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
+          break;
+        }
+
+        // @todo
+        //if (fl_string_dynamic_compare_string(x, items->array[i].name) == f_equal_to) {
+          //items->array[i].name
+          // @todo
+        //}
+      }
+    } // for
+
+    f_macro_fss_delimits_t_delete_simple(delimits);
+    f_macro_fss_comments_t_delete_simple(comments);
+    f_macro_fss_content_t_delete_simple(child_content);
+
+    if (F_status_is_error(status)) return status;
+
+    /*
+    uint8_t type;
+    uint8_t intent;
+
+    f_string_length_t line;
+
+    f_string_dynamic_t name;
+    f_string_dynamic_t content;
+    */
+    /*
+    status = fl_string_dynamic_partial_append_nulless(buffer, objects.array[i], items->array[i].name);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+      break;
+    }
+
+    status = fl_string_dynamic_terminate_after(items->array[i].name);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true);
+      break;
+    }
+
+
+    */
+  }
+#endif // _di_controller_rule_read_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h
new file mode 100644 (file)
index 0000000..0ab28b0
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_rule_h
+#define _PRIVATE_rule_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Increase the size of the rule items array by the specified amount, but only if necessary.
+ *
+ * This only increases size if the current used plus amount is greater than the currently allocated size.
+ *
+ * @param amount
+ *   A positive number representing how much to increase the size by.
+ * @param items
+ *   The items to resize.
+ *
+ * @return
+ *   F_none on success.
+ *   F_array_too_large on success, but requested size is too small (resize is smaller than requested length).
+ *
+ *   Errors (with error bit) from: f_memory_resize().
+ */
+#ifndef _di_controller_rule_items_increase_by_
+  extern f_return_status controller_rule_items_increase_by(const f_array_length_t amount, controller_rule_items_t *items) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_items_increase_by_
+
+/**
+ * Read the content within the buffer, extracting all valid items.
+ *
+ * @param data
+ *   The program data.
+ * @param file_name
+ *   The file name string.
+ * @param items
+ *   An array of items associated with the rule.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Errors (with error bit) from: controller_rule_items_increase_by().
+ *   Errors (with error bit) from: controller_rule_read_content().
+ *   Errors (with error bit) from: f_file_stream_open().
+ *   Errors (with error bit) from: f_file_stream_read().
+ *   Errors (with error bit) from: f_fss_count_lines().
+ *   Errors (with error bit) from: fl_fss_apply_delimit().
+ *   Errors (with error bit) from: fl_string_dynamic_partial_append().
+ *   Errors (with error bit) from: fl_string_dynamic_partial_append_nulless().
+ *   Errors (with error bit) from: fl_string_dynamic_terminate_after().
+ *   Errors (with error bit) from: fll_fss_basic_list_read().
+ */
+#ifndef _di_controller_rule_read_
+  extern f_return_status controller_rule_read(const controller_data_t data, const f_string_static_t file_name, controller_rule_items_t *items) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_read_
+
+/**
+ * Read the content within the buffer, extracting all valid items after determining their type for some rule file.
+ *
+ * This will perform additional FSS read functions as appropriate.
+ *
+ * @param data
+ *   The program data.
+ * @param file_name
+ *   The file name string.
+ * @param line
+ *   The line number where the content begins.
+ * @param content
+ *   The buffer containing the content.
+ * @param items
+ *   An array of items associated with the rule.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Errors (with error bit) from: f_fss_count_lines().
+ *   Errors (with error bit) from: fl_string_dynamic_partial_append_nulless().
+ *   Errors (with error bit) from: fl_string_dynamic_terminate_after().
+ */
+#ifndef _di_controller_rule_read_content_
+  extern f_return_status controller_rule_read_content(const controller_data_t data, const f_string_static_t file_name, const f_string_length_t line, f_string_static_t *content, controller_rule_items_t *items) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_read_content_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_rule_h
index 72c9bc74f72db6fb65f0bc840ecf47627c6b36d7..0e4ddb8d498de3bd2adb54de6cf1f3a62d76f3fe 100644 (file)
@@ -22,7 +22,7 @@ build_libraries -lc
 build_libraries-individual -lfll_error -lfll_program -lfll_status -lfl_color -lfl_console -lfl_status -lfl_string -lf_console -lf_conversion -lf_file -lf_memory -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-controller.c
+build_sources_library controller.c private-controller.c private-entry.c private-rule.c
 build_sources_program main.c
 build_sources_headers controller.h
 build_sources_script
index d2b5693afec1e398e8d0d3e2df008136f2acd568..ea3a9e54a4bc798de03abb9a04495b8f9deca62e 100644 (file)
@@ -3,12 +3,14 @@
 Rule Documentation:
   This describes the intent and purpose of the rule file settings.
 
-  A rule file, such as "ssh.rule", is intended to desginate what to execute.
+  A rule file, such as "ssh.rule", is intended to designate what to execute.
 
   The rule file is read top-down, except for the outer most list "settings", which is intended to store settings data for this rule.
   Multiple outer most list Objects may be specified and they are executed as provided, in a top-down manner.
 
   The "settings" outer most list Object has the following FSS-0001 (Extended) Content:
+    "define": Define a custom environment variable with a given variable, and automatically expose it to processes executed within this rule.
+    "environment": A set of environment variables to expose to the processes executed within this rule (PATH is always exposed).
     "name": A name used to represent this rule, which is printing to the user, screen, logs, etc...
     "pid": A path to a directory where the PID file is expected to be stored in.
     @todo: consider adding "path" to allow specifying a custom environment PATH variable (or even go a step further and instead provide "environment" or "variable").
@@ -32,7 +34,7 @@ Rule Documentation:
   The "reload" Content is performed whenever this rule is executed using the reload action.
 
   When "restart" Content is not provided, then "start" and "stop" is called when the rule is executed using the restart action, if both "start" and "stop" are provided.
-  When "reload", "start", or "stop" Content are not provided, then no respective action is peformed.
+  When "reload", "start", or "stop" Content are not provided, then no respective action is performed.
 
   The "group" inner Content, an associated "command", "service", or "script" are executed with that group ID or group name.
   The "user" inner Content, an associated "command", "service", or "script" are executed with that user ID or user name.
index 0f80de0d7d38062b8243d8f75fdde01d282df9e6..d2518889e37246f3f674c9a9b58d1fb9afbf46ba 100644 (file)
@@ -14,6 +14,8 @@ Rule Specification:
   For the above Basic List Objects, "main" may be specified only once whereas the others may be specifed multiple times.
 
   The "settings" outer most list Object has the following FSS-0001 (Extended) Content:
+    "define": Two Content, the first Content must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
+    "environment": Zero or more Content, each must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
     "name": One Content, must have at least 1 non-whitespace printing character.
     "pid": One Content representing the path to a PID file directory.
 
index 402a66eff88df89084a43061329b61aca2feff5c..63f71903eb409876b34e07913109dd28f902d6ca 100644 (file)
@@ -1,7 +1,71 @@
 # fss-0002
 
 Featureless Settings Specification: 000D - Basic Rule:
-  @todo: document this.
-  This should be a special case that has an FSS Basic List on the outside and conditional types on the inside.
-  The conditional types are context-specific and not defined by this specification.
-  This specification only defines that they exist and not when/how they exist.
+  This is a special case that follows FSS-0002 (Basic List), and different FSS formats inside this Basic List.
+  This Basic List is considered the "Outer List" and the Content of this Outer List is considered the "Inner Content".
+
+  The Inner Content may be any of the following FSS formats: FSS-0000 (Basic), FSS-0001 (Extended), and FSS-0003 (Extended List).
+  The way in which each format is determined is first to see if the Inner Content Object would be a valid Extended List Object.
+  If the Inner Content Object is not a valid Extended List Object, then check to see if it is an Basic/Extended Object.
+
+  The FSS Basic and FSS Extended Objects have the same format for Object names but the FSS Extended List Object is slightly different.
+  Anything that would match an FSS Extended List Object must therefore be an FSS Extended List Object.
+
+  Anything implementing this specification may impose its own restrictions on when to determine if the Inner Content is what FSS format, based on Object names.
+
+  See the appropriate specifications for the Key/Structure/Example documentation for the respective FSS-0000 (Basic), FSS-0001 (Extended), and FSS-0003 (Extended List).
+
+  Example\:
+
+    main:
+      name boot-devices
+
+    script:
+      start {
+        ip addr add 127.0.0.1/8 label lo dev lo;
+        ip link set lo up;
+      }
+
+      stop {
+        ip link set lo down;
+      }
+
+    command:
+      start mount -a -O no_netdev
+      stop umount -arf -O no_netdev
+
+  Outer List Objects would be\:
+    1) main
+    2) script
+    3) command
+
+  Outer List Contents would be\:
+    1.1) name boot-devices
+
+    2.1) start {
+           ip addr add 127.0.0.1/8 label lo dev lo;
+           ip link set lo up;
+         }
+
+         stop {
+           ip link set lo down;
+         }
+
+    3.1) begin mount -a -O no_netdev
+         end umount -arf -O no_netdev
+
+  Inner Content Objects would be\:
+    1.1.1) name
+    2.1.1) start
+    2.1.2) stop
+    3.1.1) begin
+    3.1.2) end
+
+  Inner Content Contents would be\:
+    1.1.1) boot-devices
+    2.1.1) ip addr add 127.0.0.1/8 label lo dev lo;
+           ip link set lo up;
+    2.1.2) ip link set lo down;
+    3.1.1) mount -a -O no_netdev
+    3.1.2) umount -arf -O no_netdev
+
diff --git a/specifications/fss-000E.txt b/specifications/fss-000E.txt
deleted file mode 100644 (file)
index cf43591..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# fss-0002
-
-Featureless Settings Specification: 000E - Extended Rule:
-  @todo: document this.
-  This should be a special case that has an FSS Extended List on the outside and conditional types on the inside.
-  The conditional types are context-specific and not defined by this specification.
-  This specification only defines that they exist and not when/how they exist.
index 535d249b2764c0f99d79d4720f492c09eae886c1..ea6f8e0c788fa39848c20a50e0c4836a27696da1 100644 (file)
@@ -132,4 +132,3 @@ Featureless Settings Specifications:
   - fss-000B: Simple List
   - fss-000C: Iki Text
   - fss-000D: Basic Rule
-  - fss-000E: Extended Rule