From bc9c1849a37d8b5dac42388197e558d950ed8524 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 12 Feb 2023 10:22:20 -0600 Subject: [PATCH] Feature: Add Turtle Kevux path support. This does not break API or ABI because it requires macros to be defined that would break it. These macros, when in use, should not break API (but does extend it) but may break ABI. The return value may have additional results and might be considered an API but not ABI breaking change. There is already Kevux-specific code in FLL. Temporarily continue that process as a short term solution. In the long term, separate functions or files may be used (or an entirely separate project). --- level_0/f_path/c/path/common.c | 6 + level_0/f_path/c/path/common.h | 61 +++++++++ level_0/f_path/data/build/defines | 5 + level_1/fl_environment/c/environment.c | 210 +++++++++++++++++++++++++++++- level_1/fl_environment/c/environment.h | 4 + level_1/fl_environment/data/build/defines | 1 + level_2/fll_execute/c/execute.c | 2 +- level_2/fll_execute/data/build/defines | 1 + 8 files changed, 283 insertions(+), 7 deletions(-) diff --git a/level_0/f_path/c/path/common.c b/level_0/f_path/c/path/common.c index 9dc37f1..afdc3b0 100644 --- a/level_0/f_path/c/path/common.c +++ b/level_0/f_path/c/path/common.c @@ -15,6 +15,12 @@ extern "C" { const f_string_static_t f_path_home_wildcard_s = macro_f_string_static_t_initialize(F_string_ascii_tilde_s, 0, F_string_ascii_tilde_s_length); const f_string_static_t f_path_present_working_s = macro_f_string_static_t_initialize(F_path_present_working_s, 0, F_path_present_working_s_length); const f_string_static_t f_path_present_working_old_s = macro_f_string_static_t_initialize(F_path_present_working_old_s, 0, F_path_present_working_old_s_length); + + #ifdef _en_kevux_path_architecture_bits_ + const f_string_static_t f_path_architecture_bits_s = macro_f_string_static_t_initialize(F_path_architecture_bits_s, 0, F_path_architecture_bits_s_length); + const f_string_static_t f_path_architecture_bits_default_s = macro_f_string_static_t_initialize(F_path_architecture_bits_default_s, 0, F_path_architecture_bits_default_s_length); + const f_string_static_t f_path_architecture_bits_scripts_s = macro_f_string_static_t_initialize(F_path_architecture_bits_scripts_s, 0, F_path_architecture_bits_scripts_s_length); + #endif // _en_kevux_path_architecture_bits_ #endif // _di_f_path_defines_ #if defined(_di_f_path_tree_s_) && !defined(_di_f_path_tree_hierarchy_standard_) && !defined(_di_f_path_tree_kevux_standard_) diff --git a/level_0/f_path/c/path/common.h b/level_0/f_path/c/path/common.h index f266f9e..e3da242 100644 --- a/level_0/f_path/c/path/common.h +++ b/level_0/f_path/c/path/common.h @@ -66,6 +66,67 @@ extern "C" { extern const f_string_static_t f_path_home_wildcard_s; extern const f_string_static_t f_path_present_working_s; extern const f_string_static_t f_path_present_working_old_s; + + /** + * Provide Kevux ARCHITECTURE_BITS environment variable handling support. + * + * Non-Kevux systems should not need this and enabling this might cause problems. + * + * This uses the defines for customizing the architecture bits (and scripts) path: + * - _en_kevux_path_architecture_bits_default_name_ + * - _en_kevux_path_architecture_bits_default_length_ + * - _en_kevux_path_architecture_bits_scripts_name_ + * - _en_kevux_path_architecture_bits_scripts_length_ + * + * The path separator should not be specified for these defines because it is automatically appended. + * Disable either the default or scripts by setting the length to 0. + * + * F_path_*_s: + * - architecture_bits: The architecture bits environment variable (usually is "ARCHITECTURE_BITS"). + * - architecture_bits_default: The default architecture bits string with a trailing path separator, such as "x64/". + * - architecture_bits_scripts: The default architecture bits string with a trailing path separator, such as "scripts/". + */ + #ifdef _en_kevux_path_architecture_bits_ + #define F_path_architecture_bits_s "ARCHITECTURE_BITS" + + #define F_path_architecture_bits_s_length 17 + + #if defined(_en_kevux_path_architecture_bits_default_name_) && defined(_en_kevux_path_architecture_bits_default_length_) + #if _en_kevux_path_architecture_bits_default_length_ == 0 + #define F_path_architecture_bits_default_s F_string_empty_s + + #define F_path_architecture_bits_default_s_length F_string_empty_s_length + #else + #define F_path_architecture_bits_default_s _en_kevux_path_architecture_bits_default_name_ + + #define F_path_architecture_bits_default_s_length _en_kevux_path_architecture_bits_default_length_ + F_path_separator_s_length + #endif // _en_kevux_path_architecture_bits_default_length_ == 0 + #else + #define F_path_architecture_bits_default_s "x64" F_path_separator_s + + #define F_path_architecture_bits_default_s_length 3 + F_path_separator_s_length + #endif // !defined(_en_kevux_path_architecture_bits_default_name_) || !defined(_en_kevux_path_architecture_bits_default_length_) + + #if defined(_en_kevux_path_architecture_bits_scripts_name_) && defined(_en_kevux_path_architecture_bits_scripts_length_) + #if _en_kevux_path_architecture_bits_scripts_length_ == 0 + #define F_path_architecture_bits_scripts_s F_string_empty_s + + #define F_path_architecture_bits_scripts_s_length F_string_empty_s_length + #else + #define F_path_architecture_bits_scripts_s _en_kevux_path_architecture_bits_scripts_name_ + + #define F_path_architecture_bits_scripts_s_length _en_kevux_path_architecture_bits_scripts_length_ + F_path_separator_s_length + #endif // _en_kevux_path_architecture_bits_scripts_length_ == 0 + #else + #define F_path_architecture_bits_scripts_s "scripts" F_path_separator_s + + #define F_path_architecture_bits_scripts_s_length 7 + F_path_separator_s_length + #endif // !defined(_en_kevux_path_architecture_bits_scripts_name_) || !defined(_en_kevux_path_architecture_bits_scripts_length_) + + extern const f_string_static_t f_path_architecture_bits_s; + extern const f_string_static_t f_path_architecture_bits_default_s; + extern const f_string_static_t f_path_architecture_bits_scripts_s; + #endif // _en_kevux_path_architecture_bits_ #endif // _di_f_path_defines_ /** diff --git a/level_0/f_path/data/build/defines b/level_0/f_path/data/build/defines index c665317..817f61a 100644 --- a/level_0/f_path/data/build/defines +++ b/level_0/f_path/data/build/defines @@ -1,2 +1,7 @@ # fss-0000 +_en_kevux_path_architecture_bits_ Enable Kevux architecture bits handling in PATH. +_en_kevux_path_architecture_bits_default_name_ If defined, then this is a string representing the architecture bits (without the path separator "/") such as "x64". +_en_kevux_path_architecture_bits_default_length_ If _en_kevux_path_architecture_bits_default_name_ is defined, then this must be defined as the string length of _en_kevux_path_architecture_bits_default_name_ (without the trailing NULL character), such as 3 for "x64". Set to 0 to disable _en_kevux_path_architecture_bits_default_name_ (preventing default). +_en_kevux_path_architecture_bits_scripts_name_ If defined, then this is a string representing the architecture bits (without the path separator "/") such as "script". +_en_kevux_path_architecture_bits_scripts_length_ If _en_kevux_path_architecture_bits_scripts_name_ is defined, then this must be defined as the string length of _en_kevux_path_architecture_bits_scripts_name_ (without the trailing NULL character), such as 7 for "scripts". Set to 0 to disable _en_kevux_path_architecture_bits_scripts_name_ (preventing default). diff --git a/level_1/fl_environment/c/environment.c b/level_1/fl_environment/c/environment.c index f2abc4a..e395a4d 100644 --- a/level_1/fl_environment/c/environment.c +++ b/level_1/fl_environment/c/environment.c @@ -104,11 +104,63 @@ extern "C" { f_array_length_t first = 0; f_array_length_t total = 0; + // Do a quick pre-process of PATH to approximate the amount of parts needed, reducing the number of allocations. for (; i <= path.used; ++i) { + if (path.string[i] == f_path_separator_variable_s.string[0]) ++total; + } // for - if (i == path.used || path.string[i] == f_path_separator_variable_s.string[0]) { - status = f_string_dynamics_increase(F_memory_default_allocation_small_d, paths); + #ifdef _en_kevux_path_architecture_bits_ + total *= 3; + #endif // _en_kevux_path_architecture_bits_ + + if (total) { + status = f_string_dynamics_increase_by(total, paths); + if (F_status_is_error(status)) return status; + + total = 0; + } + + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_t architecture_bits = f_string_dynamic_t_initialize; + + if (f_path_architecture_bits_s.used) { + status = f_environment_get(f_path_architecture_bits_s, &architecture_bits); if (F_status_is_error(status)) return status; + } + + if (architecture_bits.used) { + status = f_string_dynamic_append_assure(f_path_separator_s, &architecture_bits); + + if (F_status_is_error(status)) { + f_string_dynamic_resize(0, &architecture_bits); + + return status; + } + } else if (!architecture_bits.used && f_path_architecture_bits_default_s.used) { + architecture_bits.string = f_path_architecture_bits_default_s.string; + architecture_bits.used = f_path_architecture_bits_default_s.used; + architecture_bits.size = f_path_architecture_bits_default_s.size; + } + #endif // _en_kevux_path_architecture_bits_ + + for (i = 0; i <= path.used; ++i) { + + if (i == path.used || path.string[i] == f_path_separator_variable_s.string[0]) { + #ifdef _en_kevux_path_architecture_bits_ + if (paths->used + 3 > paths->size) { + status = f_string_dynamics_increase(F_memory_default_allocation_small_d + 2, paths); + } + #else + status = f_string_dynamics_increase(F_memory_default_allocation_small_d, paths); + #endif // _en_kevux_path_architecture_bits_ + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } if (!i) { paths->array[paths->used++].used = 0; @@ -136,8 +188,51 @@ extern "C" { buffer[k++] = f_path_separator_s.string[0]; } + #ifdef _en_kevux_path_architecture_bits_ + if (f_path_architecture_bits_s.used) { + status = f_string_dynamic_increase_by(k + f_path_architecture_bits_s.used, &paths->array[paths->used]); + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } + + memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); + memcpy(paths->array[paths->used].string + k, architecture_bits.string, sizeof(f_char_t) * architecture_bits.used); + + paths->array[paths->used++].used = k + architecture_bits.used; + } + + if (f_path_architecture_bits_scripts_s.used) { + status = f_string_dynamic_increase_by(k + f_path_architecture_bits_scripts_s.used, &paths->array[paths->used]); + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } + + memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); + memcpy(paths->array[paths->used].string + k, f_path_architecture_bits_scripts_s.string, sizeof(f_char_t) * f_path_architecture_bits_scripts_s.used); + + paths->array[paths->used++].used = k + f_path_architecture_bits_scripts_s.used; + } + #endif // _en_kevux_path_architecture_bits_ + status = f_string_dynamic_increase_by(k, &paths->array[paths->used]); - if (F_status_is_error(status)) return status; + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); @@ -151,6 +246,10 @@ extern "C" { } } // for + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + return F_none; } #endif // _di_fl_environment_path_explode_ @@ -182,11 +281,63 @@ extern "C" { f_array_length_t last = path.used; f_array_length_t total = 0; + // Do a quick pre-process of PATH to approximate the amount of parts needed, reducing the number of allocations. + for (; i <= path.used; ++i) { + if (path.string[i] == f_path_separator_variable_s.string[0]) ++total; + } // for + + #ifdef _en_kevux_path_architecture_bits_ + total *= 3; + #endif // _en_kevux_path_architecture_bits_ + + if (total) { + status = f_string_dynamics_increase_by(total, paths); + if (F_status_is_error(status)) return status; + + total = 0; + } + + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_t architecture_bits = f_string_dynamic_t_initialize; + + if (f_path_architecture_bits_s.used) { + status = f_environment_get(f_path_architecture_bits_s, &architecture_bits); + if (F_status_is_error(status)) return status; + } + + if (architecture_bits.used) { + status = f_string_dynamic_append_assure(f_path_separator_s, &architecture_bits); + + if (F_status_is_error(status)) { + f_string_dynamic_resize(0, &architecture_bits); + + return status; + } + } else if (!architecture_bits.used && f_path_architecture_bits_default_s.used) { + architecture_bits.string = f_path_architecture_bits_default_s.string; + architecture_bits.used = f_path_architecture_bits_default_s.used; + architecture_bits.size = f_path_architecture_bits_default_s.size; + } + #endif // _en_kevux_path_architecture_bits_ + for (; i <= path.used; ++i, --r) { if (i == path.used || path.string[r] == f_path_separator_variable_s.string[0]) { - status = f_string_dynamics_increase(F_memory_default_allocation_small_d, paths); - if (F_status_is_error(status)) return status; + #ifdef _en_kevux_path_architecture_bits_ + if (paths->used + 3 > paths->size) { + status = f_string_dynamics_increase(F_memory_default_allocation_small_d + 2, paths); + } + #else + status = f_string_dynamics_increase(F_memory_default_allocation_small_d, paths); + #endif // _en_kevux_path_architecture_bits_ + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } if (!i) { paths->array[paths->used++].used = 0; @@ -214,8 +365,51 @@ extern "C" { buffer[k++] = f_path_separator_s.string[0]; } + #ifdef _en_kevux_path_architecture_bits_ + if (f_path_architecture_bits_s.used) { + status = f_string_dynamic_increase_by(k + f_path_architecture_bits_s.used, &paths->array[paths->used]); + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } + + memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); + memcpy(paths->array[paths->used].string + k, architecture_bits.string, sizeof(f_char_t) * architecture_bits.used); + + paths->array[paths->used++].used = k + architecture_bits.used; + } + + if (f_path_architecture_bits_scripts_s.used) { + status = f_string_dynamic_increase_by(k + f_path_architecture_bits_scripts_s.used, &paths->array[paths->used]); + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } + + memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); + memcpy(paths->array[paths->used].string + k, f_path_architecture_bits_scripts_s.string, sizeof(f_char_t) * f_path_architecture_bits_scripts_s.used); + + paths->array[paths->used++].used = k + f_path_architecture_bits_scripts_s.used; + } + #endif // _en_kevux_path_architecture_bits_ + status = f_string_dynamic_increase_by(k, &paths->array[paths->used]); - if (F_status_is_error(status)) return status; + + if (F_status_is_error(status)) { + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + + return status; + } memcpy(paths->array[paths->used].string, buffer, sizeof(f_char_t) * k); @@ -229,6 +423,10 @@ extern "C" { } } // for + #ifdef _en_kevux_path_architecture_bits_ + f_string_dynamic_resize(0, &architecture_bits); + #endif // _en_kevux_path_architecture_bits_ + return F_none; } #endif // _di_fl_environment_path_explode_reverse_ diff --git a/level_1/fl_environment/c/environment.h b/level_1/fl_environment/c/environment.h index 532b18b..d0fa4fa 100644 --- a/level_1/fl_environment/c/environment.h +++ b/level_1/fl_environment/c/environment.h @@ -111,9 +111,11 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_environment_get() (only when _en_kevux_path_architecture_bits_ is defined). * Errors (with error bit) from: f_string_dynamics_increase(). * Errors (with error bit) from: f_string_dynamics_increase_by(). * + * @see f_environment_get() * @see f_string_dynamics_increase() * @see f_string_dynamics_increase_by() */ @@ -143,9 +145,11 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_environment_get() (only when _en_kevux_path_architecture_bits_ is defined). * Errors (with error bit) from: f_string_dynamics_increase(). * Errors (with error bit) from: f_string_dynamics_increase_by(). * + * @see f_environment_get() * @see f_string_dynamics_increase() * @see f_string_dynamics_increase_by() */ diff --git a/level_1/fl_environment/data/build/defines b/level_1/fl_environment/data/build/defines index c665317..16f2bfc 100644 --- a/level_1/fl_environment/data/build/defines +++ b/level_1/fl_environment/data/build/defines @@ -1,2 +1,3 @@ # fss-0000 +_en_kevux_path_architecture_bits_ Enable Kevux architecture bits handling in PATH. diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index c5cf3cf..36050ee 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -318,7 +318,7 @@ extern "C" { if (F_status_is_error(status)) { - // Do not consider PATH is not available (or not valid?) to be an error. + // Do not consider PATH to be not available (or not valid?) to be an error. if (F_status_set_fine(status) == F_valid_not || F_status_set_fine(status) == F_failure) { status = F_none; } diff --git a/level_2/fll_execute/data/build/defines b/level_2/fll_execute/data/build/defines index 649b88b..34b48fd 100644 --- a/level_2/fll_execute/data/build/defines +++ b/level_2/fll_execute/data/build/defines @@ -2,5 +2,6 @@ _di_libcap_ Disable libcap support, allow for compiling and linking without libcap (-lcap). _di_thread_support_ Disable support for compiling and depending on pthreads (and projects like f_thread). + _pthread_attr_unsupported_ Disable non-portable functionality associated with pthread_attr. _pthread_sigqueue_unsupported_ Disable GNU specific sigqueue(). -- 1.8.3.1