]> Kevux Git Server - fll/commitdiff
Progress: Focus on directory recursion related changes and Featureless Make.
authorKevin Day <kevin@kevux.org>
Fri, 14 Apr 2023 00:42:44 +0000 (19:42 -0500)
committerKevin Day <kevin@kevux.org>
Fri, 14 Apr 2023 00:42:44 +0000 (19:42 -0500)
This should wrap up most of the initial work creating the copy recursion.
There are other areas to update but this is the start.

I forgot and accidentally added "custom" to the fl_directory_do_t.
I should be using the custom from the state variable.

Now that I have had a chance to experiment with the new fl_directory_do() design I have managed to come to some more decisions.
The parameter checking will not have the f_directory_recurse_do_flag_path_e bit set for the error handler.
The before and after should be called not on just the directory recursion but also before and after each non-recursion file action.
This better allows for setting things up in a sane way as is appropriate when performing a copy operation.

I decided to provide some convenience variables.
This is not a great idea for a recursive function but it is a start.
I should investigate moving this array into a static array that is global to the private file but not shared beyond that.
This would prevent the cost of allocating the array for each recursion.

It would be a good idea to bind some of the strings to the cache and update them to better avoid additional allocations.
I think I need a cache_3 to achieve this.
I added todo comments in areas where I think this is relevant.

Do some minor clean ups on the printing in certain areas.

17 files changed:
level_0/f_directory/c/directory/type.h
level_0/f_iki/c/iki.c
level_1/fl_directory/c/directory.c
level_1/fl_directory/c/directory.h
level_1/fl_directory/c/private-directory.c
level_1/fl_directory/c/private-directory.h
level_3/fake/c/main/build.c
level_3/fake/c/main/build.h
level_3/fake/c/main/build/load.c
level_3/fake/c/main/clean.c
level_3/fake/c/main/common/print.c
level_3/fake/c/main/common/print.h
level_3/fake/c/main/fake.c
level_3/fake/c/main/print/error.c
level_3/fake/c/main/print/error.h
level_3/fake/c/main/print/message.c
level_3/fake/c/main/skeleton.c

index 01e505ccc48f0cce77faee71a07c845e7d3929f6..29f46b52e853d89e0c834d1b41cdbfc08d59e040 100644 (file)
@@ -249,8 +249,6 @@ extern "C" {
  * path_cache: A path-related cache made available for the caller to use, such as combining the path and the file name in the action callback.
  * path_top:   A pointer to the top path string, used for error handling and printing (generally assigned internally).
  *
- * custom: Custom data defined by and used by the caller. Set to NULL to not use.
- *
  * action: A callback used for performing some action (this is required to do anything).
  * handle: A callback used for performing error handling during recursion directly relating to a file.
  *
@@ -271,15 +269,13 @@ extern "C" {
     f_string_dynamic_t path_cache;
     const f_string_static_t *path_top;
 
-    void *custom;
-
     void (*action)(void * const recurse, const f_string_static_t name, const uint16_t flag);
     void (*handle)(void * const recurse, const f_string_static_t name, const uint16_t flag);
   } f_directory_recurse_do_t;
 
   #define f_directory_recurse_do_t_initialize { \
-    F_directory_max_recurse_depth_d, \
     0, \
+    F_directory_max_recurse_depth_d, \
     f_directory_recurse_do_flag_none_e, \
     f_mode_t_initialize, \
     f_state_t_initialize, \
@@ -289,10 +285,9 @@ extern "C" {
     0, \
     0, \
     0, \
-    0, \
   }
 
-  #define macro_f_directory_recurse_do_t_initialize_1(depth, depth_max, flag, mode, state, listing, path, path_cache, path_top, custom, action, handle) { \
+  #define macro_f_directory_recurse_do_t_initialize_1(depth, depth_max, flag, mode, state, listing, path, path_cache, path_top, action, handle) { \
     depth, \
     depth_max, \
     flag, \
@@ -302,12 +297,11 @@ extern "C" {
     path, \
     path_cache, \
     path_top, \
-    custom, \
     action, \
     handle, \
   }
 
-  #define macro_f_directory_recurse_do_t_initialize_2(depth, depth_max, flag, mode, state, custom, action, handle) { \
+  #define macro_f_directory_recurse_do_t_initialize_2(depth, depth_max, flag, mode, state, action, handle) { \
     depth,\
     depth_max \
     flag, \
@@ -317,7 +311,6 @@ extern "C" {
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
     0, \
-    custom, \
     action, \
     handle, \
   }
index 85b2ce78d428fb4240c96ee60b640f6361600b5d..c12011de1c897049130d93f0f10cb5044b9da220 100644 (file)
@@ -103,7 +103,7 @@ extern "C" {
       while (range->start <= range->stop && range->start < buffer->used) {
 
         if (state->interrupt) {
-          state->interrupt((void * const) &state, 0);
+          state->interrupt((void * const) state, 0);
           if (F_status_set_fine(state->status) == F_interrupt) break;
         }
 
@@ -155,7 +155,7 @@ extern "C" {
       while (F_status_is_error_not(state->status) && range->start <= range->stop && range->start < buffer->used) {
 
         if (state->interrupt) {
-          state->interrupt((void * const) &state, 0);
+          state->interrupt((void * const) state, 0);
           if (F_status_set_fine(state->status) == F_interrupt) break;
         }
 
@@ -201,7 +201,7 @@ extern "C" {
           while (range->start <= range->stop && range->start < buffer->used) {
 
             if (state->interrupt) {
-              state->interrupt((void * const) &state, 0);
+              state->interrupt((void * const) state, 0);
               if (F_status_set_fine(state->status) == F_interrupt) break;
             }
 
@@ -311,7 +311,7 @@ extern "C" {
         while (range->start <= range->stop && range->start < buffer->used) {
 
           if (state->interrupt) {
-            state->interrupt((void * const) &state, 0);
+            state->interrupt((void * const) state, 0);
             if (F_status_set_fine(state->status) == F_interrupt) break;
           }
 
index dd51dbb36511b4e5db55081b52fdb891210f1e8b..5462e35514344a1e1825b0841cc05bb73a6c93e2 100644 (file)
@@ -212,22 +212,34 @@ extern "C" {
       if (!recurse->action) {
         recurse->state.status = F_status_set_error(F_parameter);
 
-        private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e);
+        private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_top_e);
         if (F_status_is_error(recurse->state.status)) return;
       }
     #endif // _di_level_1_parameter_checking_
 
-    if (!recurse->path_top->used) {
+    if (!path.used) {
       recurse->state.status = F_data_not;
 
       private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e);
       if (F_status_is_error(recurse->state.status)) return;
     }
 
-    recurse->state.status = f_directory_exists(*recurse->path_top);
+    recurse->state.status = f_string_dynamic_append_nulless(path, &recurse->path);
 
-    if (recurse->state.status == F_false) {
-      recurse->state.status = F_status_set_error(F_directory_not);
+    if (F_status_is_error_not(recurse->state.status)) {
+
+      // Do not allow trailing path separators in the string's length calculation, except root directory '/'.
+      for (; recurse->path.used; --recurse->path.used) {
+        if (recurse->path.string[recurse->path.used - 1] != f_path_separator_s.string[0]) break;
+      } // for
+
+      recurse->path.string[recurse->path.used] = 0;
+
+      recurse->state.status = f_directory_exists(path);
+
+      if (recurse->state.status == F_false) {
+        recurse->state.status = F_status_set_error(F_directory_not);
+      }
     }
 
     if (F_status_is_error(recurse->state.status)) {
@@ -253,18 +265,6 @@ extern "C" {
     }
 
     if (recurse->depth_max) {
-      recurse->state.status = f_string_dynamic_append_nulless(path, &recurse->path);
-
-      if (F_status_is_error(recurse->state.status)) {
-        private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e);
-        if (F_status_is_error(recurse->state.status)) return;
-      }
-
-      // Do not allow trailing path separators in the string's length calculation, except root directory '/'.
-      for (; recurse->path.used; --recurse->path.used) {
-        if (recurse->path_top->string[recurse->path.used - 1] != f_path_separator_s.string[0]) break;
-      } // for
-
       recurse->depth = 1;
 
       private_fl_directory_do_recurse(recurse);
index df6f74dcf26d44743dfea9e57f76c7c579fb1a1a..c0bcb8a32ba07c2b31ff4063e963225d4bb344ad 100644 (file)
@@ -180,30 +180,55 @@ extern "C" {
  *     F_none on success.
  *     F_data_not if source.used or destination.used is 0.
  *
+ *     F_directory_descriptor (with error bit) on directory file descriptor error.
  *     F_directory_not (with error bit) if the directory does not exist.
- *     F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
+ *     F_directory_open (with error bit) on directory open error.
+ *     F_directory_stream (with error bit) on directory stream error.
+ *     F_directory_support_not (with error bit) on directory file descriptor not supported.
+ *     F_failure (with error bit) if failed to read directory information.
+ *     F_file_descriptor_max (with error bit) if max file descriptors is reached.
+ *     F_file_open_max (with error bit) too many open files.
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
+ *     F_memory_not (with error bit) on out of memory.
+ *     F_parameter (with error bit) if a parameter is invalid.
+ *     F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *
  *     Errors (with error bit) from: f_directory_create().
  *     Errors (with error bit) from: f_directory_exists().
  *     Errors (with error bit) from: f_file_mode_set().
  *     Errors (with error bit) from: f_file_role_change().
  *     Errors (with error bit) from: f_file_stat().
+ *     Errors (with error bit) from: f_file_stat_at().
  *     Errors (with error bit) from: f_string_dynamic_append_assure().
  *     Errors (with error bit) from: f_string_dynamic_append_nulless().
  *     Errors (with error bit) from: f_string_dynamic_increase_by().
  *     Errors (with error bit) from: f_string_dynamic_resize().
+ *     Errors (with error bit) from: f_string_dynamics_increase_by().
  *     Errors (with error bit) from: f_string_dynamics_resize().
  *
+ *     Errors (with error bit) from: recurse.action().
+ *     Errors (with error bit) from: recurse.handle().
+ *
+ * @see alphasort()
+ * @see opendir()
+ * @see scandir()
+ * @see versionsort()
+ *
  * @see f_directory_create()
  * @see f_directory_exists()
  * @see f_file_mode_set()
  * @see f_file_role_change()
  * @see f_file_stat()
+ * @see f_file_stat_at()
  * @see f_string_dynamic_append_assure()
  * @see f_string_dynamic_append_nulless()
  * @see f_string_dynamic_increase_by()
  * @see f_string_dynamic_resize()
+ * @see f_string_dynamics_increase_by()
  * @see f_string_dynamics_resize()
+ *
+ * @see recurse.action()
+ * @see recurse.handle()
  */
 #ifndef _di_fl_directory_do_
   extern void fl_directory_do(const f_string_static_t path, f_directory_recurse_do_t * const recurse);
index a6e63a6965bc25f4a40158f29ed6e6576b5524ec..8092d33cba6e240f0f91a969557649d8a99945e4 100644 (file)
@@ -342,7 +342,14 @@ extern "C" {
     recurse->state.status = F_none;
 
     f_array_length_t i = 0;
-    f_array_length_t used_original = 0;
+    uint8_t j = 0;
+    const f_array_length_t used_original = recurse->path.used;
+
+    const uint8_t flag_actions[] = {
+      f_directory_recurse_do_flag_before_e,
+      0,
+      f_directory_recurse_do_flag_after_e,
+    };
 
     {
       f_string_dynamics_t * const list[] = {
@@ -365,64 +372,57 @@ extern "C" {
         f_directory_recurse_do_flag_unknown_e,
       };
 
-      for (uint8_t j = 0; j < 7; ++j) {
+      for (uint8_t k = 0; k < 7; ++k) {
 
-        for (i = 0; i < list[j]->used; ++i) {
+        for (i = 0; i < list[k]->used; ++i) {
 
           if (recurse->state.interrupt) {
             recurse->state.interrupt((void *) &recurse->state, (void *) recurse);
             if (F_status_set_fine(recurse->state.status) == F_interrupt) break;
           }
 
-          used_original = recurse->path.used;
+          recurse->path.used = used_original;
 
-          recurse->state.status = f_string_dynamic_increase_by(f_path_separator_s.used + list[j]->array[i].used + 1, &recurse->path);
+          recurse->state.status = f_string_dynamic_increase_by(f_path_separator_s.used + list[k]->array[i].used + 1, &recurse->path);
 
           if (F_status_is_error_not(recurse->state.status)) {
             recurse->state.status = f_string_dynamic_append_assure(f_path_separator_s, &recurse->path);
           }
 
           if (F_status_is_error_not(recurse->state.status)) {
-            recurse->state.status = f_string_dynamic_append_nulless(list[j]->array[i], &recurse->path);
+            recurse->state.status = f_string_dynamic_append_nulless(list[k]->array[i], &recurse->path);
           }
 
           // Guarantee NULL termination.
           recurse->path.string[recurse->path.used] = 0;
 
           if (F_status_is_error(recurse->state.status)) {
-            private_inline_fl_directory_do_handle(recurse, list[j]->array[i], f_directory_recurse_do_flag_directory_e);
+            private_inline_fl_directory_do_handle(recurse, list[k]->array[i], f_directory_recurse_do_flag_directory_e);
             if (F_status_is_error(recurse->state.status)) break;
+            if (recurse->state.status == F_break || recurse->state.status == F_done) break;
+            if (recurse->state.status == F_continue) continue;
           }
 
-          if (recurse->state.status == F_break || recurse->state.status == F_done) {
-            recurse->path.used = used_original;
-
-            break;
-          }
+          // Convenience and code simplification loop for processing before action, action, and after action.
+          for (j = 0; j < 3; ++j) {
 
-          if (recurse->state.status == F_continue) {
-            recurse->path.used = used_original;
+            if (!flag_actions[j] || (recurse->flag & flag_actions[j])) {
+              recurse->state.status = F_none;
 
-            continue;
-          }
+              recurse->action((void *) recurse, list[k]->array[i], flag_actions[j] | flags[k]);
 
-          recurse->state.status = F_none;
-
-          recurse->action((void *) recurse, list[j]->array[i], flags[j]);
-
-          if (F_status_is_error(recurse->state.status)) {
-            private_inline_fl_directory_do_handle(recurse, list[j]->array[i], flags[j]);
-
-            if (F_status_is_error(recurse->state.status)) {
-              recurse->path.used = used_original;
+              if (F_status_is_error(recurse->state.status)) {
+                private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_before_e | flags[k]);
+                if (F_status_is_error(recurse->state.status)) break;
+              }
 
-              break;
+              // This loop is not considered a loop for breaking and continuing.
+              if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue) break;
             }
-          }
-
-          recurse->path.used = used_original;
+          } // for
 
-          if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_failure) break;
+          if (F_status_is_error(recurse->state.status)) break;
+          if (recurse->state.status == F_break || recurse->state.status == F_done) break;
           if (recurse->state.status == F_continue) continue;
         } // for
 
@@ -438,7 +438,7 @@ extern "C" {
           if (F_status_set_fine(recurse->state.status) == F_interrupt) break;
         }
 
-        used_original = recurse->path.used;
+        recurse->path.used = used_original;
 
         recurse->state.status = f_string_dynamic_increase_by(f_path_separator_s.used + recurse->listing.directory.array[i].used + 1, &recurse->path);
 
@@ -463,129 +463,62 @@ extern "C" {
 
         if (F_status_is_error(recurse->state.status)) {
           private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e);
-
-          if (F_status_is_error(recurse->state.status)) {
-            recurse->path.used = used_original;
-
-            break;
-          }
-        }
-
-        if (recurse->state.status == F_break || recurse->state.status == F_done) {
-          recurse->path.used = used_original;
-
-          break;
-        }
-
-        if (recurse->state.status == F_continue) {
-          recurse->path.used = used_original;
-
-          continue;
+          if (F_status_is_error(recurse->state.status)) break;
+          if (recurse->state.status == F_break || recurse->state.status == F_done) break;
+          if (recurse->state.status == F_continue) continue;
         }
 
-        if (recurse->flag & f_directory_recurse_do_flag_before_e) {
-          recurse->state.status = F_none;
+        // Convenience and code simplification loop for processing before action, action, and after action.
+        for (j = 0; j < 3; ++j) {
 
-          recurse->action((void *) recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_directory_e);
+          if (flag_actions[j]) {
+            if (recurse->flag & flag_actions[j]) {
+              recurse->action((void *) recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e);
 
-          if (F_status_is_error(recurse->state.status)) {
-            private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_directory_e);
-
-            if (F_status_is_error(recurse->state.status)) {
-              recurse->state.status = F_failure;
-
-              break;
+              if (F_status_is_error(recurse->state.status)) {
+                private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e);
+                if (F_status_is_error(recurse->state.status)) break;
+              }
             }
           }
-        }
-
-        if (recurse->state.status == F_break || recurse->state.status == F_done) {
-          recurse->path.used = used_original;
-
-          break;
-        }
-
-        if (recurse->state.status == F_continue) {
-          recurse->path.used = used_original;
-
-          continue;
-        }
-
-        if (recurse->depth < recurse->depth_max) {
-          ++recurse->depth;
-
-          private_fl_directory_do_recurse(recurse);
-
-          --recurse->depth;
-
-          if (recurse->state.status == F_done || recurse->state.status == F_failure) {
-            recurse->path.used = used_original;
-
-            break;
-          }
-        }
-        else {
-          recurse->state.status = F_none;
+          else {
+            recurse->state.status = F_none;
 
-          recurse->action((void *) recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e);
+            if (recurse->depth < recurse->depth_max) {
+              ++recurse->depth;
 
-          if (F_status_is_error(recurse->state.status)) {
-            private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e);
+              private_fl_directory_do_recurse(recurse);
 
-            if (F_status_is_error(recurse->state.status)) {
-              recurse->path.used = used_original;
+              --recurse->depth;
 
-              break;
+              if (F_status_is_error(recurse->state.status)) break;
             }
-          }
-
-          if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_failure) {
-            recurse->path.used = used_original;
-
-            break;
-          }
+            else {
+              recurse->action((void *) recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e);
 
-          if (recurse->state.status == F_continue) {
-            recurse->path.used = used_original;
-
-            continue;
-          }
-        }
-
-        if (recurse->flag & f_directory_recurse_do_flag_after_e) {
-          recurse->state.status = F_none;
-
-          recurse->action((void *) recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_directory_e);
-
-          if (F_status_is_error(recurse->state.status)) {
-            private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_directory_e);
-
-            if (F_status_is_error(recurse->state.status)) {
-              recurse->state.status = F_failure;
-              recurse->path.used = used_original;
-
-              break;
+              if (F_status_is_error(recurse->state.status)) {
+                private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e);
+                if (F_status_is_error(recurse->state.status)) break;
+              }
             }
-          }
-
-          if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_failure) {
-            recurse->path.used = used_original;
 
-            break;
+            // This loop is not considered a loop for breaking and continuing.
+            if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue) break;
           }
 
-          if (recurse->state.status == F_continue) {
-            recurse->path.used = used_original;
+          if (F_status_is_error(recurse->state.status)) break;
+          if (recurse->state.status == F_break || recurse->state.status == F_done) break;
+          if (recurse->state.status == F_continue) continue;
+        } // for
 
-            continue;
-          }
-        }
+        if (F_status_is_error(recurse->state.status) || recurse->state.status == F_done) break;
 
         recurse->state.status = F_none;
-        recurse->path.used = used_original;
       } // for
     }
 
+    recurse->path.used = used_original;
+
     // Only the directory is to be freed because all others are preserved between recursions.
     f_string_dynamics_resize(0, &recurse->listing.directory);
 
index c1516422e01ed4b164ec1ff1820a16655f5bcf1f..834a77921d9a5d602ec66965962d0959a9d1d8b6 100644 (file)
@@ -63,12 +63,33 @@ extern "C" {
  * @param recurse
  *   The directory recurse data.
  *
- * @return
- *   F_none on success.
+ *   This alters recurse.state.status:
+ *     F_none on success.
+ *     F_done on success and instructed to end recursion.
  *
- *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
+ *
+ *     Errors (with error bit) from: f_string_dynamic_append_assure().
+ *     Errors (with error bit) from: f_string_dynamic_append_nulless().
+ *     Errors (with error bit) from: f_string_dynamic_increase_by().
+ *     Errors (with error bit) from: fl_directory_list().
  *
+ *     Errors (with error bit) from: private_fl_directory_list().
+ *     Errors (with error bit) from: private_inline_fl_directory_do_handle().
+ *
+ *     Errors (with error bit) from: recurse.action().
+ *     Errors (with error bit) from: recurse.handle().
+ *
+ * @see f_string_dynamic_append_assure()
+ * @see f_string_dynamic_append_nulless()
+ * @see f_string_dynamic_increase_by()
  * @see fl_directory_do()
+ *
+ * @see private_fl_directory_list()
+ * @see private_inline_fl_directory_do_handle()
+ *
+ * @see recurse.action()
+ * @see recurse.handle()
  */
 #if !defined(_di_fl_directory_do_)
   extern void private_fl_directory_do_recurse(f_directory_recurse_do_t * const recurse) F_attribute_visibility_internal_d;
index 22612a82c6234d05af7a7cb39b6b302bfc190939..70adcf722ca6086a2744efc2447f3f3a70852da1 100644 (file)
@@ -167,15 +167,42 @@ extern "C" {
 
     fake_main_t * const main = data->main;
 
-    fake_string_dynamic_reset(&main->cache_argument);
-
     f_string_static_t buffer = f_string_static_t_initialize;
     f_status_t failed = F_none;
     fake_local_t local = macro_fake_local_t_initialize_1(main, &main->cache_map, &failed);
 
+    f_directory_recurse_do_t recurse = f_directory_recurse_do_t_initialize;
+    recurse.action = &fake_build_copy_action;
+    recurse.handle = &fake_build_copy_handle;
+    recurse.state.custom = (void *) &local;
+    recurse.state.code = fake_state_code_local_e;
+    recurse.flag = f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_after_e;
+    recurse.mode = mode;
+
     fake_build_print_message_copying(&main->program.message, label);
 
-    main->setting.state.status = f_string_dynamic_append_nulless(source, &main->cache_argument);
+    main->setting.state.status = f_file_exists(source, F_false);
+
+    if (F_status_is_error(main->setting.state.status)) {
+      fake_print_error(&main->program.error, macro_fake_f(f_file_exists));
+
+      return;
+    }
+
+    if (main->setting.state.status != F_true) {
+      fake_build_touch(data, file_stage);
+
+      return;
+    }
+
+    fake_string_dynamic_reset(&main->cache_2);
+    fake_string_dynamic_reset(&main->cache_map.name);
+
+    main->setting.state.status = f_string_dynamic_append_nulless(source, &main->cache_2);
+
+    if (F_status_is_error_not(main->setting.state.status)) {
+      main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.name);
+    }
 
     if (F_status_is_error(main->setting.state.status)) {
       fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
@@ -183,22 +210,19 @@ extern "C" {
       return;
     }
 
-    f_directory_recurse_do_t recurse = f_directory_recurse_do_t_initialize;
-    recurse.action = &fake_build_copy_action;
-    recurse.handle = &fake_build_copy_handle;
-    recurse.state.custom = (void *) &local;
-    recurse.state.code = fake_state_code_local_e;
-    recurse.flag = f_directory_recurse_do_flag_top_e & f_directory_recurse_do_flag_before_e & f_directory_recurse_do_flag_after_e;
-    recurse.mode = mode;
+    // @todo Consider binding the (non-existent) cache_3 for the recurse.path for more memory saving.
 
     for (f_array_length_t i = 0; i < files.used; ++i) {
 
       if (fake_signal_check(main)) break;
       if (!files.array[i].used) continue;
 
-      main->cache_argument.used = source.used;
+      fake_string_dynamic_reset(&main->cache_map.value);
+
+      main->cache_2.used = source.used;
+      main->cache_map.name.used = destination.used;
 
-      main->setting.state.status = f_string_dynamic_append_nulless(files.array[i], &main->cache_argument);
+      main->setting.state.status = f_string_dynamic_append_nulless(files.array[i], &main->cache_2);
 
       if (F_status_is_error(main->setting.state.status)) {
         fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
@@ -206,12 +230,21 @@ extern "C" {
         break;
       }
 
-      main->setting.state.status = f_directory_is(main->cache_argument);
+      main->cache_2.string[main->cache_2.used] = 0;
+      main->cache_map.name.string[main->cache_map.name.used] = 0;
+
+      main->setting.state.status = f_directory_is(main->cache_2);
 
       if (main->setting.state.status == F_true) {
-        main->cache_map.name.used = 0;
+        main->setting.state.status = f_file_name_base(main->cache_2, &main->cache_map.value);
 
-        main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.name);
+        if (F_status_is_error(main->setting.state.status)) {
+          fake_print_error(&main->program.error, macro_fake_f(f_file_name_base));
+
+          break;
+        }
+
+        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_map.value, &main->cache_map.name);
 
         if (F_status_is_error(main->setting.state.status)) {
           fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
@@ -219,21 +252,36 @@ extern "C" {
           break;
         }
 
-        main->setting.state.status = f_file_name_base(main->cache_argument, &main->cache_map.name);
+        main->cache_map.name.string[main->cache_map.name.used] = 0;
 
+        fl_directory_do(main->cache_2, &recurse);
+        if (F_status_set_fine(main->setting.state.status) == F_interrupt) break;
+
+        // Always provide a finall error message to the copy message.
         if (F_status_is_error(main->setting.state.status)) {
-          fake_print_error(&main->program.error, macro_fake_f(f_file_name_base));
+
+          // The final message will be generic failure if a message is already printed, otherwise a more detailed message is printed.
+          if (F_status_is_error(failed)) {
+            failed = main->setting.state.status;
+            main->setting.state.status = F_status_set_error(F_failure);
+          }
+
+          fake_print_error_build_operation_file(&main->program.error, macro_fake_f(fl_directory_do), f_file_operation_copy_s, main->cache_2, main->cache_map.name, f_file_operation_to_s, F_true);
+
+          if (F_status_is_error(failed)) {
+            main->setting.state.status = failed;
+          }
 
           break;
         }
-
-        fl_directory_do(main->cache_argument, &recurse);
-        if (F_status_is_error(main->setting.state.status)) break;
       }
       else if (main->setting.state.status == F_false) {
-        fake_string_dynamic_reset(&main->cache_map.name);
         fake_string_dynamic_reset(&main->cache_map.value);
 
+        if (main->cache_map.value.size) {
+          main->cache_map.value.string[0] = 0;
+        }
+
         main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.value);
 
         if (F_status_is_error(main->setting.state.status)) {
@@ -242,17 +290,9 @@ extern "C" {
           break;
         }
 
-        if (perserve_offset && perserve_offset < main->cache_argument.used) {
-          main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.name);
-
-          if (F_status_is_error(main->setting.state.status)) {
-            fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
-
-            break;
-          }
-
-          buffer.string = main->cache_argument.string + perserve_offset;
-          buffer.used = main->cache_argument.used - perserve_offset;
+        if (perserve_offset && perserve_offset < main->cache_2.used) {
+          buffer.string = main->cache_2.string + perserve_offset;
+          buffer.used = main->cache_2.used - perserve_offset;
 
           main->setting.state.status = f_file_name_directory(buffer, &main->cache_map.name);
 
@@ -270,16 +310,22 @@ extern "C" {
             break;
           }
 
-          main->setting.state.status = f_string_append(main->cache_argument.string + perserve_offset, main->cache_argument.used - perserve_offset, &main->cache_map.value);
+          main->setting.state.status = f_string_append_nulless(main->cache_2.string + perserve_offset, main->cache_2.used - perserve_offset, &main->cache_map.value);
 
           if (F_status_is_error(main->setting.state.status)) {
-            fake_print_error(&main->program.error, macro_fake_f(f_string_append));
+            fake_print_error(&main->program.error, macro_fake_f(f_string_append_nulless));
 
             break;
           }
         }
         else {
-          main->setting.state.status = f_file_name_base(main->cache_argument, &main->cache_map.value);
+          fake_string_dynamic_reset(&main->cache_map.name);
+
+          if (main->cache_map.name.size) {
+            main->cache_map.name.string[0] = 0;
+          }
+
+          main->setting.state.status = f_file_name_base(main->cache_2, &main->cache_map.value);
 
           if (F_status_is_error(main->setting.state.status)) {
             fake_print_error(&main->program.error, macro_fake_f(f_file_name_base));
@@ -288,18 +334,31 @@ extern "C" {
           }
         }
 
-        fake_build_print_verbose_copying(&main->program.message, main->cache_argument, main->cache_map.value);
+        fake_build_print_verbose_copying(&main->program.message, main->cache_2, main->cache_map.value);
 
-        main->setting.state.status = f_file_copy(main->cache_argument, main->cache_map.value, mode, F_file_default_read_size_d, f_file_stat_flag_reference_e);
+        main->setting.state.status = f_file_copy(main->cache_2, main->cache_map.value, mode, F_file_default_read_size_d, f_file_stat_flag_reference_e);
 
         if (F_status_is_error(main->setting.state.status)) {
-          fake_print_error_build_operation_file(&main->program.error, macro_fake_f(f_file_copy), f_file_operation_copy_s, f_file_operation_to_s, main->cache_argument, main->cache_map.value, F_true);
+          fake_print_error_build_operation_file(&main->program.error, macro_fake_f(f_file_copy), f_file_operation_copy_s, main->cache_2, main->cache_map.value, f_file_operation_to_s, F_true);
 
           break;
         }
+
+        // Restore the destination path in cases where it is changed.
+        if (!perserve_offset || perserve_offset >= main->cache_2.used) {
+          fake_string_dynamic_reset(&main->cache_map.name);
+
+          main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.name);
+
+          if (F_status_is_error(main->setting.state.status)) {
+            fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
+
+            return;
+          }
+        }
       }
       else if (F_status_is_error(main->setting.state.status)) {
-        fake_print_error_file(&main->program.error, macro_fake_f(f_directory_is), main->cache_argument, f_file_operation_create_s, fll_error_file_type_file_e);
+        fake_print_error_file(&main->program.error, macro_fake_f(f_directory_is), main->cache_2, f_file_operation_create_s, fll_error_file_type_file_e);
 
         break;
       }
@@ -307,10 +366,6 @@ extern "C" {
       main->setting.state.status = F_none;
     } // for
 
-    if (F_status_is_error(failed)) {
-      main->setting.state.status = F_status_set_error(F_failure);
-    }
-
     f_directory_recurse_do_delete(&recurse);
 
     fake_build_touch(data, file_stage);
@@ -324,9 +379,9 @@ extern "C" {
 
     f_directory_recurse_do_t * const recurse = (f_directory_recurse_do_t *) void_recurse;
 
-    if (!recurse->custom) return;
+    if (!recurse->state.custom) return;
 
-    fake_local_t * const local = (fake_local_t *) recurse->custom;
+    fake_local_t * const local = (fake_local_t *) recurse->state.custom;
 
     if (!local->custom_1) {
       recurse->state.status = F_status_set_error(F_parameter);
@@ -334,91 +389,179 @@ extern "C" {
       return;
     }
 
-    f_string_map_t * const map_destination = (f_string_map_t *) local->custom_1;
+    f_string_map_t * const map = (f_string_map_t *) local->custom_1;
 
-    if (flag & f_directory_recurse_do_flag_top_e) {
-      fake_string_dynamic_reset(&map_destination->value);
+    if (flag & f_directory_recurse_do_flag_before_e) {
+      if (flag & f_directory_recurse_do_flag_top_e) {
+        fake_build_print_verbose_copying(&local->main->program.message, *recurse->path_top, map->name);
 
-      recurse->state.status = F_none;
+        recurse->state.status = f_directory_exists(map->name);
 
-      return;
-    }
+        if (F_status_is_error(recurse->state.status)) {
+          local->main->setting.state.status = recurse->state.status;
 
-    if (flag & f_directory_recurse_do_flag_before_e) {
+          fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), map->value, f_file_operation_verify_s, fll_error_file_type_directory_e);
 
-      // Push the name on the path stack (the destination path is expected to be pre-populated).
-      recurse->state.status = f_string_dynamic_increase_by(f_path_separator_s.used + name.used + 1, &map_destination->name);
+          // Save the error status for when the error message is printed.
+          *((f_status_t *) local->custom_2) = recurse->state.status;
+        }
+        else if (recurse->state.status != F_true) {
+          recurse->state.status = fl_directory_create(map->name, F_file_mode_all_rwx_d);
 
-      if (F_status_is_error_not(recurse->state.status)) {
-        recurse->state.status = f_string_dynamic_append(f_path_separator_s, &map_destination->name);
-      }
+          if (F_status_is_error(recurse->state.status)) {
+            local->main->setting.state.status = recurse->state.status;
+
+            fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), map->value, f_file_operation_create_s, fll_error_file_type_directory_e);
+
+            // Save the error status for when the error message is printed.
+            *((f_status_t *) local->custom_2) = recurse->state.status;
+          }
+        }
+
+        if (F_status_is_error_not(recurse->state.status)) {
+          fake_string_dynamic_reset(&recurse->path_cache);
+
+          // Pre-populate the destination into the path cache.
+          recurse->state.status = f_string_dynamic_append(map->name, &recurse->path_cache);
+
+          if (F_status_is_error_not(recurse->state.status)) {
+            recurse->state.status = F_none;
 
-      if (F_status_is_error_not(recurse->state.status)) {
-        recurse->state.status = f_string_dynamic_append_nulless(name, &map_destination->name);
+            // Do not allow trailing path separators in the string's length calculation, except root directory '/'.
+            for (; recurse->path_cache.used; --recurse->path_cache.used) {
+              if (recurse->path_cache.string[recurse->path_cache.used - 1] != f_path_separator_s.string[0]) break;
+            } // for
+
+            recurse->path_cache.string[recurse->path_cache.used] = 0;
+          }
+        }
+
+        return;
       }
 
-      // Guaranetee NULL terminated string.
-      map_destination->name.string[map_destination->name.used] = 0;
+      if (flag & f_directory_recurse_do_flag_directory_e) {
+
+        // Push the directory name on the path stack (the destination path is expected to be pre-populated).
+        recurse->state.status = f_string_dynamic_increase_by(f_path_separator_s.used + name.used + 1, &recurse->path_cache);
+
+        if (F_status_is_error_not(recurse->state.status)) {
+          recurse->state.status = f_string_dynamic_append(f_path_separator_s, &recurse->path_cache);
+        }
+
+        if (F_status_is_error_not(recurse->state.status)) {
+          recurse->state.status = f_string_dynamic_append_nulless(name, &recurse->path_cache);
+        }
+
+        // Guaranetee NULL terminated string.
+        recurse->path_cache.string[recurse->path_cache.used] = 0;
+
+        if (F_status_is_error(recurse->state.status)) return;
+
+        fake_build_print_verbose_copying(&local->main->program.message, recurse->path, recurse->path_cache);
+
+        recurse->state.status = f_directory_exists(recurse->path_cache);
+
+        if (F_status_is_error_not(recurse->state.status) && recurse->state.status != F_true) {
+          recurse->state.status = fl_directory_create(recurse->path_cache, F_file_mode_all_rwx_d);
+        }
+
+        if (F_status_is_error(recurse->state.status)) {
+          local->main->setting.state.status = recurse->state.status;
+
+          fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), recurse->path_cache, f_file_operation_verify_s, fll_error_file_type_directory_e);
+
+          // Save the error status for when the error message is printed.
+          *((f_status_t *) local->custom_2) = recurse->state.status;
+        }
+        else if (recurse->state.status != F_true) {
+          recurse->state.status = fl_directory_create(recurse->path_cache, F_file_mode_all_rwx_d);
+
+          if (F_status_is_error(recurse->state.status)) {
+            local->main->setting.state.status = recurse->state.status;
+
+            fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), recurse->path_cache, f_file_operation_create_s, fll_error_file_type_directory_e);
+
+            // Save the error status for when the error message is printed.
+            *((f_status_t *) local->custom_2) = recurse->state.status;
+          }
+        }
+      }
 
       return;
     }
 
     if (flag & f_directory_recurse_do_flag_after_e) {
+      if (flag & f_directory_recurse_do_flag_directory_e) {
 
-      // Pop the current path off of the path stack.
-      map_destination->name.used -= f_path_separator_s.used + name.used;
+        // Pop the current path off of the path stack.
+        if (F_status_is_error_not(recurse->state.status)) {
+          recurse->path_cache.used -= f_path_separator_s.used + name.used;
+        }
 
-      recurse->state.status = F_none;
+        // Guaranetee NULL terminated string.
+        recurse->path_cache.string[recurse->path_cache.used] = 0;
+      }
 
       return;
     }
 
-    fake_string_dynamic_reset(&recurse->path_cache);
-    fake_string_dynamic_reset(&map_destination->value);
+    fake_string_dynamic_reset(&map->value);
 
-    recurse->state.status = f_string_dynamic_increase_by(recurse->path.used + f_path_separator_s.used + name.used + 1, &recurse->path_cache);
+    recurse->state.status = f_string_dynamic_increase_by(recurse->path_cache.used + f_path_separator_s.used + name.used + 1, &map->value);
 
     if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append_nulless(map_destination->name, &recurse->path_cache);
+      recurse->state.status = f_string_dynamic_append_nulless(recurse->path_cache, &map->value);
     }
 
     if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append(f_path_separator_s, &recurse->path_cache);
+      recurse->state.status = f_string_dynamic_append(f_path_separator_s, &map->value);
     }
 
     if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append_nulless(name, &recurse->path_cache);
+      recurse->state.status = f_string_dynamic_append_nulless(name, &map->value);
     }
 
-    if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_increase_by(map_destination->name.used + f_path_separator_s.used + name.used + 1, &map_destination->value);
-    }
+    // Guaranetee NULL terminated string.
+    map->value.string[map->value.used] = 0;
 
-    if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append_nulless(map_destination->name, &map_destination->value);
-    }
+    if (F_status_is_error(recurse->state.status)) return;
 
-    if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append(f_path_separator_s, &map_destination->value);
-    }
+    fake_build_print_verbose_copying(&local->main->program.message, recurse->path, map->value);
 
-    if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append_nulless(name, &map_destination->value);
-    }
+    if (flag & f_directory_recurse_do_flag_directory_e) {
+      if (F_status_is_error(recurse->state.status)) {
+        local->main->setting.state.status = recurse->state.status;
 
-    // Guaranetee NULL terminated strings.
-    recurse->path_cache.string[recurse->path_cache.used] = 0;
-    map_destination->value.string[map_destination->value.used] = 0;
+        fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), map->value, f_file_operation_verify_s, fll_error_file_type_directory_e);
 
-    if (F_status_is_error(recurse->state.status)) {
-      fake_string_dynamic_reset(&map_destination->value);
+        // Save the error status for when the error message is printed.
+        *((f_status_t *) local->custom_2) = recurse->state.status;
+      }
+      else if (recurse->state.status != F_true) {
+        recurse->state.status = fl_directory_create(map->value, F_file_mode_all_rwx_d);
 
-      return;
+        if (F_status_is_error(recurse->state.status)) {
+          local->main->setting.state.status = recurse->state.status;
+
+          fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_create), map->value, f_file_operation_create_s, fll_error_file_type_directory_e);
+
+          // Save the error status for when the error message is printed.
+          *((f_status_t *) local->custom_2) = recurse->state.status;
+        }
+      }
     }
+    else {
+      recurse->state.status = f_file_copy(recurse->path, map->value, recurse->mode, F_file_default_read_size_d, f_file_stat_flag_reference_e);
+
+      if (F_status_is_error(recurse->state.status)) {
+        local->main->setting.state.status = recurse->state.status;
 
-    fake_build_print_verbose_copying(&local->main->program.message, recurse->path_cache, map_destination->value);
+        fake_print_error_file(&local->main->program.error, macro_fake_f(f_file_copy), map->value, f_file_operation_create_s, fll_error_file_type_file_e);
 
-    recurse->state.status = f_file_copy(recurse->path_cache, map_destination->value, recurse->mode, F_file_default_read_size_d, f_file_stat_flag_reference_e);
+        // Save the error status for when the error message is printed.
+        *((f_status_t *) local->custom_2) = recurse->state.status;
+      }
+    }
   }
 #endif // _di_fake_build_copy_action_
 
@@ -432,62 +575,18 @@ extern "C" {
     // Do not print any errors on interrupts.
     if (F_status_set_fine(recurse->state.status) == F_interrupt) return;
 
-    if (!recurse->custom) return;
+    if (!recurse->state.custom) return;
 
-    fake_local_t * const local = (fake_local_t *) recurse->custom;
+    fake_local_t * const local = (fake_local_t *) recurse->state.custom;
 
     if (!local->main || !local->custom_1 || !local->custom_2) return;
 
-    *((f_status_t *) local->custom_2) = F_status_set_error(F_failure);
-
-    if (flag & f_directory_recurse_do_flag_top_e) {
+    if (F_status_is_error_not(*((f_status_t *) local->custom_2))) {
       local->main->setting.state.status = recurse->state.status;
 
-      if (flag == (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e)) {
-        fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_do), *recurse->path_top, f_file_operation_copy_s, fll_error_file_type_directory_e);
-      }
-      else if (flag == (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_path_e)) {
-        fake_print_error_file(&local->main->program.error, macro_fake_f(f_directory_exists), *recurse->path_top, f_file_operation_copy_s, fll_error_file_type_directory_e);
-      }
-      else if (flag == (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_path_e)) {
-        fake_print_error_file(&local->main->program.error, macro_fake_f(fl_directory_do), *recurse->path_top, f_file_operation_copy_s, fll_error_file_type_directory_e);
-      }
-
-      return;
-    }
-
-    f_string_map_t * const map_destination = (f_string_map_t *) local->custom_1;
-
-    if (flag == (flag & f_directory_recurse_do_flag_path_e)) {
-      // @todo this is old and may not be correct anymore.
-      fake_print_error_build_operation_file_recurse(&local->main->program.error, macro_fake_f(fl_directory_list), f_file_operation_copy_s, f_file_operation_to_s, recurse->path, name, map_destination->name, name, F_true);
-
-      return;
-    }
-
-    if (flag & f_directory_recurse_do_flag_directory_e) {
-      // @todo
-
-      //fake_print_error_build_operation_file_recurse(&local->main->program.error, macro_fake_f(f_file_copy), f_file_operation_copy_s, f_file_operation_to_s, recurse->path, name, map_destination->name, name, F_true);
+      fake_print_error_build_operation_file(&local->main->program.error, macro_fake_f(fl_directory_do), f_file_operation_copy_s, *recurse->path_top, recurse->path_cache, f_file_operation_to_s, F_true);
 
-      return;
-    }
-
-    // The value.used is set to 0 on allocation related failures so that better error messaging can be performed.
-    if (map_destination->value.used) {
-      fake_print_error_build_operation_file_recurse(&local->main->program.error, macro_fake_f(f_file_copy), f_file_operation_copy_s, f_file_operation_to_s, recurse->path, name, map_destination->name, name, F_true);
-    }
-    else if (map_destination->name.used) {
-      f_char_t destination[map_destination->name.used + f_path_separator_s.used + name.used];
-
-      memcpy(destination, map_destination->name.string, map_destination->name.used);
-      memcpy(destination + map_destination->name.used, f_path_separator_s.string, f_path_separator_s.used);
-      memcpy(destination + map_destination->name.used + f_path_separator_s.used, name.string, name.used);
-
-      fake_print_error_build_operation_file_recurse(&local->main->program.error, macro_fake_f(f_file_copy), f_file_operation_copy_s, f_file_operation_to_s, recurse->path, name, map_destination->name, name, F_true);
-    }
-    else {
-      fake_print_error_build_operation_file_recurse(&local->main->program.error, macro_fake_f(fl_directory_do), f_file_operation_copy_s, f_file_operation_to_s, recurse->path, name, f_string_empty_s, f_string_empty_s, F_true);
+      *((f_status_t *) local->custom_2) = recurse->state.status;
     }
   }
 #endif // _di_fake_build_copy_handle_
@@ -761,6 +860,7 @@ extern "C" {
   void fake_build_operate(fake_data_t * const data, const f_string_statics_t * const build_arguments, const bool process_pipe) {
 
     if (!data || !data->main) return;
+    if (F_status_is_error(data->main->setting.state.status)) return;
     if (fake_signal_check(data->main)) return;
 
     fake_main_t * const main = data->main;
@@ -776,7 +876,11 @@ extern "C" {
 
     fake_build_load_setting(data, build_arguments, process_pipe, &data_build.setting);
 
-    if (F_status_is_fine(main->setting.state.status)) {
+    if (F_status_is_fine(main->setting.state.status) && main->program.message.verbosity > f_console_verbosity_error_e) {
+      if (data->operation == fake_operation_make_e) {
+        fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+      }
+
       fake_print_message_building(&main->program.message, build_arguments, &data_build.setting);
     }
 
index b457cfae0c513a54050c90c79d40d86239d5dda3..676350ebfb71d164b839d47606bca138c162b893 100644 (file)
@@ -46,6 +46,9 @@ extern "C" {
  * @param data
  *   The program data.
  *
+ *   This modifies data.main->cache_2.
+ *   This modifies data.main->cache_map.
+ *
  *   This alters data.main->setting.state.status:
  *     F_none on success.
  *
@@ -53,6 +56,7 @@ extern "C" {
  *
  *     Errors (with error bit) from: f_directory_is()
  *     Errors (with error bit) from: f_file_copy()
+ *     Errors (with error bit) from: f_file_exists()
  *     Errors (with error bit) from: f_file_name_base()
  *     Errors (with error bit) from: f_file_name_directory()
  *     Errors (with error bit) from: f_string_append()
@@ -86,6 +90,7 @@ extern "C" {
  *
  * @see f_directory_is()
  * @see f_file_copy()
+ * @see f_file_exists()
  * @see f_file_name_base()
  * @see f_file_name_directory()
  * @see f_string_append()
index 4d17e0fb48c48ccd57b008fe9a6da02536dede2b..86179284cc776527aefe82fc95b386b766cfd601 100644 (file)
@@ -135,9 +135,6 @@ extern "C" {
         f_string_range_t range = macro_f_string_range_t_initialize2(buffer.used);
         f_fss_delimits_t delimits = f_fss_delimits_t_initialize;
 
-        // @todo make sure main->setting.state.custom = (void *) main->program;
-        //f_state_t state = macro_f_state_t_initialize_1(fake_allocation_large_d, fake_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main->program, 0);
-
         fll_fss_extended_read(buffer, &range, &objects, &contents, 0, 0, &delimits, 0, &main->setting.state);
 
         if (F_status_is_error(main->setting.state.status)) {
index c8eb7f092a958333bdfc4260763dea6ac07d44b0..831dc0d07a7c252e195731ad3854e3fff1ddd314 100644 (file)
@@ -8,6 +8,7 @@ extern "C" {
   void fake_clean_operate(fake_data_t * const data) {
 
     if (!data || !data->main) return;
+    if (F_status_is_error(data->main->setting.state.status)) return;
 
     fake_main_t * const main = data->main;
 
index 5838024ecf5a671186f10d4d49a5bd10a71a189d..9fe46e2b9a46d5c6626a2ac6917482bba55aa754 100644 (file)
@@ -52,6 +52,7 @@ extern "C" {
     "f_path_current",
     "f_path_directory_cleanup",
     "f_string_append",
+    "f_string_append_nulless",
     "f_string_dynamic_append",
     "f_string_dynamic_append_assure",
     "f_string_dynamic_append_nulless",
index 4ed4cc3d64ea37f14a522c4b842ee287df14c27d..060a4f9f284889e4839aef995f871413e546e343 100644 (file)
@@ -85,6 +85,7 @@ extern "C" {
     fake_f_f_path_current_e,
     fake_f_f_path_directory_cleanup_e,
     fake_f_f_string_append_e,
+    fake_f_f_string_append_nulless_e,
     fake_f_f_string_dynamic_append_e,
     fake_f_f_string_dynamic_append_assure_e,
     fake_f_f_string_dynamic_append_nulless_e,
index 917fad50c68230a3bbacb7d6548ff41b39365d0a..bb2bf81130282104171df7ba6868fc6a54cde7f7 100644 (file)
@@ -142,6 +142,10 @@ extern "C" {
 
         for (i = 0; i < main->setting.operations.used; ++i) {
 
+          if (i && main->program.message.verbosity > f_console_verbosity_error_e) {
+            fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
+          }
+
           data.operation = main->setting.operations.array[i];
 
           if (data.operation == fake_operation_build_e) {
@@ -151,18 +155,11 @@ extern "C" {
             }
 
             if (F_status_is_error_not(main->setting.state.status)) {
-              if (i && main->program.message.verbosity > f_console_verbosity_error_e) {
-                fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
-              }
-
               fake_build_operate(&data, 0, main->program.pipe & fll_program_data_pipe_input_e);
+              if (main->setting.state.status == F_child) break;
             }
           }
           else if (data.operation == fake_operation_clean_e) {
-            if (i && main->program.message.verbosity > f_console_verbosity_error_e) {
-              fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
-            }
-
             fake_clean_operate(&data);
 
             // Reset in case next operation needs files.
@@ -175,19 +172,11 @@ extern "C" {
             }
 
             if (F_status_is_error_not(main->setting.state.status)) {
-              if (i && main->program.message.verbosity > f_console_verbosity_error_e) {
-                fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
-              }
-
               fake_make_operate(&data);
               if (main->setting.state.status == F_child) break;
             }
           }
           else if (data.operation == fake_operation_skeleton_e) {
-            if (i && main->program.message.verbosity > f_console_verbosity_error_e) {
-              fll_print_dynamic_raw(f_string_eol_s, main->program.message.to);
-            }
-
             fake_skeleton_operate(&data);
 
             // Skeleton is supposed to guarantee these.
index 310f29990a8338b20faebf537c3bbf8bd81538cc..3a8160936168d590b4905ec4097596295934b0a8 100644 (file)
@@ -194,7 +194,7 @@ extern "C" {
       fl_print_format("%[", print->to, print->context);
     }
 
-    fl_print_format("%S.%]%r", print->to, print->context, after, print->context, f_string_eol_s);
+    fl_print_format("%S.%]%r", print->to, after, print->context, f_string_eol_s);
 
     f_file_stream_unlock(print->to);
 
@@ -216,41 +216,10 @@ extern "C" {
       fl_print_format("%[%Q%]", print->to, print->notable, destination, print->notable);
     }
 
-    fl_print_format("%['", print->to, print->context, print->context);
+    fl_print_format("%['", print->to, print->context);
   }
 #endif // _di_fake_print_error_build_operation_file_partial_
 
-#ifndef _di_fake_print_error_build_operation_file_recurse_
-  f_status_t fake_print_error_build_operation_file_recurse(fl_print_t * const print, const f_string_t function, const f_string_static_t operation, const f_string_static_t source_path, const f_string_static_t source_name, const f_string_static_t destination_path, const f_string_static_t destination_name, const f_string_static_t how, const bool fallback) {
-
-    if (!print) return F_status_set_error(F_output_not);
-
-    f_char_t source_array[source_path.used + source_name.used + 1];
-    source_array[source_path.used + source_name.used] = 0;
-
-    memcpy(source_array, source_path.string, source_path.used);
-    memcpy(source_array + source_path.used, f_path_separator_s.string, f_path_separator_s.used);
-    memcpy(source_array + source_path.used + f_path_separator_s.used, source_name.string, source_name.used);
-
-    const f_string_static_t source = macro_f_string_static_t_initialize(source_array, 0, source_path.used + f_path_separator_s.used + source_name.used);
-
-    if (destination_path.used || destination_name.used) {
-      f_char_t destination_array[destination_path.used + destination_name.used + 1];
-      destination_array[destination_path.used + destination_name.used] = 0;
-
-      memcpy(destination_array, destination_path.string, destination_path.used);
-      memcpy(destination_array + destination_path.used, f_path_separator_s.string, f_path_separator_s.used);
-      memcpy(destination_array + destination_path.used + f_path_separator_s.used, destination_name.string, destination_name.used);
-
-      const f_string_static_t destination = macro_f_string_static_t_initialize(source_array, 0, destination_path.used + f_path_separator_s.used + destination_name.used);
-
-      return fake_print_error_build_operation_file(print, function, operation, source, destination, how, fallback);
-    }
-
-    return fake_print_error_build_operation_file(print, function, operation, source, f_string_empty_s, how, fallback);
-  }
-#endif // _di_fake_print_error_build_operation_file_recurse_
-
 #ifndef _di_fake_print_error_directory_create_parent_missing_
   f_status_t fake_print_error_directory_create_parent_missing(fl_print_t * const print, const f_string_static_t path) {
 
index 957d455a3412622951113aaa92b5c111452696b0..d91241651848b2d347ebea1be6348a7ec11316c0 100644 (file)
@@ -179,47 +179,6 @@ extern "C" {
 #endif // _di_fake_print_error_build_operation_file_partial_
 
 /**
- * Print build operation file error messages for recursive functions that have separate path and name variables.
- *
- * @param setting
- *   The main program settings.
- *
- *   This does not alter setting.state.status.
- * @param print
- *   Designates the how and where to print.
- * @param function
- *   The name of the function where the error happened.
- * @param operation
- *   The operation performed.
- * @param source_path
- *   The operation source directory path.
- * @param source_name
- *   The operation source base file name.
- * @param destination_path
- *   The operation destination directory name, if applicable.
- *   Set destination_path.used and destination_name.used to 0 to disable.
- * @param destination_name
- *   The operation destination base file name, if applicable.
- *   Set destination_path.used and destination_name.used to 0 to disable.
- * @param how
- *   The how the operation is perform, such as "to" in "copy" source "to" destination.
- * @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.
- *   F_output_not on success, but no printing is performed.
- *
- *   F_output_not (with error bit) if print is NULL.
- *
- * @see fake_print_error_build_operation_file()
- */
-#ifndef _di_fake_print_error_build_operation_file_recurse_
-  extern f_status_t fake_print_error_build_operation_file_recurse(fl_print_t * const print, const f_string_t function, const f_string_static_t operation, const f_string_static_t source_path, const f_string_static_t source_name, const f_string_static_t destination_path, const f_string_static_t destination_name, const f_string_static_t how, const bool fallback);
-#endif // _di_fake_print_error_build_operation_file_recurse_
-
-/**
  * Print error message regarding file create directory failure due to a missing or invalid parent directory.
  *
  * @param setting
index d62fd7ab5fe03c8bc9ffd8bd393dfa0cce2675c1..418e2da85ba20614f52ecd97b12b699dda9a4a25 100644 (file)
@@ -14,7 +14,7 @@ extern "C" {
 
     f_file_stream_lock(print->to);
 
-    fl_print_format("%r%[Building%] ", print->to, f_string_eol_s, print->set->important, print->set->important);
+    fl_print_format("%[Building%] ", print->to, print->set->important, print->set->important);
     fl_print_format("%[%Q%]", print->to, print->set->notable, setting_build->build_name, print->set->notable);
     fl_print_format("%[ using '%]", print->to, print->set->important, print->set->important);
     fl_print_format("%[%Q%]", print->to, print->set->notable, main->setting.settings, print->set->notable);
@@ -76,7 +76,7 @@ extern "C" {
     if (!print) return F_status_set_error(F_output_not);
     if (print->verbosity < f_console_verbosity_normal_e) return F_output_not;
 
-    fake_print_common_simple(print, "Generating skeleton structure");
+    fake_print_context_important_simple(print, "Generating skeleton structure");
 
     return F_none;
   }
index 37b2e2fe74aa3682fa0a32568ec9e9eb5226eb86..1c6a9d72a569bfe00a8cb36a7ba71b090f0d3e49 100644 (file)
@@ -8,6 +8,7 @@ extern "C" {
   void fake_skeleton_operate(fake_data_t * const data) {
 
     if (!data || !data->main) return;
+    if (F_status_is_error(data->main->setting.state.status)) return;
 
     fake_main_t * const main = data->main;