]> Kevux Git Server - fll/commitdiff
Progress: featureless make.
authorKevin Day <thekevinday@gmail.com>
Sat, 18 Jul 2020 05:08:58 +0000 (00:08 -0500)
committerKevin Day <thekevinday@gmail.com>
Sat, 18 Jul 2020 05:09:17 +0000 (00:09 -0500)
I flip-flopped on how I wanted to handle the print functions and need to update/rewrite them again after this commit.
The end of an operation always prints the section, line number, etc.., so I do not need as many custom print functions as I ended up doing in this commit.

This begins processing the stack path.

The pre-process idea just will not work because the argument length is not known until after expansion.
This throws away the idea of having a pre-process validation on the operation rules, unfortunately.

There are some mistakes in the expand function when handling arguments that need to be fixed.

level_3/fake/c/private-build.c
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/data/build/fakefile

index 5f653de3d7187759c8af758cd8805c39e76713d2..3a570b477ca41a294c402c90878abb3b8d70692f 100644 (file)
@@ -235,7 +235,7 @@ extern "C" {
         if (F_status_is_error(*status)) {
           if (data.verbosity == fake_verbosity_verbose) {
             for (f_string_length j = 0; j < failures.used; j++) {
-              fake_print_error_operation(data.context, data.verbosity, F_status_set_fine(*status), "fl_directory_copy_content", "copy contents of", "to", path_source.string, destination.string, F_true);
+              fake_print_error_build_operation_file(data.context, data.verbosity, F_status_set_fine(*status), "fl_directory_copy_content", "copy contents of", "to", path_source.string, destination.string, F_true);
             } // for
 
             if (F_status_set_fine(*status) != F_failure) {
@@ -245,7 +245,7 @@ extern "C" {
             break;
           }
           else if (data.verbosity != fake_verbosity_quiet) {
-            fake_print_error_operation(data.context, data.verbosity, F_status_set_fine(*status), "fl_directory_copy_content", "copy contents of", "to", path_source.string, destination.string, F_true);
+            fake_print_error_build_operation_file(data.context, data.verbosity, F_status_set_fine(*status), "fl_directory_copy_content", "copy contents of", "to", path_source.string, destination.string, F_true);
           }
 
           break;
@@ -269,7 +269,7 @@ extern "C" {
         *status = f_file_copy(path_source.string, destination_file.string, mode, f_file_default_read_size, F_false);
 
         if (F_status_is_error(*status)) {
-          fake_print_error_operation(data.context, data.verbosity, F_status_set_fine(*status), "f_file_copy", "copy", "to", path_source.string, destination_file.string, F_true);
+          fake_print_error_build_operation_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_copy", "copy", "to", path_source.string, destination_file.string, F_true);
           break;
         }
 
index 92b04c0ee8af5739d7ef9206106739a35fc80a0b..9fe2566f06fe6acb4c3f3a3f79f4f9825693d757 100644 (file)
 extern "C" {
 #endif
 
+#ifndef _di_fake_make_assure_inside_project_
+  f_return_status fake_make_assure_inside_project(const fake_data data, const f_string_static path, fake_make_data *data_make) {
+
+    data_make->path_real.used = 0;
+
+    f_status status = f_path_real(path.string, &data_make->path_real);
+    if (F_status_is_error(status)) return status;
+
+    const f_string_range range = f_macro_string_range_initialize(data_make->path.stack.array[0].used);
+
+    if (range.start <= range.stop) {
+      status = fl_string_dynamic_partial_compare(data_make->path.stack.array[0], path, range, range);
+      if (F_status_is_error(status)) return status;
+
+      if (status) {
+        if (data_make->path_real.used == data_make->path.stack.array[0].used) {
+          return F_true;
+        }
+
+        if (data_make->path_real.string[data_make->path.stack.array[0].used] == f_path_separator[0]) {
+          return F_true;
+        }
+      }
+    }
+
+    return F_status_set_error(F_false);
+  }
+#endif // _di_fake_make_assure_inside_project_
+
 #ifndef _di_fake_make_load_fakefile_
   void fake_make_load_fakefile(const fake_data data, fake_make_data *data_make, f_status *status) {
     if (F_status_is_error(*status)) return;
@@ -733,97 +762,69 @@ extern "C" {
     memset(operations, 0, sizeof(uint8_t) * section->objects.used);
     memset(arguments, 0, sizeof(f_string_dynamics) * section->objects.used);
 
-    bool error_none = F_true;
-    bool process = F_true;
-
-    do {
-      // pre-process the list to identify invalid commands so that nothing is processed if any operation can be detected as invalid by the pre-process validation.
-      process = !process;
-
-      for (i = 0; i < section->objects.used; i++) {
-        operation = 0;
-        operation_name = 0;
+    for (i = 0; i < section->objects.used; i++) {
+      operation = 0;
+      operation_name = 0;
 
-        for (j = 0; j < fake_make_operation_total; j++) {
-          if (fl_string_dynamic_partial_compare(operations_name[j], data_make->buffer, operations_range[j], section->objects.array[i]) == F_equal_to) {
-            operation = operations_type[j];
-            operation_name = &operations_name[j];
-            break;
-          }
-        } // for
+      for (j = 0; j < fake_make_operation_total; j++) {
+        if (fl_string_dynamic_partial_compare(operations_name[j], data_make->buffer, operations_range[j], section->objects.array[i]) == F_equal_to) {
+          operation = operations_type[j];
+          operation_name = &operations_name[j];
+          break;
+        }
+      } // for
 
-        if (operation == 0) {
-          fake_print_error_fakefile_section_operation_unknown(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i]);
+      if (operation == 0) {
+        fake_print_error_fakefile_section_operation_unknown(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i]);
 
-          *status = F_status_set_error(F_invalid);
-        }
-        else if (operation == fake_make_operation_type_operate) {
-          if (section_stack->used == fake_make_section_stack_max) {
-            fake_print_error_fakefile_section_operation_stack_max(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max);
+        *status = F_status_set_error(F_invalid);
+      }
+      else if (operation == fake_make_operation_type_operate) {
+        if (section_stack->used == fake_make_section_stack_max) {
+          fake_print_error_fakefile_section_operation_stack_max(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max);
 
-            *status = F_status_set_error(F_recurse);
-          }
+          *status = F_status_set_error(F_recurse);
         }
+      }
 
-        // find and report all unknown operations before exiting.
-        if (F_status_is_error(*status)) {
-          error_none = F_false;
-          *status = F_none;
-          continue;
-        }
+      if (F_status_is_error(*status)) break;
 
-        operations[i] = operation;
+      operations[i] = operation;
 
-        if (process) {
-          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)) {
-            error_none = F_false;
-            continue;
-          }
-        }
+      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)) break;
 
-        fake_make_operate_validate(data, section->name, operation, *operation_name, *data_make, arguments[i], operation_if, process, status);
+      fake_make_operate_validate(data, section->name, operation, *operation_name, *data_make, arguments[i], operation_if, status);
 
-        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;
-            }
+      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 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;
+        else {
+          operation_if = 0;
         }
+      }
+      else if (operation == fake_make_operation_type_if) {
+        operation_if = fake_make_operation_if_type_if;
+      }
 
-        if (error_none && process) {
-          fake_make_operate_perform(data, section->name, operation, *operation_name, arguments[i], operation_if, data_make, status);
+      if (F_status_is_error(*status)) break;
 
-          if (F_status_is_error(*status)) {
-            fake_print_error_fakefile_section_operation_failed(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i]);
-            break;
-          }
-        }
-      } // for
-    } while (error_none && !process);
+      fake_make_operate_perform(data, section->name, operation, *operation_name, section->objects.array[i], arguments[i], operation_if, data_make, status);
 
-    if (!error_none && F_status_is_fine(*status)) {
-      *status = F_status_set_error(F_failure);
-    }
+      if (F_status_is_error(*status)) {
+        fake_print_error_fakefile_section_operation_failed(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i]);
+        break;
+      }
+    } // for
 
     for (i = 0; i < section->objects.used; i++) {
       f_macro_string_dynamics_delete_simple(arguments[i]);
@@ -832,7 +833,7 @@ extern "C" {
 #endif // _di_fake_make_operate_section_
 
 #ifndef _di_fake_make_operate_perform_
-  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 f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) {
+  void fake_make_operate_perform(const fake_data data, const f_string_range section_name, const uint8_t operation, const f_string_static operation_name, const f_string_range operation_range, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) {
     if (F_status_is_error(*status)) return;
 
     if (operation == fake_make_operation_type_archive) {
@@ -865,6 +866,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_create) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -877,6 +879,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_delete) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -893,6 +896,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_group) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -905,6 +909,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_link) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -912,6 +917,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_mode) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -924,6 +930,7 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_owner) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -970,16 +977,70 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_to) {
-      // @todo: change directory.
+      *status = fake_make_assure_inside_project(data, arguments.array[0], data_make);
+      if (F_status_is_error(*status)) {
+        fake_print_error_fakefile_section_operation_path_outside(data.context, data.verbosity, *status, "fake_make_assure_inside_project", data_make->buffer, section_name, operation_range, arguments.array[0].string);
+
+        if (F_status_set_fine(*status) == F_false) {
+          *status = F_status_set_error(F_failure);
+        }
+
+        return;
+      }
+
+      *status = f_path_change(arguments.array[0].string);
+      if (F_status_is_error(*status)) {
+        fake_print_error_fakefile_section_line(data.context, data.verbosity, F_status_set_fine(*status), "f_path_change", data_make->buffer, section_name, operation_range, arguments.array[0].string);
+      }
+      else {
+        if (data_make->path.stack.used == data_make->path.stack.size) {
+          if (data_make->path.stack.used + 1 >= f_array_length_size) {
+            *status = F_status_set_error(F_buffer_too_large);
+            fake_print_error_fakefile_section_line(data.context, data.verbosity, F_buffer_too_large, "f_macro_string_dynamics_resize", data_make->buffer, section_name, operation_range, "path stack");
+            return;
+          }
+
+          if (data_make->path.stack.used + f_memory_default_allocation_step >= f_array_length_size) {
+            f_macro_string_dynamics_resize(*status, data_make->path.stack, data_make->path.stack.size + 1);
+          }
+          else {
+            f_macro_string_dynamics_resize(*status, data_make->path.stack, data_make->path.stack.size + f_memory_default_allocation_step);
+          }
+
+          if (F_status_is_error(*status)) {
+            fake_print_error_fakefile_section_line(data.context, data.verbosity, F_status_set_fine(*status), "f_macro_string_dynamics_resize", data_make->buffer, section_name, operation_range, 0);
+            return;
+          }
+        }
+
+        // copy the entire real path, including the trailing NULL.
+        data_make->path_real.used++;
+
+        fl_string_dynamic_append_nulless(data_make->path_real, &data_make->path.stack.array[data_make->path.stack.used]);
+
+        // reset the used to disclude the trailing NULL.
+        data_make->path_real.used--;
+
+        if (F_status_is_error(*status)) {
+          fake_print_error_fakefile_section_line(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_append_nulless", data_make->buffer, section_name, operation_range, 0);
+          return;
+        }
+
+        data_make->path.stack.used++;
+
+        // @todo: if verbose, then print the directory change (strip out the project root part of the path when printing).
+      }
+
       return;
     }
 
     if (operation == fake_make_operation_type_top) {
-      // @todo: change directory.
+      *status = f_path_change_at(data_make->path.top);
       return;
     }
 
     if (operation == fake_make_operation_type_touch) {
+      // fake_make_assure_inside_project
       // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
       //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
       //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
@@ -998,6 +1059,8 @@ extern "C" {
     if (F_status_is_error(*status)) {
       // @todo: convert F_status_set_fine(*status) to a string and assign that instead of 1. (need a convert function from llu to string.)
       status2 = fl_string_append("1", 1, &data_make->setting_make.parameter.array[0].value.array[0]);
+
+      // fake_print_error_fakefile_section_line(data.context, data.verbosity, F_status_set_fine(*status), "fake_clean_operate", data_make.buffer, section_name, operation_range, arguments.array[0].string);
     }
     else {
       // @todo: convert return_code to a string and assign that instead of 0. (need a convert function from llu to string.)
@@ -1019,7 +1082,7 @@ extern "C" {
 #endif // _di_fake_make_operate_perform_process_return_
 
 #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, const bool process, f_status *status) {
+  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) {
@@ -1033,7 +1096,7 @@ extern "C" {
         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 && process) {
+      else if (arguments.used) {
         if (arguments.array[0].used) {
           f_status status_file = f_file_is(arguments.array[0].string, f_file_type_regular);
 
@@ -1066,30 +1129,28 @@ extern "C" {
     }
     else if (operation == fake_make_operation_type_create || operation == fake_make_operation_type_delete) {
       if (arguments.used) {
-        if (process) {
-          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);
-            }
+        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");
+        }
+        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 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, "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");
@@ -1098,10 +1159,8 @@ extern "C" {
     }
     else if (operation == fake_make_operation_type_define) {
       if (arguments.used) {
-        if (process) {
-          // @todo: validate that first argument is a valid define name.
-          // @todo: if arguments.used is 1, then value is assigned to null.
-        }
+        // @todo: validate that first argument is a valid define name.
+        // @todo: if arguments.used is 1, then value is assigned to null.
       }
       else {
         fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "requires arguments");
@@ -1120,13 +1179,11 @@ extern "C" {
     }
     else if (operation == fake_make_operation_type_fail) {
       if (arguments.used) {
-        if (process) {
-          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_warn, arguments.array[0], fake_make_operation_argument_warn_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);
-              }
+        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_warn, arguments.array[0], fake_make_operation_argument_warn_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);
             }
           }
         }
@@ -1142,24 +1199,22 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
       else if (arguments.used > 1) {
-        if (process) {
-          f_status status_file = f_file_is(arguments.array[1].string, f_file_type_regular);
+        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 (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 (!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);
-            }
+        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);
           }
         }
       }
@@ -1181,47 +1236,45 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
       else if (arguments.used == 2) {
-        if (process) {
-          f_status status_file = F_none;
+        f_status status_file = F_none;
 
-          if (arguments.array[0].used) {
-            status_file = f_file_exists(arguments.array[0].string);
+        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 (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;
-              }
+            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);
-          }
+        }
+        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 (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 (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;
-              }
+            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, "%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");
@@ -1238,24 +1291,22 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
       else if (arguments.used) {
-        if (process) {
-          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 (arguments.array[0].used) {
+          f_status status_file = f_file_is(arguments.array[0].string, f_file_type_directory);
 
-            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);
-            }
+          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;
           }
-          else {
-            fake_print_error_section_operation(data, data_make.buffer,section_name, operation_name, "filename argument must not be an empty string");
+
+          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");
index b0a3330c84a57f1b83472aa24a464000c90b4ff4..b237fb92f907d30f6317dbcf44b032787aedf2a8 100644 (file)
@@ -271,7 +271,9 @@ extern "C" {
     fake_make_path path;
 
     f_fss_nameds fakefile;
+
     f_string_dynamic buffer;
+    f_string_dynamic path_real; // used as a cache for determining a real path.
 
     f_array_length main;
 
@@ -286,6 +288,7 @@ extern "C" {
     fake_make_path_initialize, \
     f_fss_nameds_initialize, \
     f_string_dynamic_initialize, \
+    f_string_dynamic_initialize, \
     0, \
     0, \
   }
@@ -297,10 +300,32 @@ extern "C" {
     fake_macro_make_parameter_delete_simple(data.parameter) \
     fake_macro_make_path_delete_simple(data.path) \
     f_macro_fss_nameds_delete_simple(data.fakefile) \
-    f_macro_string_dynamic_delete_simple(data.buffer)
+    f_macro_string_dynamic_delete_simple(data.buffer) \
+    f_macro_string_dynamic_delete_simple(data.path_real)
 #endif // _di_fake_make_data_
 
 /**
+ * Assure that a path is within the project root path.
+ *
+ * @param data
+ *   The program data.
+ * @param path
+ *   file path to get the real path of.
+ * @param data_make
+ *   All make related setting data, including data from the fakefile and optionally build settings file.
+ *   The data_make.path_real will be updated to reflect the full path to this file.
+ *
+ * @return
+ *   F_true if inside the project.
+ *   F_false (with error bit) if path exists outside of the root project path.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_make_assure_inside_project_
+  extern f_return_status fake_make_assure_inside_project(const fake_data data, const f_string_static path, fake_make_data *data_make) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_assure_inside_project_
+
+/**
  * Find the fake file, load it, validate it, and process it.
  *
  * This will process any additional files as necessary, such as the build settings file.
@@ -312,7 +337,6 @@ extern "C" {
  * @param status
  *   The return status.
  *
- * @return
  *   F_none on success.
  *
  *   Status codes (with error bit) are returned on any problem.
@@ -398,9 +422,11 @@ extern "C" {
  * @param section_name
  *   The section name.
  * @param operation
- *   The operation being performed.
+ *   The operation type.
  * @param operation_name
  *   The operation name.
+ * @param operation_range
+ *   The range within the buffer pointing to the operation.
  * @param arguments
  *   The expanded arguments.
  * @param operation_if
@@ -413,7 +439,7 @@ extern "C" {
  *   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 f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) f_gcc_attribute_visibility_internal;
+  extern void fake_make_operate_perform(const fake_data data, const f_string_range section_name, const uint8_t operation, const f_string_static operation_name, const f_string_range operation_range, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_make_operate_perform_
 
 /**
@@ -452,16 +478,13 @@ extern "C" {
  *   The expanded arguments.
  * @param operation_if
  *   The if-condition status for the current operation.
- * @param process
- *   Set to TRUE if this is a process validation, FALSE if this is a pre-process validation.
- *   A pre-process validation does not check for content because content is not yet expanded.
  * @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, const bool process, f_status *status) f_gcc_attribute_visibility_internal;
+  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_
 
 /**
index 466b982c2f220c8a5b401075ed3116cacdfc27b3..68d495eef50ad7fba3059ded9439ce6dae3cb718 100644 (file)
@@ -44,6 +44,227 @@ extern "C" {
   }
 #endif // _di_fake_print_error_
 
+#ifndef _di_fake_print_error_build_operation_file_
+  bool fake_print_error_build_operation_file(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string operation, const f_string how, const f_string source, const f_string destination, const bool fallback) {
+
+    if (status == F_file_found_not) {
+      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: Failed to find '");
+
+        if (f_file_exists(source) == F_true) {
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+        else {
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+        }
+
+        fl_color_print(f_type_error, context.error, context.reset, "' while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_parameter) {
+      if (verbosity != fake_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+        fl_color_print(f_type_error, context.error, context.reset, "() to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_name) {
+      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: Invalid name for '");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' or '");
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_memory_out) {
+      if (verbosity != fake_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "CRITICAL ERROR: Unable to allocate memory, while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_number_overflow) {
+      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: Overflow while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_directory) {
+      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: Invalid directory while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_access_denied) {
+      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: Access denied while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_loop) {
+      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: Loop while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_prohibited) {
+      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: Prohibited by system while trying to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_directory_found_not) {
+      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: Failed to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "' due to an invalid directory in the path.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_failure) {
+      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: Failed to %s '", operation);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+        if (destination) {
+          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+        }
+
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (fake_print_error(context, verbosity, status, function, F_false) == F_unknown && fallback && verbosity != fake_verbosity_quiet) {
+      fprintf(f_type_error, "%c", f_string_eol[0]);
+      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
+      fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
+      fl_color_print(f_type_error, context.error, context.reset, ") occurred while trying to %s '", operation);
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+
+      if (destination) {
+        fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+      }
+
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+
+    return F_true;
+  }
+#endif // _di_fake_print_error_build_operation_file_
+
 #ifndef _di_fake_print_error_fakefile_section_
   bool fake_print_error_fakefile_section(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const bool fallback) {
 
@@ -67,36 +288,52 @@ extern "C" {
 #endif // _di_fake_print_error_fakefile_section_
 
 #ifndef _di_fake_print_error_fakefile_section_line_
-  bool fake_print_error_fakefile_section_line(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const bool fallback) {
+  void fake_print_error_fakefile_section_line(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const f_string string) {
+    if (verbosity == fake_verbosity_quiet) return;
 
     f_string_length line = 0;
 
     f_fss_count_lines(buffer, operation_name.start, &line);
 
-    if (fake_print_error(context, verbosity, status, function, F_false) == F_unknown && fallback && verbosity != fake_verbosity_quiet) {
-      fprintf(f_type_error, "%c", f_string_eol[0]);
+    fprintf(f_type_error, "%c", f_string_eol[0]);
+
+    if (status == F_parameter) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: Invalid parameter");
+    }
+    else if (status == F_memory_allocation || status == F_memory_reallocation) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: Unable to allocate memory");
+    }
+    else if (status == F_buffer_too_large) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: Maximum size reached for %s array", string ? string : "");
+    }
+    else {
       fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
       fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
-      fl_color_print(f_type_error, context.error, context.reset, ") occurred while calling ");
+      fl_color_print(f_type_error, context.error, context.reset, ") occurred");
+    }
+
+    if (function) {
+      fl_color_print(f_type_error, context.error, context.reset, " while calling ");
       fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
       fl_color_print(f_type_error, context.error, context.reset, "() for section '");
+    }
+    else {
+      fl_color_print(f_type_error, context.error, context.reset, " while operating section '");
+    }
 
-      fl_color_print_code(f_type_error, context.notable);
-      f_print_string_dynamic_partial(f_type_error, buffer, section_name);
-      fl_color_print_code(f_type_error, context.reset);
-
-      fl_color_print(f_type_error, context.error, context.reset, " on line ");
-      fl_color_print(f_type_error, context.notable, context.reset, "%llu", line);
-      fl_color_print(f_type_error, context.error, context.reset, ", operation '");
+    fl_color_print_code(f_type_error, context.notable);
+    f_print_string_dynamic_partial(f_type_error, buffer, section_name);
+    fl_color_print_code(f_type_error, context.reset);
 
-      fl_color_print_code(f_type_error, context.notable);
-      f_print_string_dynamic_partial(f_type_error, buffer, operation_name);
-      fl_color_print_code(f_type_error, context.reset);
+    fl_color_print(f_type_error, context.error, context.reset, " on line ");
+    fl_color_print(f_type_error, context.notable, context.reset, "%llu", line);
+    fl_color_print(f_type_error, context.error, context.reset, ", operation '");
 
-      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-    }
+    fl_color_print_code(f_type_error, context.notable);
+    f_print_string_dynamic_partial(f_type_error, buffer, operation_name);
+    fl_color_print_code(f_type_error, context.reset);
 
-    return F_true;
+    fl_color_print_line(f_type_error, context.error, context.reset, "'.");
   }
 #endif // _di_fake_print_error_fakefile_section_line_
 
@@ -416,226 +653,40 @@ extern "C" {
   }
 #endif // _di_fake_print_error_fss
 
-#ifndef _di_fake_print_error_operation_
-  bool fake_print_error_operation(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string operation, const f_string how, const f_string source, const f_string destination, const bool fallback) {
-
-    if (status == F_file_found_not) {
-      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: Failed to find '");
-
-        if (f_file_exists(source) == F_true) {
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-        else {
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-        }
-
-        fl_color_print(f_type_error, context.error, context.reset, "' while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_parameter) {
-      if (verbosity != fake_verbosity_quiet) {
-        fprintf(f_type_error, "%c", f_string_eol[0]);
-        fl_color_print(f_type_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling ");
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
-        fl_color_print(f_type_error, context.error, context.reset, "() to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_name) {
-      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: Invalid name for '");
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' or '");
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_memory_out) {
-      if (verbosity != fake_verbosity_quiet) {
-        fprintf(f_type_error, "%c", f_string_eol[0]);
-        fl_color_print(f_type_error, context.error, context.reset, "CRITICAL ERROR: Unable to allocate memory, while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_number_overflow) {
-      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: Overflow while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_directory) {
-      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: Invalid directory while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_access_denied) {
-      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: Access denied while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_loop) {
-      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: Loop while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
-
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
-
-      return F_false;
-    }
-
-    if (status == F_prohibited) {
-      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: Prohibited by system while trying to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
+#ifndef _di_fake_print_error_fakefile_section_operation_path_outside_
+  void fake_print_error_fakefile_section_operation_path_outside(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const f_string path) {
+    if (verbosity != fake_verbosity_quiet) {
 
-        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
-      }
+      if (F_status_set_fine(status) == F_false) {
+        f_string_length line = 0;
 
-      return F_false;
-    }
+        f_fss_count_lines(buffer, operation_name.start, &line);
 
-    if (status == F_directory_found_not) {
-      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: Failed to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: the path '");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", path);
+        fl_color_print(f_type_error, context.error, context.reset, "' is outside the project root for section '");
 
-        fl_color_print_line(f_type_error, context.error, context.reset, "' due to an invalid directory in the path.");
-      }
-
-      return F_false;
-    }
+        fl_color_print_code(f_type_error, context.notable);
+        f_print_string_dynamic_partial(f_type_error, buffer, section_name);
+        fl_color_print_code(f_type_error, context.reset);
 
-    if (status == F_failure) {
-      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: Failed to %s '", operation);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
+        fl_color_print(f_type_error, context.error, context.reset, " on line ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%llu", line);
+        fl_color_print(f_type_error, context.error, context.reset, ", operation '");
 
-        if (destination) {
-          fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-          fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
-        }
+        fl_color_print_code(f_type_error, context.notable);
+        f_print_string_dynamic_partial(f_type_error, buffer, operation_name);
+        fl_color_print_code(f_type_error, context.reset);
 
         fl_color_print_line(f_type_error, context.error, context.reset, "'.");
       }
-
-      return F_false;
-    }
-
-    if (fake_print_error(context, verbosity, status, function, F_false) == F_unknown && fallback && verbosity != fake_verbosity_quiet) {
-      fprintf(f_type_error, "%c", f_string_eol[0]);
-      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
-      fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
-      fl_color_print(f_type_error, context.error, context.reset, ") occurred while trying to %s '", operation);
-      fl_color_print(f_type_error, context.notable, context.reset, "%s", source);
-
-      if (destination) {
-        fl_color_print(f_type_error, context.error, context.reset, "' %s '", how);
-        fl_color_print(f_type_error, context.notable, context.reset, "%s", destination);
+      else {
+        fake_print_error_fakefile_section_line(context, verbosity, status, function, buffer, section_name, operation_name, path);
       }
-
-      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
     }
-
-    return F_true;
   }
-#endif // _di_fake_print_error_operation_
+#endif // _di_fake_print_error_fakefile_section_operation_path_outside_
 
 #ifndef _di_fake_print_error_parameter_missing_value_
   void fake_print_error_parameter_missing_value(const fl_color_context context, const uint8_t verbosity, const f_string parameter) {
index 86d42ef07309e7f82073b22322c2d557b582d374..72604654652575afa8a99f5dc37503d65d000bf4 100644 (file)
@@ -35,6 +35,40 @@ extern "C" {
 #endif // _di_fake_print_error_
 
 /**
+ * Print build operation file error messages.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The error status code to report on.
+ * @param function
+ *   The name of the function where the error happened.
+ * @param operation
+ *   The operation performed.
+ * @param source
+ *   The operation source.
+ *   Set to 0 to disable.
+ * @param destination
+ *   The operation destination, if applicable.
+ *   Requires source to be non-zero.
+ *   Set to 0 to disable.
+ * @param how
+ *   The how the operation is perform, such as "to" in "copy" source "to" destination.
+ *   Requires source and destination to be non-zero.
+ * @param fallback
+ *   Set to F_true to print the fallback error message for unknown errors.
+ *
+ * @return
+ *   F_true is returned if the status code has no print message.
+ *   F_false is returned on successful print of known errors.
+ */
+#ifndef _di_fake_print_error_operation_file_
+  extern bool fake_print_error_build_operation_file(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string operation, const f_string source, const f_string destination, const f_string how, const bool fallback) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_error_operation_file_
+
+/**
  * Print error messages when processing some fakefile section.
  *
  * @param context
@@ -71,21 +105,19 @@ extern "C" {
  *   The status code representing an error.
  * @param function
  *   The name of the function where the error happened.
+ *   Set to 0 to disable.
  * @param buffer
  *   The buffer containing the fakefile data.
  * @param section_name
  *   The range within the buffer representing the section name.
  * @param operation_name
  *   The range within the buffer representing the operation name within the section.
- * @param fallback
- *   Set to F_true to print the fallback error message for unknown errors.
- *
- * @return
- *   F_none is returned on successful print of known errors.
- *   F_unknown is returned if the status code has no print message.
+ * @param string
+ *   A string used by certain error conditions.
+ *   Set to 0 disable.
  */
 #ifndef _di_fake_print_error_fakefile_section_line_
-  extern bool fake_print_error_fakefile_section_line(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const bool fallback) f_gcc_attribute_visibility_internal;
+  extern void fake_print_error_fakefile_section_line(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const f_string string) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_print_error_fakefile_section_line_
 
 /**
@@ -107,6 +139,30 @@ extern "C" {
 #endif // _di_fake_print_error_fakefile_section_operation_failed_
 
 /**
+ * Print error messages when processing some fakefile section, for a specific line and operation, and that operation has a path outside of the project root.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The status code representing an error.
+ * @param function
+ *   The name of the function where the error happened.
+ * @param buffer
+ *   The buffer containing the fakefile data.
+ * @param section_name
+ *   The range within the buffer representing the section name.
+ * @param operation_name
+ *   The range within the buffer representing the operation name within the section.
+ * @param path
+ *   The path that is outside of the project path.
+ */
+#ifndef _di_fake_print_error_fakefile_section_operation_path_outside_
+  extern void fake_print_error_fakefile_section_operation_path_outside(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string_static buffer, const f_string_range section_name, const f_string_range operation_name, const f_string path) f_gcc_attribute_visibility_internal;
+#endif // _fake_print_error_fakefile_section_operation_path_outside_
+
+/**
  * Print error messages when processing some fakefile section, for a specific line and operation, and that the max stack depth is reached.
  *
  * @param context
@@ -218,40 +274,9 @@ extern "C" {
  *   F_true is returned if the status code has no print message.
  *   F_false is returned on successful print of known errors.
  */
-#ifndef _di_fake_print_error_fss
+#ifndef _di_fake_print_error_fss_
   extern bool fake_print_error_fss(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string path_file, const f_string_range range, const bool fallback) f_gcc_attribute_visibility_internal;
-#endif // _di_fake_print_error_fss
-
-/**
- * Print operation error messages.
- *
- * @param context
- *   The color context.
- * @param verbosity
- *   The verbosity level, which determines if and what should be printed.
- * @param status
- *   The error status code to report on.
- * @param function
- *   The name of the function where the error happened.
- * @param operation
- *   The operation performed.
- * @param how
- *   The how the operation is perform, such as "to" in "copy" source "to" destination.
- * @param source
- *   The operation source.
- * @param destination
- *   The operation destination, if applicable.
- *   Set to 0 to disable.
- * @param fallback
- *   Set to F_true to print the fallback error message for unknown errors.
- *
- * @return
- *   F_true is returned if the status code has no print message.
- *   F_false is returned on successful print of known errors.
- */
-#ifndef _di_fake_print_error_operation_
-  extern bool fake_print_error_operation(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string operation, const f_string how, const f_string source, const f_string destination, const bool fallback) f_gcc_attribute_visibility_internal;
-#endif // _di_fake_print_error_operation_
+#endif // _di_fake_print_error_fss_
 
 /**
  * Print an error message for when the parameter is missing its accompanying value.
index 979692eeb2cd7449710ab815815b9c809f88879d..0f6aa6a9a429264afa6a5bf10126540d6e518368 100644 (file)
@@ -25,3 +25,12 @@ main:
   build
 
   print Result = \'parameter:"result"'
+
+  to sources
+  print should have changed to sources
+
+  to invalid
+  print should have errored before this
+
+  to /tmp
+  print should not be allowed to leave project root.