]> Kevux Git Server - fll/commitdiff
Progress: featureless make.
authorKevin Day <thekevinday@gmail.com>
Mon, 13 Jul 2020 02:04:12 +0000 (21:04 -0500)
committerKevin Day <thekevinday@gmail.com>
Mon, 13 Jul 2020 02:04:12 +0000 (21:04 -0500)
begin validating operations.

begin adding documentation for fakefile.

Fix mistake in documentation files where incomplete/incorrect fss header is specified.

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/documents/fakefile.txt [new file with mode: 0644]
level_3/fake/specifications/defines.txt
level_3/fake/specifications/dependencies.txt
level_3/fake/specifications/fakefile.txt [new file with mode: 0644]
level_3/fake/specifications/settings.txt

index 9d228b29809ae89a4c5c2147ba9af16c4e0c8d58..97d08dc0a1abeb08bfbd885603c83e3577bfeb35 100644 (file)
@@ -225,6 +225,8 @@ extern "C" {
 
     f_macro_mode_set_default_umask(mode, data.umask);
 
+    data_make.fail = fake_make_operation_fail_type_exit;
+
     fake_make_load_fakefile(data, &data_make, &status);
 
     fake_make_operate_section(data, data_make.main, &data_make, &list_stack, &status);
@@ -236,8 +238,8 @@ extern "C" {
   }
 #endif // _di_fake_make_operate_
 
-#ifndef _di_fake_make_operation_expand_
-  void fake_make_operation_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, const f_fss_quoteds quoteds, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) {
+#ifndef _di_fake_make_operate_expand_
+  void fake_make_operate_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, const f_fss_quoteds quoteds, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) {
     if (F_status_is_error(*status)) return;
     if (content.used == 0) return;
 
@@ -487,7 +489,7 @@ extern "C" {
     f_macro_iki_vocabulary_delete_simple(iki_vocabulary);
     f_macro_iki_content_delete_simple(iki_content);
   }
-#endif // _di_fake_make_operation_expand_
+#endif // _di_fake_make_operate_expand_
 
 #ifndef _di_fake_make_operate_section_
   void fake_make_operate_section(const fake_data data, const f_array_length section_id, fake_make_data *data_make, f_string_lengths *section_stack, f_status *status) {
@@ -514,6 +516,10 @@ extern "C" {
       fl_color_print_line(f_type_output, data.color_section_set, data.color_section_reset, "'.");
     }
 
+    if (!section->objects.used) {
+      return;
+    }
+
     const f_string_static operations_name[] = {
       f_macro_string_static_initialize(fake_make_operation_archive, fake_make_operation_archive_length),
       f_macro_string_static_initialize(fake_make_operation_build, fake_make_operation_build_length),
@@ -564,8 +570,8 @@ extern "C" {
       f_macro_string_range_initialize(fake_make_operation_touch_length),
     };
 
-    const f_array_length operations_type[] = {
-      fake_make_operation_type_archive ,
+    const uint8_t operations_type[] = {
+      fake_make_operation_type_archive,
       fake_make_operation_type_build,
       fake_make_operation_type_clean,
       fake_make_operation_type_compile,
@@ -589,8 +595,9 @@ extern "C" {
       fake_make_operation_type_touch,
     };
 
-    f_array_length operation = 0;
-    f_array_length operations[section->objects.used];
+    uint8_t operation = 0;
+    uint8_t operations[section->objects.used];
+    uint8_t operation_if = 0;
 
     const f_string_static *operation_name = 0;
 
@@ -599,10 +606,10 @@ extern "C" {
     f_array_length i = 0;
     f_array_length j = 0;
 
-    memset(operations, 0, sizeof(f_array_length) * section->objects.used);
+    memset(operations, 0, sizeof(uint8_t) * section->objects.used);
     memset(arguments, 0, sizeof(f_string_dynamics) * section->objects.used);
 
-    bool has_error = F_false;
+    bool error_none = F_true;
 
     // pre-process the list to identify invalid commands so that nothing is processed if any operation is invalid.
     for (; i < section->objects.used; i++) {
@@ -632,40 +639,58 @@ extern "C" {
 
       // find and report all unknown operations before exiting.
       if (F_status_is_error(*status)) {
-        has_error = F_true;
+        error_none = F_false;
         *status = F_none;
         continue;
       }
 
       operations[i] = operation;
 
-      fake_make_operation_expand(data, section->name, operation, *operation_name, section->contents.array[i], section->quotedss.array[i], data_make, &arguments[i], status);
+      fake_make_operate_expand(data, section->name, operation, *operation_name, section->contents.array[i], section->quotedss.array[i], data_make, &arguments[i], status);
       if (F_status_is_error(*status)) {
-        has_error = F_true;
+        error_none = F_false;
         *status = F_none;
         continue;
       }
 
-      //fake_make_operation_validate();
-    } // for
+      fake_make_operate_validate(data, section->name, operation, *operation_name, *data_make, arguments[i], operation_if, status);
 
-    if (F_status_is_fine(*status) && has_error) {
-      *status = F_none;
-    }
+      if (operation_if) {
+        if (operation_if == fake_make_operation_if_type_if) {
+          operation_if = fake_make_operation_if_type_else;
+        }
+        else if (operation_if == fake_make_operation_if_type_else) {
+          if (operation == fake_make_operation_type_if) {
+            operation_if = fake_make_operation_if_type_if;
+          }
+          else {
+            operation_if = 0;
+          }
+        }
+        else {
+          operation_if = 0;
+        }
+      }
+      else if (operation == fake_make_operation_type_if) {
+        operation_if = fake_make_operation_if_type_if;
+      }
+
+      if (F_status_is_error(*status)) {
+        error_none = F_false;
+        *status = F_none;
+        continue;
+      }
+    } // for
 
-    if (F_status_is_error(*status)) {
+    if (error_none) {
       for (i = 0; i < section->objects.used; i++) {
-        f_macro_string_dynamics_delete_simple(arguments[i]);
+        // @todo: perform the operation.
+        //fake_make_operate_perform();
       } // for
-
-      return;
     }
-
-    for (; i < section->objects.used; i++) {
-      // 3: expand the operation content into dynamic strings.
-      // 4: process any variables and then re-validate any operations with replacements.
-      // 5: perform the operation.
-    } // for
+    else {
+      *status = F_status_set_error(F_failure);
+    }
 
     for (i = 0; i < section->objects.used; i++) {
       f_macro_string_dynamics_delete_simple(arguments[i]);
@@ -673,6 +698,233 @@ extern "C" {
   }
 #endif // _di_fake_make_operate_section_
 
+#ifndef _di_fake_make_operate_validate_
+  void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) {
+    if (F_status_is_error(*status)) return;
+
+    if (operation == fake_make_operation_type_archive || operation == fake_make_operation_type_run || operation == fake_make_operation_type_shell || operation == fake_make_operation_type_touch) {
+      if (arguments.used == 0) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_build) {
+      if (arguments.used > 1) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+        *status = F_status_set_error(F_failure);
+      }
+      else if (arguments.used) {
+        if (arguments.array[0].used) {
+          f_status status_file = f_file_is(arguments.array[0].string, f_file_type_regular);
+
+          if (F_status_is_error(status_file)) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "failed to find file '%s'", arguments.array[0].string);
+            *status = status_file;
+          }
+
+          if (!status_file) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "the file '%s' must be a regular file", arguments.array[0].string);
+            *status = F_status_set_error(F_failure);
+          }
+        }
+        else {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "filename argument must not be an empty string");
+        }
+      }
+    }
+    else if (operation == fake_make_operation_type_clean || operation == fake_make_operation_type_pop || operation == fake_make_operation_type_top || operation == fake_make_operation_type_skeleton) {
+      if (arguments.used) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_compile) {
+      if (arguments.used == 0) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_create || operation == fake_make_operation_type_delete) {
+      if (arguments.used) {
+        if (fl_string_dynamic_compare_string(fake_make_operation_argument_file, arguments.array[0], fake_make_operation_argument_file_length) == F_equal_to) {
+          if (arguments.used > 2) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+            *status = F_status_set_error(F_failure);
+          }
+        }
+        else if (fl_string_dynamic_compare_string(fake_make_operation_argument_directory, arguments.array[0], fake_make_operation_argument_directory_length) == F_equal_to) {
+          if (arguments.used > 3) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+            *status = F_status_set_error(F_failure);
+          }
+          else if (arguments.used == 3) {
+            if (fl_string_dynamic_compare_string(fake_make_operation_argument_recursive, arguments.array[0], fake_make_operation_argument_recursive_length) == F_equal_to_not) {
+              fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "third argument must be either '%s' or not provided at all", fake_make_operation_argument_recursive);
+              *status = F_status_set_error(F_failure);
+            }
+          }
+        }
+        else {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "unsupported file type '%s'", arguments.array[0].string);
+          *status = F_status_set_error(F_failure);
+        }
+      }
+      else {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_else) {
+      if (operation_if == fake_make_operation_if_type_else) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "must not be used after another else condition");
+        *status = F_status_set_error(F_failure);
+      }
+      else if (!operation_if) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has no preceding if condition");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_fail) {
+      if (arguments.used) {
+        if (fl_string_dynamic_compare_string(fake_make_operation_argument_error, arguments.array[0], fake_make_operation_argument_error_length) == F_equal_to_not) {
+          if (fl_string_dynamic_compare_string(fake_make_operation_argument_warning, arguments.array[0], fake_make_operation_argument_warning_length) == F_equal_to_not) {
+            if (fl_string_dynamic_compare_string(fake_make_operation_argument_ignore, arguments.array[0], fake_make_operation_argument_ignore_length) == F_equal_to_not) {
+              fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "unsupported fail type '%s'", arguments.array[0].string);
+              *status = F_status_set_error(F_failure);
+            }
+          }
+        }
+      }
+      else {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_group || operation == fake_make_operation_type_mode || operation == fake_make_operation_type_owner) {
+      if (arguments.used > 3) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+        *status = F_status_set_error(F_failure);
+      }
+      else if (arguments.used > 1) {
+        f_status status_file = f_file_is(arguments.array[1].string, f_file_type_regular);
+
+        if (F_status_is_error(status_file)) {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "failed to find file '%s'", arguments.array[1].string);
+          *status = status_file;
+        }
+
+        if (!status_file) {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "the file '%s' must be a regular file", arguments.array[1].string);
+          *status = F_status_set_error(F_failure);
+        }
+
+        if (arguments.used == 3) {
+          if (fl_string_dynamic_compare_string(fake_make_operation_argument_recursive, arguments.array[2], fake_make_operation_argument_recursive_length) == F_equal_to_not) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "third argument must be either '%s' or not provided at all", fake_make_operation_argument_recursive);
+            *status = F_status_set_error(F_failure);
+          }
+        }
+      }
+      else {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_if) {
+      if (operation_if == fake_make_operation_if_type_if) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "must not be used after another if condition");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_link) {
+      // @todo validate link is outside that the link is or is not outside the project directory.
+      if (arguments.used > 2) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+        *status = F_status_set_error(F_failure);
+      }
+      else if (arguments.used == 2) {
+        f_status status_file = F_none;
+
+        if (arguments.array[0].used) {
+          status_file = f_file_exists(arguments.array[0].string);
+
+          if (F_status_is_error(status_file) || !status_file) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "failed to find file '%s'", arguments.array[0].string);
+
+            if (status_file == F_false) {
+              *status = F_status_set_error(F_failure);
+            }
+            else {
+              *status = status_file;
+            }
+          }
+        }
+        else {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "%s filename argument must not be an empty string", fake_make_operation_argument_target);
+          *status = F_status_set_error(F_failure);
+        }
+
+        if (arguments.array[1].used) {
+          status_file = f_file_exists(arguments.array[1].string);
+
+          if (F_status_is_error(status_file) || !status_file) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "failed to find file '%s'", arguments.array[1].string);
+
+            if (status_file == F_false) {
+              *status = F_status_set_error(F_failure);
+            }
+            else {
+              *status = status_file;
+            }
+          }
+        }
+        else {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "%s filename argument must not be an empty string", fake_make_operation_argument_point);
+          *status = F_status_set_error(F_failure);
+        }
+      }
+      else {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+    else if (operation == fake_make_operation_type_operate) {
+      // @todo: validate if list name exists (and is not reserved, such as 'settings' and 'main').
+      // @todo: should recursion be checked here as well?
+    }
+    else if (operation == fake_make_operation_type_to) {
+      if (arguments.used > 1) {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "has too many arguments");
+        *status = F_status_set_error(F_failure);
+      }
+      else if (arguments.used) {
+        if (arguments.array[0].used) {
+          f_status status_file = f_file_is(arguments.array[0].string, f_file_type_directory);
+
+          if (F_status_is_error(status_file)) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "failed to find file '%s'", arguments.array[0].string);
+            *status = status_file;
+          }
+
+          if (!status_file) {
+            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "the file '%s' must be a directory file", arguments.array[0].string);
+            *status = F_status_set_error(F_failure);
+          }
+        }
+        else {
+          fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "filename argument must not be an empty string");
+        }
+      }
+      else {
+        fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
+        *status = F_status_set_error(F_failure);
+      }
+    }
+
+    // note: there is nothing to validate for fake_make_operation_type_print.
+  }
+#endif // _di_fake_make_operate_validate_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index fc4b66e43c1616b9ea93386914a2aaecc152fc67..98b1717918440edd463891013d3be12ce0cc266a 100644 (file)
@@ -126,6 +126,35 @@ extern "C" {
   };
 
   #define fake_make_operation_total 22
+
+  #define fake_make_operation_argument_file      "file"
+  #define fake_make_operation_argument_directory "directory"
+  #define fake_make_operation_argument_error     "error"
+  #define fake_make_operation_argument_ignore    "ignore"
+  #define fake_make_operation_argument_point     "point"
+  #define fake_make_operation_argument_recursive "recursive"
+  #define fake_make_operation_argument_target    "target"
+  #define fake_make_operation_argument_warning   "warning"
+
+  #define fake_make_operation_argument_file_length      4
+  #define fake_make_operation_argument_directory_length 9
+  #define fake_make_operation_argument_error_length     5
+  #define fake_make_operation_argument_ignore_length    6
+  #define fake_make_operation_argument_point_length     5
+  #define fake_make_operation_argument_recursive_length 9
+  #define fake_make_operation_argument_target_length    6
+  #define fake_make_operation_argument_warning_length   7
+
+  enum {
+    fake_make_operation_if_type_if = 1,
+    fake_make_operation_if_type_else,
+  };
+
+  enum {
+    fake_make_operation_fail_type_exit = 1,
+    fake_make_operation_fail_type_warn,
+    fake_make_operation_fail_type_ignore,
+  };
 #endif // _di_fake_make_operation_
 
 // @todo each one of these should be made available to be passed to the program as "$parameter_define[X]" for multi-value (define) or "$parameter_no_color" for single-value (no_color).
@@ -217,6 +246,8 @@ extern "C" {
     f_fss_nameds fakefile;
     f_string_dynamic buffer;
     f_array_length main;
+
+    uint8_t fail;
   } fake_make_data;
 
   #define fake_make_data_initialize { \
@@ -227,6 +258,7 @@ extern "C" {
     f_fss_nameds_initialize, \
     f_string_dynamic_initialize, \
     0, \
+    0, \
   }
 
   #define fake_macro_make_data_delete_simple(data) \
@@ -262,7 +294,10 @@ extern "C" {
 #endif // _di_fake_make_load_fakefile_
 
 /**
- * Execute the make operation.
+ * Execute the make sections and their respective operations.
+ *
+ * The first section operated on is the 'main' section.
+ * The 'settings' section is only loaded into settings and is never operated on.
  *
  * @param data
  *   The program data.
@@ -277,7 +312,7 @@ extern "C" {
 #endif // _di_fake_make_operate_
 
 /**
- * For a given make operation section, expand the content into an arguments array.
+ * For a given make section operation, expand the content into an arguments array for that operation.
  *
  * @param data
  *   The program data.
@@ -295,19 +330,17 @@ extern "C" {
  *   All make related setting data, including data from the fakefile and optionally build settings file.
  * @param arguments
  *   The expanded arguments.
- * @param section_id
- *   The array location id within the fakefile of the section to operate on.
  * @param status
  *   The return status.
  *
  *   Status codes (with error bit) are returned on any problem.
  */
-#ifndef _di_fake_make_operation_expand_
-  extern void fake_make_operation_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, const f_fss_quoteds quoteds, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) f_gcc_attribute_visibility_internal;
-#endif // _di_fake_make_operation_expand_
+#ifndef _di_fake_make_operate_expand_
+  extern void fake_make_operate_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, const f_fss_quoteds quoteds, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_operate_expand_
 
 /**
- * Process a make operation section.
+ * Perform the make operations within the given section.
  *
  * @param data
  *   The program data.
@@ -327,6 +360,61 @@ extern "C" {
   void fake_make_operate_section(const fake_data data, const f_array_length section_id, fake_make_data *data_make, f_string_lengths *section_stack, f_status *status) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_make_operate_section_
 
+/**
+ * Perform a specific make operation within the given section.
+ *
+ * @todo
+ *
+ * @param data
+ *   The program data.
+ * @param section_name
+ *   The section name.
+ * @param operation
+ *   The operation being performed.
+ * @param operation_name
+ *   The operation name.
+ * @param data_make
+ *   All make related setting data, including data from the fakefile and optionally build settings file.
+ * @param arguments
+ *   The expanded arguments.
+ * @param status
+ *   The return status.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_make_operate_perform_
+  //extern void fake_make_operate_perform(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_operate_perform_
+
+/**
+ * For a given make section operation, validate the given operation.
+ *
+ * This performs pre-operation validations.
+ * Additional issues may occure when running operations that are not detected nor detectable by this.
+ *
+ * @param data
+ *   The program data.
+ * @param section_name
+ *   The section name.
+ * @param operation
+ *   The operation being performed.
+ * @param operation_name
+ *   The operation name.
+ * @param data_make
+ *   All make related setting data, including data from the fakefile and optionally build settings file.
+ * @param arguments
+ *   The expanded arguments.
+ * @param operation_if
+ *   The if-condition status for the current operation.
+ * @param status
+ *   The return status.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_make_operate_validate_
+  extern void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_operate_validate_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index c883872444966bbfe1c56f56a6a560d3ab52607b..7d0538b46ad71e120cae3747cc30e8a258949ed2 100644 (file)
@@ -628,7 +628,7 @@ extern "C" {
     if (verbosity != fake_verbosity_quiet) {
       fprintf(f_type_error, "%c", f_string_eol[0]);
 
-      fl_color_print(f_type_error, context.error, context.reset, "ERROR: the parameter '");
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The parameter '");
       fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
 
       fl_color_print_line(f_type_error, context.error, context.reset, "' specified too many times.");
@@ -636,6 +636,42 @@ extern "C" {
   }
 #endif // _di_fake_print_error_parameter_too_many_
 
+#ifndef _di_fake_print_error_section_operation_
+  void fake_print_error_section_operation(const fake_data data, const f_string_static buffer, const f_string_range section_name, const f_string_static operation_name, const f_string message, ...) {
+    if (data.verbosity != fake_verbosity_quiet) {
+      fprintf(f_type_error, "%c", f_string_eol[0]);
+
+      fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Section '");
+
+      fl_color_print_code(f_type_error, data.context.notable);
+      f_print_string_dynamic_partial(f_type_error, buffer, section_name);
+      fl_color_print_code(f_type_error, data.context.reset);
+
+      fl_color_print(f_type_error, data.context.error, data.context.reset, "' operation '");
+
+      fl_color_print_code(f_type_error, data.context.notable);
+      f_print_string_dynamic(f_type_error, operation_name);
+      fl_color_print_code(f_type_error, data.context.reset);
+
+      fl_color_print(f_type_error, data.context.error, data.context.reset, "' ");
+
+      f_print_string_dynamic(f_type_error, data.context.error);
+
+      va_list ap;
+
+      va_start(ap, message);
+
+      vfprintf(f_type_error, message, ap);
+
+      va_end(ap);
+
+      f_print_string_dynamic(f_type_error, data.context.reset);
+
+      fl_color_print_line(f_type_error, data.context.error, data.context.reset, ".");
+    }
+  }
+#endif // _di_fake_print_error_section_operation_
+
 #ifndef _di_fake_print_warning_fakefile_object_multiple_
   void fake_print_warning_fakefile_object_multiple(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string label, const f_string name_object) {
     if (verbosity != fake_verbosity_verbose) return;
index 47053654b830795b6e506ecfddfb1c9d88acf6a6..74b0a59780145d3f59df58b3a0792a2fa93013a1 100644 (file)
@@ -264,6 +264,26 @@ extern "C" {
 #endif // _di_fake_print_error_parameter_too_many_
 
 /**
+ * Print a specific error message for a named section operation.
+ *
+ * @param data
+ *   The program data.
+ * @param buffer
+ *   A buffer containing the contents of the fakefile file.
+ * @param section_name
+ *   The range within the buffer representing the section name.
+ * @param operation_name
+ *   The name of the operation designated to have an error.
+ * @param message
+ *   The error message.
+ * @param ...
+ *   Variable arguments, processed in the same way fprintf() processes them.
+ */
+#ifndef _di_fake_print_error_section_operation_
+  extern void fake_print_error_section_operation(const fake_data data, const f_string_static buffer, const f_string_range section_name, const f_string_static operation_name, const f_string message, ...) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_error_section_operation_
+
+/**
  * Print warning message when fakefile has too many objects with the same name.
  *
  * @param context
diff --git a/level_3/fake/documents/fakefile.txt b/level_3/fake/documents/fakefile.txt
new file mode 100644 (file)
index 0000000..40b9f84
--- /dev/null
@@ -0,0 +1,6 @@
+# fss-0002
+
+Fakefile Documentation:
+  This describes intent and purposes of the fakefile file settings.
+  For specific details on the allowed formatting, see the fakefile.txt under the specifications folder.
+
index 9ae91ab80b6a6e31aa2e0a2e9c6b5478caa2fe3c..08b1890eb27ec8fc527bda944c2a9f8f50914f24 100644 (file)
@@ -1,4 +1,4 @@
-# fss-002
+# fss-0002
 
 Defines Specification:
   The build settings "defines" file follows the FSS-0000 (Basic) format.
index fe925be33901ddacb5ee6ef1e3dde0706c689852..2b9654d3e799ae1666df169152ff8dc94f02236e 100644 (file)
@@ -1,4 +1,4 @@
-# fss-002
+# fss-0002
 
 Dependencies Specification:
   The build settings "dependencies" file follows the FSS-0000 (Basic) format.
diff --git a/level_3/fake/specifications/fakefile.txt b/level_3/fake/specifications/fakefile.txt
new file mode 100644 (file)
index 0000000..57d5180
--- /dev/null
@@ -0,0 +1,3 @@
+# fss-0002
+
+Fakefile Specification:
index 092558eb945d65781e4a1d3ec5c32bcbbe31f09a..0ef3624f23e5144c3199acfa45d2651957d3ddea 100644 (file)
@@ -1,4 +1,4 @@
-# fss-002
+# fss-0002
 
 Settings Specification:
   The build settings "settings" file follows the FSS-0001 (Extended) format.