]> Kevux Git Server - fll/commitdiff
Update: provide fll_path and fl_environment while providing an alternative to f_path_...
authorKevin Day <thekevinday@gmail.com>
Thu, 23 Jul 2020 01:57:02 +0000 (20:57 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 23 Jul 2020 02:03:49 +0000 (21:03 -0500)
The realpath() function does not work on non-existent paths.
Provide an alternative, fll_path_canonical(), that works on paths without concern for some paths existence.

The f_environment_path* functions need f_path, so move them to a new fl_environment project.

26 files changed:
build/level_1/settings
build/level_2/settings
build/monolithic/settings
build/scripts/bootstrap-example.sh
level_0/f_environment/c/environment.c
level_0/f_environment/c/environment.h
level_0/f_path/c/path.h
level_1/fl_environment/c/environment.c [new file with mode: 0644]
level_1/fl_environment/c/environment.h [new file with mode: 0644]
level_1/fl_environment/data/build/defines [new file with mode: 0644]
level_1/fl_environment/data/build/dependencies [new file with mode: 0644]
level_1/fl_environment/data/build/settings [new file with mode: 0644]
level_2/fll_execute/c/execute.c
level_2/fll_execute/c/execute.h
level_2/fll_execute/data/build/dependencies
level_2/fll_execute/data/build/settings
level_2/fll_path/c/path.c [new file with mode: 0644]
level_2/fll_path/c/path.h [new file with mode: 0644]
level_2/fll_path/data/build/defines [new file with mode: 0644]
level_2/fll_path/data/build/dependencies [new file with mode: 0644]
level_2/fll_path/data/build/settings [new file with mode: 0644]
level_3/fake/c/fake.h
level_3/fake/c/private-make.c
level_3/fake/c/private-make.h
level_3/fake/data/build/dependencies
level_3/fake/data/build/settings

index f62e84534d5af212a94f62d98f64cccb2e33d69c..dfda42546d7c73a16d979c07ac351a0ea799817c 100644 (file)
@@ -20,9 +20,9 @@ build_language c
 build_linker ar
 build_libraries -lc
 build_libraries-level -lfll_0
-build_sources_library color.c console.c conversion.c directory.c private-directory.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
+build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c private-fss.c iki.c print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
 build_sources_program
-build_sources_headers color.h console.h conversion.h directory.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
+build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
 build_sources_script
 build_sources_setting
 build_script yes
index a77c00c08cc18cc546e8fbd47b59bc51d2f96954..6c3f83cdd6d196c35bf538cde204e075bf845357 100644 (file)
@@ -20,9 +20,9 @@ build_language c
 build_linker ar
 build_libraries -lc
 build_libraries-level -lfll_1 -lfll_0
-build_sources_library execute.c private-execute.c file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c program.c status.c
+build_sources_library execute.c private-execute.c file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c path.c program.c status.c
 build_sources_program
-build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h program.h status.h
+build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h path.c program.h status.h
 build_sources_script
 build_sources_setting
 build_script yes
index 94c819685767030f7feac0f5906c558c6bca1155..06c63be32551ec455b1514ea2c551dbfb8e2ecfe 100644 (file)
@@ -20,9 +20,9 @@ build_language c
 build_linker ar
 build_libraries -lc
 build_libraries-monolithic
-build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c
+build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/environment.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/path.c level_2/program.c level_2/status.c
 build_sources_program
-build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h
+build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/path.h level_2/program.h level_2/status.h
 build_sources_script
 build_sources_setting
 build_script yes
index abd4f9633a82c5e19bf60344ae1b354b42088906..7b66ff1e370ba0523075e277dbf0ce3401d7f0e3 100644 (file)
@@ -23,7 +23,7 @@ if [[ $1 == "individual" ]] ; then
   bash build/scripts/package.sh build -i
 
   if [[ $? -eq 0 ]] ; then
-    for i in f_type f_status f_memory f_string f_utf f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_socket fl_color fl_console fl_conversion fl_directory fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_program fll_status ; do
+    for i in f_type f_status f_memory f_string f_utf f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_socket fl_color fl_console fl_conversion fl_directory fl_environment fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_path fll_program fll_status ; do
       echo && echo "Processing $i." &&
 
       cd package/individual/$i-$2/ &&
index 2bc15224c0e2b63d0a295ff58ff51423e17599c0..ccca0862babf31377bb2fcba6141236df1e704bb 100644 (file)
@@ -43,348 +43,6 @@ extern "C" {
   }
 #endif // _di_f_environment_get_dynamic_
 
-#ifndef _di_f_environment_path_explode_
-  f_return_status f_environment_path_explode(const f_string path, f_string_dynamics *paths) {
-    #ifndef _di_level_0_parameter_checking_
-      if (paths == 0) return F_status_set_error(F_parameter);
-      if (paths->used > paths->size) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
-
-    f_status status = F_none;
-    const f_string_length length = strnlen(path, PATH_MAX);
-
-    if (length == 0) {
-      // When PATH is "", this is actually a valid search path for PWD.
-      // Therefore append an equivalent representation of PWD (string used length is 0).
-      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-      if (F_status_is_error(status)) return status;
-
-      f_macro_string_dynamic_clear(paths->array[paths->used]);
-      paths->used++;
-
-      return F_none;
-    }
-
-    f_string_length i = length;
-    f_string_length first = 0;
-    f_string_length total = 0;
-
-    for (i = 0; i <= length; i++) {
-      if (i == length || path[i] == f_path_separator_variable[0]) {
-        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-        if (F_status_is_error(status)) return status;
-
-        if (i == 0) {
-          f_macro_string_dynamic_clear(paths->array[paths->used]);
-          paths->used++;
-
-          first = 1;
-          continue;
-        }
-
-        f_string_dynamic part = f_string_dynamic_initialize;
-
-        total = i - first;
-
-        if (total > 0) {
-          if (path[i - 1] == f_path_separator[0]) {
-            f_macro_string_dynamic_new(status, part, total);
-            if (F_status_is_error(status)) return status;
-
-            part.used = total;
-          }
-          else {
-            f_macro_string_dynamic_new(status, part, total + 1);
-            if (F_status_is_error(status)) return status;
-
-            part.string[total] = f_path_separator[0];
-            part.used = total + 1;
-          }
-
-          memcpy(part.string, path + first, total);
-        }
-
-        paths->array[paths->used].string = part.string;
-        paths->array[paths->used].used = part.used;
-        paths->array[paths->used].size = part.size;
-        paths->used++;
-
-        first = i + 1;
-      }
-    } // for
-
-    return F_none;
-  }
-#endif // _di_f_environment_path_explode_
-
-#ifndef _di_f_environment_path_explode_dynamic_
-  f_return_status f_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) {
-    #ifndef _di_level_0_parameter_checking_
-      if (path.used > path.size) return F_status_set_error(F_parameter);
-      if (paths == 0) return F_status_set_error(F_parameter);
-      if (paths->used > paths->size) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
-
-    f_status status = F_none;
-
-    if (path.used == 0) {
-      // When PATH is "", this is actually a valid search path for PWD.
-      // Therefore append an equivalent representation of PWD (string used length is 0).
-      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-      if (F_status_is_error(status)) return status;
-
-      f_macro_string_dynamic_clear(paths->array[paths->used]);
-      paths->used++;
-
-      return F_none;
-    }
-
-    f_string_length i = 0;
-    f_string_length j = 0;
-    f_string_length first = 0;
-    f_string_length total = 0;
-
-    f_string_dynamic part = f_string_dynamic_initialize;
-
-    for (i = 0; i <= path.used; i++) {
-      if (i == path.used || path.string[i] == f_path_separator_variable[0]) {
-        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-        if (F_status_is_error(status)) return status;
-
-        if (i == 0) {
-          f_macro_string_dynamic_clear(paths->array[paths->used]);
-          paths->used++;
-
-          first = 1;
-          continue;
-        }
-
-        total = i - first;
-
-        if (total > 0) {
-          f_macro_string_dynamic_new(status, part, total);
-          if (F_status_is_error(status)) return status;
-
-          for (j = 0; j < total; j++) {
-            if (path.string[first + j] == 0) continue;
-
-            part.string[part.used] = path.string[first + j];
-            part.used++;
-          } // for
-
-          if (part.string[part.used - 1] != f_path_separator[0]) {
-            f_macro_string_dynamic_resize(status, part, total + 1);
-            if (F_status_is_error(status)) return status;
-
-            part.string[part.used] = f_path_separator[0];
-            part.used++;
-          }
-        }
-
-        paths->array[paths->used].string = part.string;
-        paths->array[paths->used].used = part.used;
-        paths->array[paths->used].size = part.size;
-        paths->used++;
-
-        first = i + 1;
-      }
-    } // for
-
-    return F_none;
-  }
-#endif // _di_f_environment_path_explode_dynamic_
-
-#ifndef _di_f_environment_path_explode_reverse_
-  f_return_status f_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths) {
-    #ifndef _di_level_0_parameter_checking_
-      if (paths == 0) return F_status_set_error(F_parameter);
-      if (paths->used > paths->size) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
-
-    f_status status = F_none;
-    const f_string_length length = strnlen(path, PATH_MAX);
-
-    if (length == 0) {
-      // When PATH is "", this is actually a valid search path for PWD.
-      // Therefore append an equivalent representation of PWD (string used length is 0).
-      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-      if (F_status_is_error(status)) return status;
-
-      paths->array[paths->used].string = 0;
-      paths->array[paths->used].used = 0;
-      paths->array[paths->used].size = 0;
-      paths->used++;
-
-      return F_none;
-    }
-
-    f_string_length i = length;
-    f_string_length j = length;
-    f_string_length last = length;
-    f_string_length total = 0;
-
-    f_string_dynamic part = f_string_dynamic_initialize;
-
-    for (; i > 0; i--) {
-      j--;
-
-      if (j == 0 || path[j] == f_path_separator_variable[0]) {
-        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-        if (F_status_is_error(status)) return status;
-
-        if (path[j] == f_path_separator_variable[0]) {
-          total = last - i;
-
-          if (total > 0) {
-            if (path[j + total] == f_path_separator[0]) {
-              f_macro_string_dynamic_new(status, part, total);
-              if (F_status_is_error(status)) return status;
-
-              part.used = total;
-            }
-            else {
-              f_macro_string_dynamic_new(status, part, total + 1);
-              if (F_status_is_error(status)) return status;
-
-              part.string[total] = f_path_separator[0];
-              part.used = total + 1;
-            }
-
-            memcpy(part.string, path + i, total);
-          }
-
-          last = j;
-        }
-        else if (j == 0) {
-          // when j = 0, the total is actually the entire length to max.
-          total = last - j;
-
-          if (total > 0) {
-            if (path[last - 1] == f_path_separator[0]) {
-              f_macro_string_dynamic_new(status, part, total);
-              if (F_status_is_error(status)) return status;
-
-              part.used = total;
-            }
-            else {
-              f_macro_string_dynamic_new(status, part, total + 1);
-              if (F_status_is_error(status)) return status;
-
-              part.used = total + 1;
-              part.string[total] = f_path_separator[0];
-            }
-
-            memcpy(part.string, path, total);
-          }
-        }
-
-        paths->array[paths->used].string = part.string;
-        paths->array[paths->used].used = part.used;
-        paths->array[paths->used].size = part.size;
-        paths->used++;
-      }
-    } // for
-
-    return F_none;
-  }
-#endif // _di_f_environment_path_explode_reverse_
-
-#ifndef _di_f_environment_path_explode_reverse_dynamic_
-  f_return_status f_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) {
-    #ifndef _di_level_0_parameter_checking_
-      if (path.used > path.size) return F_status_set_error(F_parameter);
-      if (paths == 0) return F_status_set_error(F_parameter);
-      if (paths->used > paths->size) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
-
-    f_status status = F_none;
-
-    if (path.used == 0) {
-      // When PATH is "", this is actually a valid search path for PWD.
-      // Therefore append an equivalent representation of PWD (string used length is 0).
-      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-      if (F_status_is_error(status)) return status;
-
-      f_macro_string_dynamic_clear(paths->array[paths->used]);
-      paths->used++;
-
-      return F_none;
-    }
-
-    f_string_length i = path.used;
-    f_string_length j = path.used;
-    f_string_length k = 0;
-    f_string_length last = path.used;
-    f_string_length total = 0;
-
-    f_string_dynamic part = f_string_dynamic_initialize;
-
-    for (; i > 0; i--) {
-      j--;
-
-      if (j == 0 || path.string[j] == f_path_separator_variable[0]) {
-        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
-        if (F_status_is_error(status)) return status;
-
-        if (path.string[j] == f_path_separator_variable[0]) {
-          total = last - i;
-
-          if (total > 0) {
-            f_macro_string_dynamic_new(status, part, total);
-            if (F_status_is_error(status)) return status;
-
-            for (k = 0; k < total; k++) {
-              if (path.string[i + k] == 0) continue;
-
-              part.string[part.used] = path.string[i + k];
-              part.used++;
-            } // for
-
-            if (part.string[part.used - 1] != f_path_separator[0]) {
-              f_macro_string_dynamic_resize(status, part, total + 1);
-              if (F_status_is_error(status)) return status;
-
-              part.string[part.used] = f_path_separator[0];
-              part.used++;
-            }
-          }
-
-          last = j;
-        }
-        else if (j == 0) {
-          // when j = 0, the total is actually the entire length to max.
-          total = last - j;
-
-          f_macro_string_dynamic_new(status, part, total);
-          if (F_status_is_error(status)) return status;
-
-          for (k = 0; k < total; k++) {
-            if (path.string[i + k] == 0) continue;
-
-            part.string[part.used] = path.string[i + k];
-            part.used++;
-          } // for
-
-          if (part.string[part.used - 1] != f_path_separator[0]) {
-            f_macro_string_dynamic_resize(status, part, total + 1);
-            if (F_status_is_error(status)) return status;
-
-            part.string[part.used - 1] = f_path_separator[0];
-            part.used++;
-          }
-        }
-
-        paths->array[paths->used].string = part.string;
-        paths->array[paths->used].used = part.used;
-        paths->array[paths->used].size = part.size;
-        paths->used++;
-      }
-    } // for
-
-    return F_none;
-  }
-#endif // _di_f_environment_path_explode_reverse_dynamic_
-
 #ifndef _di_f_environment_set_
   f_return_status f_environment_set(const f_string name, const f_string value, const bool replace) {
     return private_f_environment_set(name, value, replace);
index 19a10f8183f847afc47b9f74dbe3dac07c56df70..be12382b9eecd1b07137daf3e1710b1d1cf59315 100644 (file)
@@ -99,106 +99,6 @@ extern "C" {
 #endif // _di_f_environment_get_dynamic_
 
 /**
- * Separate a given PATH-style string into multiple separate paths.
- *
- * @param path
- *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
- *   Each seperate path is separated by a single ':'.
- *   Must not contain NULLs except for the terminating NULL.
- *   Must be NULL terminated.
- * @param paths
- *   All of the strings exploded from PATH.
- *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
- *   Each exploded path is not NULL terminated.
- *
- * @return
- *   F_none on success.
- *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
- *   F_memory_reallocation (with error bit) on reallocation error.
- *   F_memory_allocation (with error bit) on allocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_f_environment_path_explode_
-  extern f_return_status f_environment_path_explode(const f_string path, f_string_dynamics *paths);
-#endif // _di_f_environment_path_explode_
-
-/**
- * Separate a given PATH-style string into multiple separate paths.
- *
- * @param path
- *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
- *   Each seperate path is separated by a single ':'.
- *   Need not be NULL terminated.
- *   NULLs are ignored and are not copied into the exploded paths.
- * @param paths
- *   All of the strings exploded from PATH.
- *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
- *   Each exploded path is not NULL terminated.
- *
- * @return
- *   F_none on success.
- *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
- *   F_memory_reallocation (with error bit) on reallocation error.
- *   F_memory_allocation (with error bit) on allocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_f_environment_path_explode_dynamic_
-  extern f_return_status f_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths);
-#endif // _di_f_environment_path_explode_dynamic_
-
-/**
- * Separate a given PATH-style string into multiple separate paths.
- *
- * The paths are created in reverse order.
- *
- * @param path
- *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
- *   Each seperate path is separated by a single ':'.
- *   Must not contain NULLs except for the terminating NULL.
- *   Must be NULL terminated.
- * @param paths
- *   All of the strings exploded from PATH.
- *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
- *   Each exploded path is not NULL terminated.
- *
- * @return
- *   F_none on success.
- *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
- *   F_memory_reallocation (with error bit) on reallocation error.
- *   F_memory_allocation (with error bit) on allocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_f_environment_path_explode_reverse_
-  extern f_return_status f_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths);
-#endif // _di_f_environment_path_explode_reverse_
-
-/**
- * Separate a given PATH-style string into multiple separate paths.
- *
- * The paths are created in reverse order.
- *
- * @param path
- *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
- *   Each seperate path is separated by a single ':'.
- *   Need not be NULL terminated.
- *   NULLs are ignored and are not copied into the exploded paths.
- * @param paths
- *   All of the strings exploded from PATH.
- *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
- *   Each exploded path is not NULL terminated.
- *
- * @return
- *   F_none on success.
- *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
- *   F_memory_reallocation (with error bit) on reallocation error.
- *   F_memory_allocation (with error bit) on allocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_f_environment_path_explode_reverse_dynamic_
-  extern f_return_status f_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths);
-#endif // _di_f_environment_path_explode_reverse_dynamic_
-
-/**
  * Assign the given value to the named environment variable.
  *
  * If the name does not exist, then it is created.
index 5160fd72c7abdde40bdc50bebbc1c30a7282373c..1490d6b6d872c39455112315e0da00dcf1e7208b 100644 (file)
@@ -146,12 +146,16 @@ extern "C" {
 #endif // _di_f_path_current_
 
 /**
- * Get the real path for some path.
+ * Get the real path for the given path.
  *
- * All symbolic links and relative path parts are expanded to yield the real full path.
+ * This does check to see if the path exists or not (path must exist).
+ * This processes all relative parts.
+ * This processes all symbolic links.
+ * This has a max size of f_path_max + 1.
  *
  * @param path
  *   The source path to determine what the real path is.
+ *   This is a NULL terminated string.
  * @param real
  *   The (allocated) real file path.
  *   This will have a max size of f_path_max + 1.
diff --git a/level_1/fl_environment/c/environment.c b/level_1/fl_environment/c/environment.c
new file mode 100644 (file)
index 0000000..15430d9
--- /dev/null
@@ -0,0 +1,351 @@
+#include <level_1/environment.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fl_environment_path_explode_
+  f_return_status fl_environment_path_explode(const f_string path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (paths == 0) return F_status_set_error(F_parameter);
+      if (paths->used > paths->size) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = F_none;
+    const f_string_length length = strnlen(path, PATH_MAX);
+
+    if (length == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Append an equivalent representation of PWD (string used length is 0).
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
+
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
+      paths->used++;
+
+      return F_none;
+    }
+
+    f_string_length i = length;
+    f_string_length first = 0;
+    f_string_length total = 0;
+
+    for (i = 0; i <= length; i++) {
+      if (i == length || path[i] == f_path_separator_variable[0]) {
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
+
+        if (i == 0) {
+          f_macro_string_dynamic_clear(paths->array[paths->used]);
+          paths->used++;
+
+          first = 1;
+          continue;
+        }
+
+        f_string_dynamic part = f_string_dynamic_initialize;
+
+        total = i - first;
+
+        if (total > 0) {
+          if (path[i - 1] == f_path_separator[0]) {
+            f_macro_string_dynamic_new(status, part, total);
+            if (F_status_is_error(status)) return status;
+
+            part.used = total;
+          }
+          else {
+            f_macro_string_dynamic_new(status, part, total + 1);
+            if (F_status_is_error(status)) return status;
+
+            part.string[total] = f_path_separator[0];
+            part.used = total + 1;
+          }
+
+          memcpy(part.string, path + first, total);
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+
+        first = i + 1;
+      }
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fl_environment_path_explode_
+
+#ifndef _di_fl_environment_path_explode_dynamic_
+  f_return_status fl_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path.used > path.size) return F_status_set_error(F_parameter);
+      if (paths == 0) return F_status_set_error(F_parameter);
+      if (paths->used > paths->size) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = F_none;
+
+    if (path.used == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
+
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
+      paths->used++;
+
+      return F_none;
+    }
+
+    f_string_length i = 0;
+    f_string_length j = 0;
+    f_string_length first = 0;
+    f_string_length total = 0;
+
+    f_string_dynamic part = f_string_dynamic_initialize;
+
+    for (i = 0; i <= path.used; i++) {
+      if (i == path.used || path.string[i] == f_path_separator_variable[0]) {
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
+
+        if (i == 0) {
+          f_macro_string_dynamic_clear(paths->array[paths->used]);
+          paths->used++;
+
+          first = 1;
+          continue;
+        }
+
+        total = i - first;
+
+        if (total > 0) {
+          f_macro_string_dynamic_new(status, part, total);
+          if (F_status_is_error(status)) return status;
+
+          for (j = 0; j < total; j++) {
+            if (path.string[first + j] == 0) continue;
+
+            part.string[part.used] = path.string[first + j];
+            part.used++;
+          } // for
+
+          if (part.string[part.used - 1] != f_path_separator[0]) {
+            f_macro_string_dynamic_resize(status, part, total + 1);
+            if (F_status_is_error(status)) return status;
+
+            part.string[part.used] = f_path_separator[0];
+            part.used++;
+          }
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+
+        first = i + 1;
+      }
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fl_environment_path_explode_dynamic_
+
+#ifndef _di_fl_environment_path_explode_reverse_
+  f_return_status fl_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (paths == 0) return F_status_set_error(F_parameter);
+      if (paths->used > paths->size) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = F_none;
+    const f_string_length length = strnlen(path, PATH_MAX);
+
+    if (length == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
+
+      paths->array[paths->used].string = 0;
+      paths->array[paths->used].used = 0;
+      paths->array[paths->used].size = 0;
+      paths->used++;
+
+      return F_none;
+    }
+
+    f_string_length i = length;
+    f_string_length j = length;
+    f_string_length last = length;
+    f_string_length total = 0;
+
+    f_string_dynamic part = f_string_dynamic_initialize;
+
+    for (; i > 0; i--) {
+      j--;
+
+      if (j == 0 || path[j] == f_path_separator_variable[0]) {
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
+
+        if (path[j] == f_path_separator_variable[0]) {
+          total = last - i;
+
+          if (total > 0) {
+            if (path[j + total] == f_path_separator[0]) {
+              f_macro_string_dynamic_new(status, part, total);
+              if (F_status_is_error(status)) return status;
+
+              part.used = total;
+            }
+            else {
+              f_macro_string_dynamic_new(status, part, total + 1);
+              if (F_status_is_error(status)) return status;
+
+              part.string[total] = f_path_separator[0];
+              part.used = total + 1;
+            }
+
+            memcpy(part.string, path + i, total);
+          }
+
+          last = j;
+        }
+        else if (j == 0) {
+          // when j = 0, the total is actually the entire length to max.
+          total = last - j;
+
+          if (total > 0) {
+            if (path[last - 1] == f_path_separator[0]) {
+              f_macro_string_dynamic_new(status, part, total);
+              if (F_status_is_error(status)) return status;
+
+              part.used = total;
+            }
+            else {
+              f_macro_string_dynamic_new(status, part, total + 1);
+              if (F_status_is_error(status)) return status;
+
+              part.used = total + 1;
+              part.string[total] = f_path_separator[0];
+            }
+
+            memcpy(part.string, path, total);
+          }
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+      }
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fl_environment_path_explode_reverse_
+
+#ifndef _di_fl_environment_path_explode_reverse_dynamic_
+  f_return_status fl_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path.used > path.size) return F_status_set_error(F_parameter);
+      if (paths == 0) return F_status_set_error(F_parameter);
+      if (paths->used > paths->size) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = F_none;
+
+    if (path.used == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
+      f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+      if (F_status_is_error(status)) return status;
+
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
+      paths->used++;
+
+      return F_none;
+    }
+
+    f_string_length i = path.used;
+    f_string_length j = path.used;
+    f_string_length k = 0;
+    f_string_length last = path.used;
+    f_string_length total = 0;
+
+    f_string_dynamic part = f_string_dynamic_initialize;
+
+    for (; i > 0; i--) {
+      j--;
+
+      if (j == 0 || path.string[j] == f_path_separator_variable[0]) {
+        f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large);
+        if (F_status_is_error(status)) return status;
+
+        if (path.string[j] == f_path_separator_variable[0]) {
+          total = last - i;
+
+          if (total > 0) {
+            f_macro_string_dynamic_new(status, part, total);
+            if (F_status_is_error(status)) return status;
+
+            for (k = 0; k < total; k++) {
+              if (path.string[i + k] == 0) continue;
+
+              part.string[part.used] = path.string[i + k];
+              part.used++;
+            } // for
+
+            if (part.string[part.used - 1] != f_path_separator[0]) {
+              f_macro_string_dynamic_resize(status, part, total + 1);
+              if (F_status_is_error(status)) return status;
+
+              part.string[part.used] = f_path_separator[0];
+              part.used++;
+            }
+          }
+
+          last = j;
+        }
+        else if (j == 0) {
+          // when j = 0, the total is actually the entire length to max.
+          total = last - j;
+
+          f_macro_string_dynamic_new(status, part, total);
+          if (F_status_is_error(status)) return status;
+
+          for (k = 0; k < total; k++) {
+            if (path.string[i + k] == 0) continue;
+
+            part.string[part.used] = path.string[i + k];
+            part.used++;
+          } // for
+
+          if (part.string[part.used - 1] != f_path_separator[0]) {
+            f_macro_string_dynamic_resize(status, part, total + 1);
+            if (F_status_is_error(status)) return status;
+
+            part.string[part.used - 1] = f_path_separator[0];
+            part.used++;
+          }
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+      }
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fl_environment_path_explode_reverse_dynamic_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_1/fl_environment/c/environment.h b/level_1/fl_environment/c/environment.h
new file mode 100644 (file)
index 0000000..c3e49b6
--- /dev/null
@@ -0,0 +1,132 @@
+/**
+ * FLL - Level 1
+ *
+ * Project: Environment
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides environment processing functionality, such as environment variable handling.
+ */
+#ifndef _FL_environment_h
+#define _FL_environment_h
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/environment.h>
+#include <level_0/path.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Must not contain NULLs except for the terminating NULL.
+ *   Must be NULL terminated.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_memory_allocation (with error bit) on allocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fl_environment_path_explode_
+  extern f_return_status fl_environment_path_explode(const f_string path, f_string_dynamics *paths);
+#endif // _di_fl_environment_path_explode_
+
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Need not be NULL terminated.
+ *   NULLs are ignored and are not copied into the exploded paths.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_memory_allocation (with error bit) on allocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fl_environment_path_explode_dynamic_
+  extern f_return_status fl_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths);
+#endif // _di_fl_environment_path_explode_dynamic_
+
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * The paths are created in reverse order.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Must not contain NULLs except for the terminating NULL.
+ *   Must be NULL terminated.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_memory_allocation (with error bit) on allocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fl_environment_path_explode_reverse_
+  extern f_return_status fl_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths);
+#endif // _di_fl_environment_path_explode_reverse_
+
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * The paths are created in reverse order.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Need not be NULL terminated.
+ *   NULLs are ignored and are not copied into the exploded paths.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_memory_allocation (with error bit) on allocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fl_environment_path_explode_reverse_dynamic_
+  extern f_return_status fl_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths);
+#endif // _di_fl_environment_path_explode_reverse_dynamic_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FL_environment_h
diff --git a/level_1/fl_environment/data/build/defines b/level_1/fl_environment/data/build/defines
new file mode 100644 (file)
index 0000000..c665317
--- /dev/null
@@ -0,0 +1,2 @@
+# fss-0000
+
diff --git a/level_1/fl_environment/data/build/dependencies b/level_1/fl_environment/data/build/dependencies
new file mode 100644 (file)
index 0000000..2e9e9f3
--- /dev/null
@@ -0,0 +1,9 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_environment
+f_path
diff --git a/level_1/fl_environment/data/build/settings b/level_1/fl_environment/data/build/settings
new file mode 100644 (file)
index 0000000..9a42638
--- /dev/null
@@ -0,0 +1,52 @@
+# fss-0001
+
+project_name fl_environment
+
+version_major 0
+version_minor 5
+version_micro 0
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual
+modes_default individual
+
+build_compiler gcc
+build_language c
+build_linker ar
+build_libraries -lc
+build_libraries-individual -lf_environment -lf_path -lf_utf -lf_memory
+build_sources_library environment.c
+build_sources_program
+build_sources_headers environment.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_1
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
index eb323a4f618d53b16c92e780b2469967e542fa1c..413edb50244f3140919c86ac12d53ab178ac5ae3 100644 (file)
@@ -587,7 +587,7 @@ extern "C" {
       }
     }
     else {
-      status = f_environment_path_explode_dynamic(path, &paths);
+      status = fl_environment_path_explode_dynamic(path, &paths);
     }
 
     if (F_status_is_error(status)) {
index dd97c372f09d997717f635e5f5ae9b9f1daf5515..16e22a3be8789477ec6388b2fac6cb499db1aef2 100644 (file)
@@ -28,6 +28,7 @@
 #include <level_0/path.h>
 
 // fll-1 includes
+#include <level_1/environment.h>
 #include <level_1/string.h>
 
 #ifdef __cplusplus
index f2299d5d790f338cc29f8ef2b5ccc2c74d7ad567..6c62d3b049d94e03a961afa6bd386c51ba2e9886 100644 (file)
@@ -7,4 +7,5 @@ f_string
 f_environment
 f_file
 f_path
+fl_environment
 fl_string
index 70484c8e4f8df26a8bbf710f43ae983d552f2cd1..27468a9c03f08acc651cc8020356c7e42dd394c2 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_language c
 build_linker ar
 build_libraries -lc
-build_libraries-individual -lfl_string -lf_utf -lf_path -lf_file -lf_environment -lf_memory
+build_libraries-individual -lfl_environment -lfl_string -lf_utf -lf_path -lf_file -lf_environment -lf_memory
 build_sources_library execute.c private-execute.c
 build_sources_program
 build_sources_headers execute.h
diff --git a/level_2/fll_path/c/path.c b/level_2/fll_path/c/path.c
new file mode 100644 (file)
index 0000000..57177c7
--- /dev/null
@@ -0,0 +1,140 @@
+#include <level_2/path.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fll_path_canonical_
+  f_return_status fll_path_canonical(const f_string path, f_string_dynamic *canonical) {
+    #ifndef _di_level_2_parameter_checking_
+      if (canonical == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    f_status status = F_none;
+    f_string_length at = 0;
+
+    uint8_t previous_1 = 0;
+    uint8_t previous_2 = 0;
+
+    f_string_length size_chunk = 0;
+    f_string_length position = 0;
+
+    canonical->used = 0;
+
+    if (path[0] == '/') {
+      previous_1 = '/';
+      at = 1;
+    }
+    else {
+      status = f_path_current(F_true, canonical);
+      if (F_status_is_error(status)) return status;
+
+      if (!path[0]) {
+        return F_none;
+      }
+    }
+
+    status = fl_string_append_assure("/", 1, canonical);
+    if (F_status_is_error(status)) return status;
+
+    for (; path[at]; at++) {
+
+      if (!size_chunk && path[at] == '.') {
+        if (!previous_1 || previous_1 == '/') {
+          previous_1 = '.';
+          previous_2 = 0;
+          continue;
+        }
+
+        if (previous_1 == '.') {
+          if (previous_2) {
+            previous_1 = 0;
+            previous_2 = 0;
+            size_chunk = 3;
+            position = at - 2;
+          }
+          else {
+            previous_2 = '.';
+          }
+        }
+      }
+      else if (path[at] == '/') {
+        if (previous_1 == '/') {
+          size_chunk = 0;
+          position = 0;
+          continue;
+        }
+
+        if (previous_1 == '.') {
+          if (previous_2 == '.') {
+            if (canonical->used > 1) {
+              for (canonical->used--; canonical->used > 0; canonical->used--) {
+                if (canonical->string[canonical->used - 1] == '/') break;
+              } // for
+            }
+          }
+        }
+        else {
+          size_chunk++;
+
+          status = fl_string_append(path + position, size_chunk, canonical);
+          if (F_status_is_error(status)) return status;
+        }
+
+        previous_1 = '/';
+        previous_2 = 0;
+        size_chunk = 0;
+        position = 0;
+      }
+      else {
+        if (!size_chunk) {
+          position = at;
+
+          if (previous_2) {
+            position -= 2;
+            size_chunk = 2;
+          }
+          else if (previous_1) {
+            position--;
+            size_chunk = 1;
+          }
+        }
+
+        if (previous_1) {
+          previous_1 = 0;
+          previous_2 = 0;
+        }
+
+        size_chunk++;
+      }
+    } // for
+
+    if (previous_2 == '.') {
+      if (canonical->used > 1) {
+        for (canonical->used--; canonical->used > 0; canonical->used--) {
+          if (canonical->string[canonical->used - 1] == '/') break;
+        } // for
+      }
+    }
+    else if (!(previous_1 == '.' || previous_1 == '/')) {
+      if (size_chunk) {
+        status = fl_string_append(path + position, size_chunk, canonical);
+        if (F_status_is_error(status)) return status;
+      }
+    }
+
+    // assure there is no trailing forward slash, unless it is the first slash.
+    if (canonical->used > 1 && canonical->string[canonical->used - 1] == '/') {
+      canonical->used--;
+    }
+
+    status = fl_string_dynamic_terminate_after(canonical);
+    if (F_status_is_error(status)) return status;
+
+    return F_none;
+  }
+#endif // _di_fll_path_canonical_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_2/fll_path/c/path.h b/level_2/fll_path/c/path.h
new file mode 100644 (file)
index 0000000..9672772
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides path-related functionality.
+ */
+#ifndef _FLL_path_h
+#define _FLL_path_h
+
+// libc includes
+#include <stdio.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/path.h>
+
+// fll-1 includes
+#include <level_1/string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the canonical (real) path for some path.
+ *
+ * This does not check if the path exists or not.
+ * This processes the relative parts: './', '../', and extra '/'.
+ * This does not process symbolic links.
+ * This has a max size of f_string_length_size.
+ *
+ * @param path
+ *   The source path to determine what the canonical path is.
+ *   This is a NULL terminated string.
+ * @param canonical
+ *   The (allocated) canonical file path.
+ *   The canonical->used is reset to 0 before processing.
+ *   This will be NULL terminated at canonical->used + 1.
+ *
+ * @return
+ *   F_none on success.
+ */
+#ifndef _di_fll_path_canonical_
+  extern f_return_status fll_path_canonical(const f_string path, f_string_dynamic *canonical);
+#endif // _di_fll_path_canonical_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FLL_path_h
diff --git a/level_2/fll_path/data/build/defines b/level_2/fll_path/data/build/defines
new file mode 100644 (file)
index 0000000..c665317
--- /dev/null
@@ -0,0 +1,2 @@
+# fss-0000
+
diff --git a/level_2/fll_path/data/build/dependencies b/level_2/fll_path/data/build/dependencies
new file mode 100644 (file)
index 0000000..2815ad2
--- /dev/null
@@ -0,0 +1,8 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_path
+fl_string
diff --git a/level_2/fll_path/data/build/settings b/level_2/fll_path/data/build/settings
new file mode 100644 (file)
index 0000000..41800b3
--- /dev/null
@@ -0,0 +1,52 @@
+# fss-0001
+
+project_name fll_path
+
+version_major 0
+version_minor 5
+version_micro 0
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual
+modes_default individual
+
+build_compiler gcc
+build_language c
+build_linker ar
+build_libraries -lc
+build_libraries-individual -lfl_string -lf_path -lf_memory
+build_sources_library path.c
+build_sources_program
+build_sources_headers path.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_2
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
index f115eb273596266cd71baa9313672006d553c1da..ec9ce249dc67687e168916f9bfa287f9447d63e6 100644 (file)
@@ -75,6 +75,7 @@
 #include <level_2/fss.h>
 #include <level_2/fss_basic_list.h>
 #include <level_2/fss_extended.h>
+#include <level_2/path.h>
 #include <level_2/program.h>
 
 #ifdef __cplusplus
index 04c29130c164abb3076fc3a09fff2135cd7cc003..e8a2cfefdfcb2d2c0ed41a650c90f8f53b7163e7 100644 (file)
@@ -15,7 +15,7 @@ extern "C" {
 
     data_make->path_cache.used = 0;
 
-    f_status status = f_path_real(path.string, &data_make->path_cache);
+    f_status status = fll_path_canonical(path.string, &data_make->path_cache);
     if (F_status_is_error(status)) return status;
 
     if (data_make->path_cache.used < data_make->path.stack.array[0].used) {
@@ -1235,7 +1235,7 @@ extern "C" {
       fake_make_operate_expand(data, section->name, operation, *operation_name, section->contents.array[i], section->quotedss.array[i], data_make, &arguments[i], status);
       if (F_status_is_error(*status)) break;
 
-      fake_make_operate_validate(data, section->name, operation, *operation_name, *data_make, arguments[i], operation_if, status);
+      fake_make_operate_validate(data, section->name, operation, *operation_name, arguments[i], operation_if, data_make, status);
 
       if (operation_if) {
         if (operation_if == fake_make_operation_if_type_if) {
@@ -1547,7 +1547,13 @@ extern "C" {
         *status = f_file_touch(arguments.array[1].string, mode.regular, F_false);
 
         if (F_status_is_error(*status)) {
-          fake_print_error(data, F_status_set_fine(*status), "f_file_touch", F_true);
+          if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", data_make->path_cache.string, "touch", F_true, F_true);
+          }
+          else {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", arguments.array[1].string, "touch", F_true, F_true);
+          }
+
           return;
         }
       }
@@ -1555,7 +1561,13 @@ extern "C" {
         *status = f_directory_touch(arguments.array[1].string, mode.directory);
 
         if (F_status_is_error(*status)) {
-          fake_print_error(data, F_status_set_fine(*status), "f_directory_touch", F_true);
+          if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", data_make->path_cache.string, "touch", F_false, F_true);
+          }
+          else {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", arguments.array[1].string, "touch", F_false, F_true);
+          }
+
           return;
         }
       }
@@ -1734,7 +1746,7 @@ extern "C" {
 #endif // _di_fake_make_operate_process_run_
 
 #ifndef _di_fake_make_operate_validate_
-  void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) {
+  void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) {
     if (F_status_is_error(*status)) return;
 
     if (operation == fake_make_operation_type_archive || operation == fake_make_operation_type_run || operation == fake_make_operation_type_shell) {
@@ -1790,7 +1802,7 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
       else if (operation == fake_make_operation_type_pop) {
-        if (data_make.path.stack.used == 1) {
+        if (data_make->path.stack.used == 1) {
           printf("%c", f_string_eol[0]);
           fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Must not attempt to pop project root off of path stack.");
 
@@ -2082,7 +2094,14 @@ extern "C" {
           }
         }
 
-        // @todo: fake_make_assure_inside_project
+        *status = fake_make_assure_inside_project(data, arguments.array[1], data_make);
+        if (F_status_is_error(*status)) {
+          fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", arguments.array[1].string);
+
+          if (F_status_set_fine(*status) == F_false) {
+            *status = F_status_set_error(F_failure);
+          }
+        }
       }
       else {
         printf("%c", f_string_eol[0]);
index 73e2038e1c3a8a9c5e611599e80764b660b13db0..f9ea2c9ae57f4ff1fda22e5467d72cbfb11da813 100644 (file)
@@ -559,19 +559,19 @@ extern "C" {
  *   The operation being performed.
  * @param operation_name
  *   The operation name.
- * @param data_make
- *   All make related setting data, including data from the fakefile and optionally build settings file.
  * @param arguments
  *   The expanded arguments.
  * @param operation_if
  *   The if-condition status for the current operation.
+ * @param data_make
+ *   All make related setting data, including data from the fakefile and optionally build settings file.
  * @param status
  *   The return status.
  *
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fake_make_operate_validate_
-  extern void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) f_gcc_attribute_visibility_internal;
+  extern void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_make_operate_validate_
 
 /**
index e114de724aece3e7da21cee8d6162e599555a7b5..2a05f0899a948e7c32c3b42a26caa5ad52ab964f 100644 (file)
@@ -26,4 +26,5 @@ fl_string
 fl_utf
 fll_fss
 fll_execute
+fll_path
 fll_program
index ba781b97e259e50daa6b9d6bef064802a89c7a4c..09e5000e4d4a9f4e9c51993ce2c5901ec4f8e8c4 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_language c
 build_linker ar
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_execute -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_execute -lfll_fss -lfll_path -lfll_program -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c