]> Kevux Git Server - fll/commitdiff
Update: Featureless Make with regard to recent fl_directory_do() changes.
authorKevin Day <Kevin@kevux.org>
Sun, 27 Apr 2025 03:09:42 +0000 (22:09 -0500)
committerKevin Day <Kevin@kevux.org>
Sun, 27 Apr 2025 03:21:58 +0000 (22:21 -0500)
The changes to `fl_directory_do()` requires that the Featureless Make be updated.

I noticed that the `fake_build_copy()` has the `perserve_offset` parameter (also a typo in the name).
This was added in a hackish way in the past as sort of a quick and lazy solution.
Break this out into two parameters `preserve` and `offset` to allow for preserving the path with no offset at all.
I believe the current function structure is still not ideal but that is a problem for another time.

The `fake_do_copy_action()` callback for `fl_directory_do()` is now rewritten.
I distantly remember not being happy with the situation of the code and I would have needed to fix the `cache_map` to have a more logical use.
There were too many changes going on at the time and I did not want to deal with changing that as well.
Well, the problem of that approach finally caught up with me and I have fixed it now.
The `cache_map` now has the `key` as the source directory and the path as the `destination` directory.

I impulsively decided to use a `uint8_t` to designate the functions.
Then I wrapped the code in `F_status_is_error_not()` to allow for calling the error handling later on.
This has a downside of a rather ugly ternary blob.
Aside from the ternary blob, the rest of the code is rather simpler due to the avoidance of always handling the error and returning.

This is not well tested and I need to review the changes made as it should affect how the Featureless Make builds the tree structure.
The unit tests do seem to be failing to build.
I suspect there is some sort of problem in these changes that need to be further investigated.

level_3/fake/c/main/build.c
level_3/fake/c/main/build.h
level_3/fake/c/main/common/print.c
level_3/fake/c/main/common/print.h
level_3/fake/c/main/fake/do.c
level_3/fake/c/main/fake/do.h
level_3/fake/c/main/make/operate_process_type.c

index c936a446221f99110446505373468b2e146f5071..f51813ab50b03986cc17c232a07a6a73d14381ad 100644 (file)
@@ -164,7 +164,7 @@ extern "C" {
 #endif // _di_fake_build_arguments_standard_add_
 
 #ifndef _di_fake_build_copy_
-  void fake_build_copy(fake_data_t * const data, const f_mode_t mode, const f_string_static_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_number_unsigned_t perserve_offset) {
+  void fake_build_copy(fake_data_t * const data, const f_mode_t mode, const f_string_static_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const uint8_t preserve, const f_number_unsigned_t offset) {
 
     if (!data || !data->main) return;
     if (data->main->setting.state.status == F_child) return;
@@ -176,6 +176,7 @@ extern "C" {
     f_string_static_t buffer = f_string_static_t_initialize;
     f_status_t failed = F_okay;
     fake_local_t local = macro_fake_local_t_initialize_1(main, &main->cache_map, &failed);
+    uint8_t func = 0;
 
     main->cache_recurse_do.action = &fake_do_copy_action;
     main->cache_recurse_do.handle = &fake_do_copy_handle;
@@ -184,18 +185,25 @@ extern "C" {
     main->cache_recurse_do.flag = f_directory_recurse_do_flag_before_after_d;
     main->cache_recurse_do.mode = mode;
 
+    // Use cache_recurse_do.path as the top-level destination path for error printing.
+    // Use cache_recurse_do.path_cache as partial destination (directory creation) or for storing the top path with fl_directory_do().
+    // Use cache_map.key as source.
+    // Use cache_map.value as destination.
     fake_string_dynamic_reset(&main->cache_recurse_do.path);
     fake_string_dynamic_reset(&main->cache_recurse_do.path_cache);
+    fake_string_dynamic_reset(&main->cache_map.key);
+    fake_string_dynamic_reset(&main->cache_map.value);
 
     fake_build_print_message_copying(&main->program.message, label);
 
-    fake_string_dynamic_reset(&main->cache_2);
-    fake_string_dynamic_reset(&main->cache_map.key);
+    main->setting.state.status = f_string_dynamic_append_nulless(source, &main->cache_map.key);
 
-    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.value);
+    }
 
     if (F_status_is_error_not(main->setting.state.status)) {
-      main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.key);
+      main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_recurse_do.path);
     }
 
     if (F_status_is_error(main->setting.state.status)) {
@@ -209,132 +217,139 @@ extern "C" {
       if (macro_fake_signal_check(&main->program, &main->setting.state)) break;
       if (!files.array[i].used) continue;
 
-      fake_string_dynamic_reset(&main->cache_map.value);
-
-      main->cache_2.used = source.used;
-      main->cache_map.key.used = destination.used;
+      fake_string_dynamic_reset(&main->cache_recurse_do.path_cache);
 
-      main->setting.state.status = f_string_dynamic_append_nulless(files.array[i], &main->cache_2);
+      main->cache_map.key.used = source.used;
+      main->cache_map.value.used = destination.used;
 
-      if (F_status_is_error(main->setting.state.status)) {
-        fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
+      func = 0;
+      main->setting.state.status = f_memory_array_increase_by(f_path_separator_s.used + files.array[i].used + 1, sizeof(f_char_t), (void **) &main->cache_map.key.string, &main->cache_map.key.used, &main->cache_map.key.size);
 
-        break;
+      if (F_status_is_error_not(main->setting.state.status)) {
+        main->setting.state.status = f_memory_array_increase_by(f_path_separator_s.used + files.array[i].used + 1, sizeof(f_char_t), (void **) &main->cache_map.value.string, &main->cache_map.value.used, &main->cache_map.value.size);
       }
 
-      main->cache_2.string[main->cache_2.used] = 0;
-      main->cache_map.key.string[main->cache_map.key.used] = 0;
-
-      main->setting.state.status = f_directory_is(main->cache_2);
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 1;
+        main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &main->cache_map.key);
+      }
 
-      if (main->setting.state.status == F_true) {
-        main->setting.state.status = f_file_name_base(main->cache_2, &main->cache_map.key);
+      if (F_status_is_error_not(main->setting.state.status)) {
+        main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &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));
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 2;
+        main->setting.state.status = f_string_dynamic_append_nulless(files.array[i], &main->cache_map.key);
+      }
 
-          break;
+      if (F_status_is_error_not(main->setting.state.status)) {
+        if (preserve) {
+          func = 3;
+          main->setting.state.status = f_file_name_base(files.array[i], &main->cache_map.value);
         }
+        else {
+          if (offset) {
+            buffer.string = files.array[i].string + offset;
+            buffer.used = files.array[i].used - offset;
 
-        main->cache_map.key.string[main->cache_map.key.used] = 0;
-
-        fl_directory_do(main->cache_2, &main->cache_recurse_do);
-        if (F_status_set_fine(main->setting.state.status) == F_interrupt) break;
-
-        // Always provide a final error message to the copy message.
-        if (F_status_is_error(main->setting.state.status)) {
-
-          // 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);
+            main->setting.state.status = f_string_dynamic_append_nulless(buffer, &main->cache_map.value);
           }
-
-          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.key, f_file_operation_to_s, F_true);
-
-          if (F_status_is_error(failed)) {
-            main->setting.state.status = failed;
+          else {
+            main->setting.state.status = f_string_dynamic_append_nulless(files.array[i], &main->cache_map.value);
           }
-
-          break;
         }
       }
-      else if (main->setting.state.status == F_false) {
-        main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.value);
 
-        if (F_status_is_error(main->setting.state.status)) {
-          fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
-
-          break;
-        }
-
-        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.key);
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 4;
+        main->setting.state.status = f_string_dynamic_terminate_after(&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_directory));
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 5;
 
-            break;
-          }
+        main->cache_map.key.string[main->cache_map.key.used] = 0;
+        main->cache_map.value.string[main->cache_map.value.used] = 0;
 
-          main->setting.state.status = fl_directory_create(main->cache_map.key, F_file_mode_all_rwx_d);
+        main->setting.state.status = f_directory_is(main->cache_map.key);
+      }
 
-          if (F_status_is_error(main->setting.state.status)) {
-            fake_print_error_file(&main->program.error, macro_fake_f(fl_directory_create), main->cache_map.key, f_file_operation_create_s, fll_error_file_type_directory_e);
+      if (main->setting.state.status == F_true) {
+        func = 2;
+        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_map.key, &main->cache_recurse_do.path_cache);
 
-            break;
-          }
+        if (F_status_is_error_not(main->setting.state.status)) {
+          func = 4;
+          main->setting.state.status = f_string_dynamic_terminate_after(&main->cache_recurse_do.path_cache);
+        }
 
-          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_not(main->setting.state.status)) {
+          fl_directory_do(main->cache_recurse_do.path_cache, &main->cache_recurse_do);
+          if (F_status_set_fine(main->setting.state.status) == F_interrupt) break;
 
+          // Always provide a final 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_string_append_nulless));
 
-            break;
-          }
-        }
-        else {
-          fake_string_dynamic_reset(&main->cache_map.key);
+            // 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);
+            }
 
-          main->setting.state.status = f_file_name_base(main->cache_2, &main->cache_map.value);
+            fake_print_error_build_operation_file(&main->program.error, macro_fake_f(fl_directory_do), f_file_operation_copy_s, main->cache_map.key, main->cache_map.value, f_file_operation_to_s, F_true);
 
-          if (F_status_is_error(main->setting.state.status)) {
-            fake_print_error(&main->program.error, macro_fake_f(f_file_name_base));
+            if (F_status_is_error(failed)) {
+              main->setting.state.status = failed;
+            }
 
             break;
           }
         }
+      }
+      else if (main->setting.state.status == F_false) {
+        func = 6;
+        main->setting.state.status = f_file_name_directory(main->cache_map.value, &main->cache_recurse_do.path_cache);
 
-        main->cache_map.value.string[main->cache_map.value.used] = 0;
-
-        fake_print_verbose_copying(&main->program.message, main->cache_2, main->cache_map.value);
-
-        main->setting.state.status = f_file_copy(main->cache_2, main->cache_map.value, mode, F_file_default_size_read_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, main->cache_2, main->cache_map.value, f_file_operation_to_s, F_true);
-
-          break;
+        if (F_status_is_error_not(main->setting.state.status)) {
+          func = 7;
+          main->setting.state.status = fl_directory_create(main->cache_recurse_do.path_cache, F_file_mode_all_rwx_d);
         }
 
-        // 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.key);
-
-          main->setting.state.status = f_string_dynamic_append_nulless(destination, &main->cache_map.key);
-
-          if (F_status_is_error(main->setting.state.status)) {
-            fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
+        if (F_status_is_error_not(main->setting.state.status)) {
+          fake_print_verbose_copying(&main->program.message, main->cache_map.key, main->cache_map.value);
 
-            break;
-          }
+          func = 8;
+          main->setting.state.status = f_file_copy(main->cache_map.key, main->cache_map.value, mode, F_file_default_size_read_d, f_file_stat_flag_reference_e);
         }
       }
-      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_2, f_file_operation_create_s, fll_error_file_type_file_e);
+
+      if (F_status_is_error(main->setting.state.status)) {
+        fake_print_error_build_operation_file(
+          &main->program.error,
+          !func
+            ? macro_fake_f(f_memory_array_increase_by)
+            : func == 1
+              ? macro_fake_f(f_string_dynamic_append_assure)
+              : func == 2
+                ? macro_fake_f(f_string_dynamic_append_nulless)
+                : func == 3
+                  ? macro_fake_f(f_file_name_base)
+                  : func == 4
+                    ? macro_fake_f(f_string_dynamic_terminate_after)
+                    : func == 5
+                      ? macro_fake_f(f_directory_is)
+                      : func == 6
+                        ? macro_fake_f(f_file_name_directory)
+                        : func == 7
+                          ? macro_fake_f(fl_directory_create)
+                          : macro_fake_f(f_file_copy),
+          f_file_operation_copy_s,
+          main->cache_map.key,
+          main->cache_map.value,
+          f_file_operation_to_s,
+          F_true
+        );
 
         break;
       }
@@ -647,9 +662,9 @@ extern "C" {
 
     main->program.child = fake_build_execute_process_script(data, &data_build, data_build.setting.process_pre, stage.file_process_pre);
 
-    fake_build_copy(data, mode, fake_build_documentation_files_s, data->path_data_documentation, data->path_build_documentation, data_build.setting.build_sources_documentation, stage.file_sources_documentation, 0);
+    fake_build_copy(data, mode, fake_build_documentation_files_s, data->path_data_documentation, data->path_build_documentation, data_build.setting.build_sources_documentation, stage.file_sources_documentation, F_false, 0);
 
-    fake_build_copy(data, mode, fake_build_setting_files_s, data->path_data_settings, data->path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, 0);
+    fake_build_copy(data, mode, fake_build_setting_files_s, data->path_data_settings, data->path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, F_false, 0);
 
     if (data_build.setting.language == fake_build_language_shell_e) {
       fake_build_object_script(data, &data_build, mode, stage.file_object_script);
@@ -669,7 +684,7 @@ extern "C" {
           }
         }
 
-        fake_build_copy(data, mode, fake_build_scripts_s, main->cache_argument, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0);
+        fake_build_copy(data, mode, fake_build_scripts_s, main->cache_argument, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, F_false, 0);
       }
     }
     else {
@@ -690,14 +705,14 @@ extern "C" {
           }
         }
 
-        fake_build_copy(data, mode, fake_build_header_files_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.preserve_path_headers ? main->cache_argument.used : 0);
+        fake_build_copy(data, mode, fake_build_header_files_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.preserve_path_headers, main->cache_argument.used);
 
         if (data_build.setting.build_shared) {
-          fake_build_copy(data, mode, fake_build_header_files_shared_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers_shared, stage.file_sources_headers, data_build.setting.preserve_path_headers ? main->cache_argument.used : 0);
+          fake_build_copy(data, mode, fake_build_header_files_shared_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers_shared, stage.file_sources_headers, data_build.setting.preserve_path_headers, main->cache_argument.used);
         }
 
         if (data_build.setting.build_static) {
-          fake_build_copy(data, mode, fake_build_header_files_static_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers_static, stage.file_sources_headers, data_build.setting.preserve_path_headers ? main->cache_argument.used : 0);
+          fake_build_copy(data, mode, fake_build_header_files_static_s, main->cache_argument, main->cache_1, data_build.setting.build_sources_headers_static, stage.file_sources_headers, data_build.setting.preserve_path_headers, main->cache_argument.used);
         }
       }
 
@@ -729,7 +744,7 @@ extern "C" {
             fake_print_error(&main->program.error, macro_fake_f(f_string_dynamic_append_nulless));
           }
           else {
-            fake_build_copy(data, mode, fake_build_scripts_s, main->cache_argument, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0);
+            fake_build_copy(data, mode, fake_build_scripts_s, main->cache_argument, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, F_false, 0);
           }
         }
       }
index 236d5cf166a17263502d65f373668227408cbbb7..04702da9cb848659544c1e9650dfed35c54ce120 100644 (file)
@@ -53,7 +53,6 @@ extern "C" {
  * @param data
  *   The program data.
  *
- *   This modifies data.main.cache_2.
  *   This modifies data.main.cache_map.
  *   This modifies data.main.cache_recurse_do.
  *
@@ -87,16 +86,15 @@ extern "C" {
  *   The files to copy from source to destination.
  * @param file_stage
  *   The specific stage file path.
- * @param perserve_offset
- *   (optional) When a positive number, this represents the amount of characters at the front of each file to ignore.
- *   Everything after that is preserved, and the directory is created if necessary.
- *
- *   This is always treated as 0 for any file that is a directory type.
- *
- *   Set to 0 to disable.
+ * @param preserve
+ *   Set to F_true to preserve the path.
+ *   Set to F_False to only use the base name when copying.
+ * @param offset
+ *   When preserve is F_true, this represents the amount of characters at the front of each path to ignore.
+ *   Everything after the offset is preserved, and directories are created if necessary.
  *
  *   Example: 'sources/c/level_0/fss.h' with a preseve of 10, would result in the path of 'level_0/fss.h' being preserved.
- *            Whereas a perserve_offset of 0 would result in a path of 'fss.h' being used (the 'level_0/' directory is not preserved).
+ *            Whereas a preseve is F_false, then the path used would instead be 'fss.h' (the 'sources/c/level_0/' directories are not preserved).
  *
  * @see f_directory_is()
  * @see f_file_copy()
@@ -111,7 +109,7 @@ extern "C" {
  * @see fll_program_print_signal_received()
  */
 #ifndef _di_fake_build_copy_
-  extern void fake_build_copy(fake_data_t * const data, const f_mode_t mode, const f_string_static_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_number_unsigned_t perserve_offset);
+  extern void fake_build_copy(fake_data_t * const data, const f_mode_t mode, const f_string_static_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const uint8_t preserve, const f_number_unsigned_t offset);
 #endif // _di_fake_build_copy_
 
 /**
index 5b5d3ec0626bd167620b043bc58f1b7750f6a25e..14338402f854d844b5eeef29e15de51e5695f3de 100644 (file)
@@ -62,6 +62,7 @@ extern "C" {
     "f_string_dynamic_partial_append",
     "f_string_dynamic_partial_append_nulless",
     "f_string_dynamic_prepend",
+    "f_string_dynamic_terminate_after",
     "f_thread_create",
     "f_utf_is_word_dash_plus",
     "fl_conversion_dynamic_to_unsigned_detect",
index 413acc091b5b9b779d0b4dfa12fbff4942374af7..263308057c5dc8356a164d0ff8e2856de3f033f2 100644 (file)
@@ -95,6 +95,7 @@ extern "C" {
     fake_f_f_string_dynamic_partial_append_e,
     fake_f_f_string_dynamic_partial_append_nulless_e,
     fake_f_f_string_dynamic_prepend_e,
+    fake_f_f_string_dynamic_terminate_after_e,
     fake_f_f_thread_create_e,
     fake_f_f_utf_is_word_dash_plus_e,
     fake_f_fl_conversion_dynamic_to_unsigned_detect_e,
index d7b48082daf87bb8976d28a4f61e36535b762028..c95dc9a8e82515bc50f2dec479e6158292929cfc 100644 (file)
@@ -26,146 +26,120 @@ extern "C" {
     }
 
     f_string_map_t * const map = (f_string_map_t *) local->custom_1;
+    uint8_t func = 0;
 
-    if (!recurse->depth && (flag & f_directory_recurse_do_flag_before_d)) {
-      if (recurse->state.code & fake_state_code_clone_d) {
-        fake_print_verbose_cloning(&local->main->program.message, *recurse->path_top, map->key);
-
-        recurse->state.status = f_file_clone(*recurse->path_top, map->key, F_file_default_size_write_d, f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e));
-      }
-      else {
-        fake_print_verbose_copying(&local->main->program.message, *recurse->path_top, map->key);
-
-        recurse->state.status = f_file_copy(*recurse->path_top, map->key, recurse->mode, F_file_default_size_write_d, f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e);
-      }
-
-      if (F_status_is_error(recurse->state.status)) {
-        local->main->setting.state.status = recurse->state.status;
-
-        fake_print_error_file(&local->main->program.error, (recurse->state.code & fake_state_code_clone_d) ? macro_fake_f(f_file_clone) : macro_fake_f(f_file_copy), *recurse->path_top, (recurse->state.code & fake_state_code_clone_d) ? f_file_operation_clone_s : f_file_operation_copy_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 {
-        fake_string_dynamic_reset(&recurse->path_cache);
+    // Append the directory path on start.
+    // If the path is a directory, then make sure to copy/clone the directory first before the action.
+    if (flag & f_directory_recurse_do_flag_before_d) {
 
-        // Pre-populate the destination into the path cache.
-        recurse->state.status = f_string_dynamic_append_nulless(map->key, &recurse->path_cache);
+      // Append the name to the path everytime, except for the top-path because that is already part of the path.
+      if (recurse->depth) {
+        func = 0;
+        recurse->state.status = f_memory_array_increase_by(f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &map->key.string, &map->key.used, &map->key.size);
 
         if (F_status_is_error_not(recurse->state.status)) {
-          recurse->state.status = F_okay;
-
-          // 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;
+          recurse->state.status = f_memory_array_increase_by(f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &map->value.string, &map->value.used, &map->value.size);
         }
-      }
-
-      return;
-    }
 
-    if (flag & f_directory_recurse_do_flag_before_d) {
-      if ((flag & f_directory_recurse_do_flag_directory_d) && (flag & f_directory_recurse_do_flag_action_d)) {
-
-        // Push the directory name on the path stack (the destination path is expected to be pre-populated).
-        recurse->state.status = f_memory_array_increase_by(f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &recurse->path_cache.string, &recurse->path_cache.used, &recurse->path_cache.size);
+        if (F_status_is_error_not(recurse->state.status)) {
+          func = 1;
+          recurse->state.status = f_string_dynamic_append_nulless(f_path_separator_s, &map->key);
+        }
 
         if (F_status_is_error_not(recurse->state.status)) {
-          recurse->state.status = f_string_dynamic_append_assure(f_path_separator_s, &recurse->path_cache);
+          recurse->state.status = f_string_dynamic_append_nulless(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->key);
         }
 
-        // Guaranetee NULL terminated string.
-        recurse->path_cache.string[recurse->path_cache.used] = 0;
+        if (F_status_is_error_not(recurse->state.status)) {
+          recurse->state.status = f_string_dynamic_append_nulless(name, &map->value);
+        }
+      }
 
-        if (F_status_is_error(recurse->state.status)) return;
+      if (F_status_is_error_not(recurse->state.status)) {
+        map->key.string[map->key.used] = 0;
+        map->value.string[map->value.used] = 0;
 
         if (recurse->state.code & fake_state_code_clone_d) {
-          fake_print_verbose_cloning(&local->main->program.message, recurse->path, recurse->path_cache);
-
-          recurse->state.status = f_file_clone(recurse->path, recurse->path_cache, F_file_default_size_write_d, f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e));
+          fake_print_verbose_cloning(&local->main->program.message, map->key, map->value);
+
+          func = 2;
+          recurse->state.status = f_file_clone(
+            map->key,
+            map->value,
+            F_file_default_size_write_d,
+            f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (
+              recurse->flag & f_directory_recurse_do_flag_dereference_d
+                ? 0
+                : f_file_stat_flag_reference_e
+            )
+          );
         }
         else {
-          fake_print_verbose_copying(&local->main->program.message, recurse->path, recurse->path_cache);
-
-          recurse->state.status = f_file_copy(recurse->path, recurse->path_cache, recurse->mode, F_file_default_size_write_d, f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e);
+          fake_print_verbose_copying(&local->main->program.message, map->key, map->value);
+
+          func = 3;
+          recurse->state.status = f_file_copy(
+            map->key,
+            map->value,
+            recurse->mode,
+            F_file_default_size_write_d,
+            recurse->flag & f_directory_recurse_do_flag_dereference_d
+              ? 0
+              : f_file_stat_flag_reference_e
+          );
         }
+      }
 
-        if (F_status_is_error(recurse->state.status)) {
-          local->main->setting.state.status = recurse->state.status;
+      if (F_status_is_error(recurse->state.status)) {
+        local->main->setting.state.status = recurse->state.status;
 
-          fake_print_error_file(&local->main->program.error, (recurse->state.code & fake_state_code_clone_d) ? macro_fake_f(f_file_clone) : macro_fake_f(f_file_copy), recurse->path, (recurse->state.code & fake_state_code_clone_d) ? f_file_operation_clone_s : f_file_operation_copy_s, fll_error_file_type_directory_e);
+        fake_print_error_file(
+          &local->main->program.error,
+          !func
+            ? macro_fake_f(f_memory_array_increase_by)
+            : func == 1
+              ? macro_fake_f(f_string_dynamic_append_nulless)
+              : func == 2
+                ? macro_fake_f(f_file_clone)
+                : macro_fake_f(f_file_copy),
+          map->key,
+          recurse->state.code & fake_state_code_clone_d
+            ? f_file_operation_clone_s
+            : f_file_operation_copy_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;
-        }
+        // Save the error status for when the error message is printed.
+        *((f_status_t *) local->custom_2) = recurse->state.status;
       }
 
       return;
     }
+    else if (flag & f_directory_recurse_do_flag_after_d) {
 
-    if (!recurse->depth && (flag & f_directory_recurse_do_flag_after_d)) {
-      if ((flag & f_directory_recurse_do_flag_directory_d) && (flag & f_directory_recurse_do_flag_action_d)) {
+      // Pop the current path off of the path stack.
+      if (recurse->depth) {
+        if (map->key.size && map->key.size >= f_path_separator_s.used + name.used) {
+          map->key.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;
+          // Guaranetee NULL terminated string.
+          map->key.string[map->key.used] = 0;
         }
 
-        // Guaranetee NULL terminated string.
-        recurse->path_cache.string[recurse->path_cache.used] = 0;
+        if (map->value.size && map->value.size >= f_path_separator_s.used + name.used) {
+          map->value.used -= f_path_separator_s.used + name.used;
+
+          // Guaranetee NULL terminated string.
+          map->value.string[map->value.used] = 0;
+        }
       }
 
       return;
     }
-
-    fake_string_dynamic_reset(&map->value);
-
-    recurse->state.status = f_memory_array_increase_by(recurse->path_cache.used + f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &map->value.string, &map->value.used, &map->value.size);
-
-    if (F_status_is_error_not(recurse->state.status)) {
-      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_assure(f_path_separator_s, &map->value);
-    }
-
-    if (F_status_is_error_not(recurse->state.status)) {
-      recurse->state.status = f_string_dynamic_append_nulless(name, &map->value);
-    }
-
-    // Guaranetee NULL terminated string.
-    map->value.string[map->value.used] = 0;
-
-    if (F_status_is_error(recurse->state.status)) return;
-
-    if (recurse->state.code & fake_state_code_clone_d) {
-      fake_print_verbose_cloning(&local->main->program.message, recurse->path, map->value);
-
-      recurse->state.status = f_file_clone(recurse->path, map->value, F_file_default_size_write_d, f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e));
-    }
-    else {
-      fake_print_verbose_copying(&local->main->program.message, recurse->path, map->value);
-
-      recurse->state.status = f_file_copy(recurse->path, map->value, recurse->mode, F_file_default_size_write_d, f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e);
-    }
-
-    if (F_status_is_error(recurse->state.status)) {
-      local->main->setting.state.status = recurse->state.status;
-
-      fake_print_error_file(&local->main->program.error, (recurse->state.code & fake_state_code_clone_d) ? macro_fake_f(f_file_clone) : macro_fake_f(f_file_copy), map->value, f_file_operation_create_s, (flag & f_directory_recurse_do_flag_directory_d) ? fll_error_file_type_directory_e : fll_error_file_type_file_e);
-
-      // Save the error status for when the error message is printed.
-      *((f_status_t *) local->custom_2) = recurse->state.status;
-    }
   }
 #endif // _di_fake_do_copy_action_
 
@@ -181,7 +155,19 @@ extern "C" {
     if (F_status_is_error_not(*((f_status_t *) local->custom_2))) {
       local->main->setting.state.status = recurse->state.status;
 
-      fake_print_error_build_operation_file(&local->main->program.error, macro_fake_f(fl_directory_do), (recurse->state.code & fake_state_code_clone_d) ? f_file_operation_clone_s : f_file_operation_copy_s, *recurse->path_top, recurse->path_cache, f_file_operation_to_s, F_true);
+      fake_print_error_build_operation_file(
+        &local->main->program.error,
+        macro_fake_f(fl_directory_do),
+        recurse->state.code & fake_state_code_clone_d
+          ? f_file_operation_clone_s
+          : f_file_operation_copy_s,
+        recurse->path_top
+          ? *recurse->path_top
+          : f_string_empty_s,
+        recurse->path,
+        f_file_operation_to_s,
+        F_true
+      );
 
       *((f_status_t *) local->custom_2) = recurse->state.status;
     }
index 2ee1806cd49b82ee92691470b0e0f9d624ff278a..6e687b3980b6795c973d2d5bd781841ea1d76dff 100644 (file)
@@ -21,6 +21,12 @@ extern "C" {
  *
  * This can also be used for a clone or a move operation when the appropriate flags or set.
  *
+ * This expects and potentially alters the following:
+ *   - main.cache_recurse_do.path:       The top-level destination path to use when printing errors.
+ *   - main.cache_recurse_do.path_cache: A cache to use for special cases.
+ *   - recurse.state.custom:             A pointer to fake_local_t.
+ *   - recurse.state.custom.custom_1:    A pointer to f_string_map_t where the custom_1.key is the specific source path and custom_1.value is the destination path during before, action, and after operations.
+ *
  * @param recurse
  *   The recuse structure.
  *
index 46738452aa5d3e9c626341fffb4983ddcebbe9f1..862e334524a36fdfc77c1740b81db045e1119f9a 100644 (file)
@@ -209,7 +209,7 @@ extern "C" {
 
     fake_main_t * const main = data_make->main;
 
-    const f_number_unsigned_t total = main->cache_arguments.used - 1;
+    const f_number_unsigned_t total = main->cache_arguments.used ? main->cache_arguments.used - 1 : 0;
     f_status_t failed = F_okay;
     fake_local_t local = macro_fake_local_t_initialize_1(main, &main->cache_map, &failed);
 
@@ -226,14 +226,21 @@ extern "C" {
       macro_f_mode_t_set_default_umask(main->cache_recurse_do.mode, main->program.umask);
     }
 
+    // Use cache_recurse_do.path as the top-level destination path for error printing.
+    // Use cache_recurse_do.path_cache as partial destination (directory creation) or for storing the top path with fl_directory_do().
+    // Use cache_map.key as source.
+    // Use cache_map.value as destination.
     fake_string_dynamic_reset(&main->cache_recurse_do.path);
     fake_string_dynamic_reset(&main->cache_recurse_do.path_cache);
+    fake_string_dynamic_reset(&main->cache_map.key);
+    fake_string_dynamic_reset(&main->cache_map.value);
 
-    bool existing = F_true;
-    f_number_unsigned_t i = 0;
-    const f_string_t *function = 0;
-    const f_string_static_t *operation = 0;
+    uint8_t func = 0;
+    uint8_t existing = F_true;
     uint8_t type = fll_error_file_type_path_e;
+    f_number_unsigned_t i = 0;
+
+    f_string_static_t operation = f_string_static_t_initialize;
 
     // The first argument may designate not to dereference links.
     if (f_compare_dynamic(fake_make_operation_argument_no_dereference_s, main->cache_arguments.array[i]) == F_equal_to) {
@@ -246,93 +253,117 @@ extern "C" {
       main->setting.state.status = f_directory_is(main->cache_arguments.array[1]);
 
       if (F_status_is_error(main->setting.state.status)) {
-        function = &macro_fake_f(f_directory_is);
-        operation = &f_file_operation_identify_s;
+        operation = f_file_operation_identify_s;
       }
       else if (main->setting.state.status == F_false || main->setting.state.status == F_file_found_not || main->setting.state.status == F_data_not) {
         existing = F_false;
       }
     }
 
-    if (F_status_is_error_not(main->setting.state.status)) {
-      for (; i < total; ++i) {
-
-        fake_string_dynamic_reset(&main->cache_map.key);
+    for (; F_status_is_error_not(main->setting.state.status) && i < total; ++i) {
 
-        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_arguments.array[total], &main->cache_map.key);
+      fake_string_dynamic_reset(&main->cache_recurse_do.path);
+      fake_string_dynamic_reset(&main->cache_map.key);
+      fake_string_dynamic_reset(&main->cache_map.value);
 
-        if (F_status_is_error(main->setting.state.status)) {
-          function = &macro_fake_f(f_string_dynamic_append_nulless);
-          operation = &f_file_operation_process_s;
+      func = 0;
+      operation = f_file_operation_process_s;
+      main->setting.state.status = f_memory_array_increase_by(main->cache_arguments.array[i].used + 1, sizeof(f_char_t), (void **) &main->cache_map.key.string, &main->cache_map.key.used, &main->cache_map.key.size);
 
-          break;
-        }
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 1;
+        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_arguments.array[i], &main->cache_map.key);
+      }
 
-        if (existing) {
-          main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &main->cache_map.key);
+      if (F_status_is_error_not(main->setting.state.status)) {
+        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_arguments.array[total], &main->cache_map.value);
+      }
 
-          if (F_status_is_error(main->setting.state.status)) {
-            function = &macro_fake_f(f_string_dynamic_append_assure);
-            operation = &f_file_operation_process_s;
+      if (F_status_is_error_not(main->setting.state.status)) {
+        main->setting.state.status = f_string_dynamic_append_nulless(main->cache_arguments.array[total], &main->cache_recurse_do.path);
+      }
 
-            break;
-          }
+      if (F_status_is_error_not(main->setting.state.status) && existing) {
+        func = 2;
+        main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &main->cache_map.value);
+      }
 
-          main->setting.state.status = f_file_name_base(main->cache_arguments.array[i], &main->cache_map.key);
+      if (F_status_is_error_not(main->setting.state.status) && existing) {
+        func = 3;
+        main->setting.state.status = f_string_dynamic_terminate_after(&main->cache_map.key);
+      }
 
-          if (F_status_is_error(main->setting.state.status)) {
-            function = &macro_fake_f(f_file_name_base);
-            operation = &f_file_operation_process_s;
+      if (F_status_is_error_not(main->setting.state.status) && existing) {
+        func = 4;
+        main->setting.state.status = f_file_name_base(main->cache_arguments.array[i], &main->cache_map.value);
+      }
 
-            break;
-          }
-        }
+      if (F_status_is_error_not(main->setting.state.status)) {
+        func = 5;
+        operation = f_file_operation_identify_s;
+        type = fll_error_file_type_directory_e;
 
         main->setting.state.status = f_directory_is(main->cache_arguments.array[i]);
 
         if (main->setting.state.status == F_true) {
+          func = 6;
+          operation = clone ? f_file_operation_clone_s : f_file_operation_copy_s;
+
           fl_directory_do(main->cache_arguments.array[i], &main->cache_recurse_do);
 
           if (F_status_is_error(main->cache_recurse_do.state.status)) {
             main->setting.state.status = main->cache_recurse_do.state.status;
-
-            function = &macro_fake_f(fl_directory_do);
-            operation = clone ? &f_file_operation_clone_s : &f_file_operation_copy_s;
-            type = fll_error_file_type_directory_e;
-
-            break;
           }
         }
         else if (main->setting.state.status == F_false) {
+          type = fll_error_file_type_file_e;
+
           if (clone) {
-            main->setting.state.status = f_file_clone(main->cache_arguments.array[i], main->cache_map.key, F_file_default_size_write_d, f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e));
+            func = 7;
+            operation = f_file_operation_clone_s;
+
+            main->setting.state.status = f_file_clone(main->cache_arguments.array[i], main->cache_map.value, F_file_default_size_write_d, f_file_stat_flag_group_e | f_file_stat_flag_owner_e | (f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e));
           }
           else {
-            main->setting.state.status = f_file_copy(main->cache_arguments.array[i], main->cache_map.key, main->cache_recurse_do.mode, F_file_default_size_write_d, f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e);
-          }
-
-          if (F_status_is_error(main->setting.state.status)) {
-            function = clone ? &macro_fake_f(f_file_clone) : &macro_fake_f(f_file_copy);
-            operation = clone ? &f_file_operation_clone_s : &f_file_operation_copy_s;
-            type = fll_error_file_type_file_e;
+            func = 8;
+            operation = f_file_operation_copy_s;
 
-            break;
+            main->setting.state.status = f_file_copy(main->cache_arguments.array[i], main->cache_map.value, main->cache_recurse_do.mode, F_file_default_size_write_d, f_directory_recurse_do_flag_dereference_d ? 0 : f_file_stat_flag_reference_e);
           }
 
-          fake_make_print_verbose_operate_copy(&main->program.message, clone, main->cache_arguments.array[i], main->cache_map.key);
-        }
-        else if (F_status_is_error(main->setting.state.status)) {
-          function = &macro_fake_f(f_directory_is);
-          operation = &f_file_operation_identify_s;
-          type = fll_error_file_type_directory_e;
-
-          break;
+          if (F_status_is_error_not(main->cache_recurse_do.state.status)) {
+            fake_make_print_verbose_operate_copy(&main->program.message, clone, main->cache_arguments.array[i], main->cache_map.value);
+          }
         }
-      } // for
-    }
+      }
+    } // for
 
     if (F_status_is_error(main->setting.state.status)) {
-      fake_print_error_file(&main->program.error, *function, main->cache_arguments.array[1], *operation, type);
+      fake_print_error_file(
+        &main->program.error,
+        !func
+          ? macro_fake_f(f_memory_array_increase_by)
+          : func == 1
+            ? macro_fake_f(f_string_dynamic_append_nulless)
+            : func == 2
+              ? macro_fake_f(f_string_dynamic_append_assure)
+              : func == 3
+                ? macro_fake_f(f_string_dynamic_terminate_after)
+                : func == 4
+                  ? macro_fake_f(f_file_name_base)
+                  : func == 5
+                    ? macro_fake_f(f_directory_is)
+                    : func == 6
+                      ? macro_fake_f(fl_directory_do)
+                      : func == 7
+                        ? macro_fake_f(f_file_clone)
+                        : macro_fake_f(f_file_copy),
+        main->cache_arguments.used
+          ? main->cache_arguments.array[1]
+          : f_string_empty_s,
+        operation,
+        type
+      );
 
       main->setting.state.status = F_status_set_error(F_failure);
     }