From c51866da43b5c02745600c0ee460ef70897a11d3 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 24 May 2022 21:11:44 -0500 Subject: [PATCH] Update: The fake "build" fakefile Object needs to support modes and fix a related bug. The fakefile needs to be able to support being passed custom modes. The default behavior is preserved with this change. This requires supporting that an empty string is passed as Content. It turns out that the quoted empty string is incorrectly being skipped. Make sure the quoted empty strings are not skipped. --- level_3/fake/c/fake.c | 2 +- level_3/fake/c/private-build-load.c | 27 ++++++++++++++++++++------ level_3/fake/c/private-build-load.h | 18 ++++++++++++----- level_3/fake/c/private-build.c | 6 +++--- level_3/fake/c/private-build.h | 10 +++++++++- level_3/fake/c/private-make-load_fakefile.c | 4 ++-- level_3/fake/c/private-make-operate.c | 10 +++++++++- level_3/fake/c/private-make-operate_process.c | 2 +- level_3/fake/c/private-make-operate_validate.c | 7 +------ level_3/fake/documents/fakefile.txt | 6 ++++++ level_3/fake/specifications/fakefile.txt | 4 ++-- 11 files changed, 68 insertions(+), 28 deletions(-) diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c index bc37e60..da714a3 100644 --- a/level_3/fake/c/fake.c +++ b/level_3/fake/c/fake.c @@ -302,7 +302,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fake_build_operate(&data, f_string_empty_s); + status = fake_build_operate(&data, 0); } } else if (data.operation == fake_operation_clean_e) { diff --git a/level_3/fake/c/private-build-load.c b/level_3/fake/c/private-build-load.c index d94eda0..ccfa4f2 100644 --- a/level_3/fake/c/private-build-load.c +++ b/level_3/fake/c/private-build-load.c @@ -71,7 +71,7 @@ extern "C" { #endif // _di_fake_build_load_environment_ #ifndef _di_fake_build_load_setting_ - void fake_build_load_setting(fake_data_t * const data, const f_string_static_t setting_file, fake_build_setting_t * const setting, f_status_t * const status) { + void fake_build_load_setting(fake_data_t * const data, const f_string_statics_t * const build_arguments, fake_build_setting_t * const setting, f_status_t * const status) { if (F_status_is_error(*status)) return; @@ -83,6 +83,17 @@ extern "C" { return; } + const f_string_static_t setting_file = build_arguments && build_arguments->used ? build_arguments->array[0] : f_string_empty_s; + f_string_statics_t modes_custom = f_string_statics_t_initialize; + const f_string_statics_t *modes_custom_ptr = 0; + + if (build_arguments && build_arguments->used > 1) { + modes_custom.array = build_arguments->array + 1; + modes_custom.used = build_arguments->used - 1; + + modes_custom_ptr = &modes_custom; + } + f_string_static_t path_file = f_string_static_t_initialize; path_file.used = data->path_data_build.used + setting_file.used; @@ -123,7 +134,7 @@ extern "C" { fll_error_print(data->main->error, F_status_set_fine(*status), "f_fss_apply_delimit", F_true); } else { - fake_build_load_setting_process(data, F_true, setting_file.used ? path_file : data->file_data_build_settings, buffer, objects, contents, setting, status); + fake_build_load_setting_process(data, F_true, setting_file.used ? path_file : data->file_data_build_settings, modes_custom_ptr, buffer, objects, contents, setting, status); } } @@ -177,7 +188,7 @@ extern "C" { #endif // _di_fake_build_load_setting_ #ifndef _di_fake_build_load_setting_process_ - void fake_build_load_setting_process(fake_data_t * const data, const bool checks, const f_string_static_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t * const setting, f_status_t * const status) { + void fake_build_load_setting_process(fake_data_t * const data, const bool checks, const f_string_static_t path_file, const f_string_statics_t * const modes_custom, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t * const setting, f_status_t * const status) { if (F_status_is_error(*status) && buffer.used) return; @@ -522,14 +533,18 @@ extern "C" { f_array_length_t i = 0; f_array_length_t j = 0; - // If any mode is specified, the entire defaults is replaced. - if (data->mode.used) { + // Custom modes are always used if provided, otherwise if any mode is specified, the entire defaults is replaced. + if (modes_custom) { + modes = modes_custom; + } + else if (data->mode.used) { modes = &data->mode; } for (; i < modes->used; ++i) { - found = F_false; + // Skip empty modes. + if (!modes->array[i].used) continue; for (j = 0; j < setting->modes.used; ++j) { diff --git a/level_3/fake/c/private-build-load.h b/level_3/fake/c/private-build-load.h index 7dcd5ce..2d2ec5e 100644 --- a/level_3/fake/c/private-build-load.h +++ b/level_3/fake/c/private-build-load.h @@ -17,9 +17,14 @@ extern "C" { * * @param data * The program data. - * @param setting_file - * The name of the settings file to use. - * If setting_file.used is 0, then the default or program parameter supplied file is used. + * @param build_arguments + * (optional) A set of custom arguments to pass to the build. + * The first argument represents the name of the settings file to use. + * The second and on arguments represent custom modes to use. + * If build_arguments is NULL, then the default (or program supplied) settings file and modes are used. + * If build_arguments.used is 0, then the default or program parameter supplied file is used. + * Set the first argument used length to 0 to use the default program parameter supplied file. + * Set the second argument used length to 0 without any further arguments to not use any modes. * @param setting * All build related setting data from the build setting file are loaded into this. * These setting will have any specified mode property applied. @@ -32,7 +37,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_load_setting_ - extern void fake_build_load_setting(fake_data_t * const data, const f_string_static_t setting_file, fake_build_setting_t * const setting, f_status_t * const status) F_attribute_visibility_internal_d; + extern void fake_build_load_setting(fake_data_t * const data, const f_string_statics_t * const build_arguments, fake_build_setting_t * const setting, f_status_t * const status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_setting_ /** @@ -69,6 +74,9 @@ extern "C" { * If FALSE, do not perform certain "required" sanity checks (intended for a fakefile rather than a build settings file). * @param path_file * The path to the buffer. + * @param modes_custom + * (optional) When not NULL, specifies custom modes to use rather than what is provided. + * This also overrides command line parameters that specify the mode. * @param buffer * The loaded file data. * @param objects @@ -95,7 +103,7 @@ extern "C" { * @see fll_fss_snatch_apart() */ #ifndef _di_fake_build_load_setting_process_ - extern void fake_build_load_setting_process(fake_data_t * const data, const bool checks, const f_string_static_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t * const setting, f_status_t * const status) F_attribute_visibility_internal_d; + extern void fake_build_load_setting_process(fake_data_t * const data, const bool checks, const f_string_static_t path_file, const f_string_statics_t * const modes_custom, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t * const setting, f_status_t * const status) F_attribute_visibility_internal_d; #endif // _di_fake_build_load_setting_process_ /** diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index a4887f2..fd0c88c 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -813,7 +813,7 @@ extern "C" { #endif // _di_fake_build_objects_add_ #ifndef _di_fake_build_operate_ - f_status_t fake_build_operate(fake_data_t * const data, const f_string_static_t setting_file) { + f_status_t fake_build_operate(fake_data_t * const data, const f_string_statics_t * const build_arguments) { if (fll_program_standard_signal_received(data->main)) { fake_print_signal_received(data); @@ -829,7 +829,7 @@ extern "C" { macro_f_mode_t_set_default_umask(mode, data->main->umask); - fake_build_load_setting(data, setting_file, &data_build.setting, &status); + fake_build_load_setting(data, build_arguments, &data_build.setting, &status); if (F_status_is_fine(status)) { if (data->main->output.verbosity != f_console_verbosity_quiet_e) { @@ -845,7 +845,7 @@ extern "C" { } } - fake_build_load_stage(data, setting_file, &stage, &status); + fake_build_load_stage(data, build_arguments && build_arguments->array[0].used ? build_arguments->array[0] : f_string_empty_s, &stage, &status); fake_build_load_environment(data, &data_build, &data_build.environment, &status); diff --git a/level_3/fake/c/private-build.h b/level_3/fake/c/private-build.h index ce5459a..5e99fab 100644 --- a/level_3/fake/c/private-build.h +++ b/level_3/fake/c/private-build.h @@ -186,6 +186,14 @@ extern "C" { * @param setting_file * The name of the settings file to use. * If setting_file.used is 0, then the default or program parameter supplied file is used. + * @param build_arguments + * (optional) A set of custom arguments to pass to the build. + * The first argument represents the name of the settings file to use. + * The second and on arguments represent custom modes to use. + * If build_arguments is NULL, then the default (or program supplied) settings file and modes are used. + * If build_arguments.used is 0, then the default or program parameter supplied file is used. + * Set the first argument used length to 0 to use the default program parameter supplied file. + * Set the second argument used length to 0 without any further arguments to not use any modes. * * @return * F_none on success. @@ -193,7 +201,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_operate_ - extern f_status_t fake_build_operate(fake_data_t * const data, const f_string_static_t setting_file) F_attribute_visibility_internal_d; + extern f_status_t fake_build_operate(fake_data_t * const data, const f_string_statics_t * const build_arguments) F_attribute_visibility_internal_d; #endif // _di_fake_build_operate_ /** diff --git a/level_3/fake/c/private-make-load_fakefile.c b/level_3/fake/c/private-make-load_fakefile.c index 4bb5ba3..c62bd82 100644 --- a/level_3/fake/c/private-make-load_fakefile.c +++ b/level_3/fake/c/private-make-load_fakefile.c @@ -284,7 +284,7 @@ extern "C" { } if (F_status_is_error_not(*status) && data_make->setting_make.load_build) { - fake_build_load_setting(data_make->data, f_string_empty_s, &data_make->setting_build, status); + fake_build_load_setting(data_make->data, 0, &data_make->setting_build, status); if (F_status_is_error(*status) && *status != F_status_set_error(F_interrupt)) { fll_error_print(data_make->main->error, F_status_set_fine(*status), "fake_build_load_setting", F_true); @@ -374,7 +374,7 @@ extern "C" { f_string_map_multis_t define = f_string_map_multis_t_initialize; // Load the fakefile "settings" as if they are build "settings". - fake_build_load_setting_process(data, F_false, data->file_data_build_fakefile, data_make->buffer, settings->objects, settings->contents, &data_make->setting_build, &status); + fake_build_load_setting_process(data, F_false, data->file_data_build_fakefile, 0, data_make->buffer, settings->objects, settings->contents, &data_make->setting_build, &status); if (F_status_is_error_not(status) && settings->objects.used) { const f_string_static_t settings_name[] = { diff --git a/level_3/fake/c/private-make-operate.c b/level_3/fake/c/private-make-operate.c index 674f72d..40b0f39 100644 --- a/level_3/fake/c/private-make-operate.c +++ b/level_3/fake/c/private-make-operate.c @@ -258,7 +258,15 @@ extern "C" { for (; i < content.used; ++i) { - if (content.array[i].start > content.array[i].stop) continue; + // Skip content that is unused, but quoted content, even if empty, should remain. + if (content.array[i].start > content.array[i].stop) { + + if (quotes.array[i]) { + ++arguments->used; + } + + continue; + } range = content.array[i]; diff --git a/level_3/fake/c/private-make-operate_process.c b/level_3/fake/c/private-make-operate_process.c index a1f71f2..6157397 100644 --- a/level_3/fake/c/private-make-operate_process.c +++ b/level_3/fake/c/private-make-operate_process.c @@ -99,7 +99,7 @@ extern "C" { } if (state_process->operation == fake_make_operation_type_build_e) { - *status = fake_build_operate(data_make->data, arguments.used ? arguments.array[0] : f_string_empty_s); + *status = fake_build_operate(data_make->data, arguments.used ? &arguments : 0); if (F_status_set_fine(*status) == F_interrupt) { return 0; diff --git a/level_3/fake/c/private-make-operate_validate.c b/level_3/fake/c/private-make-operate_validate.c index f59f12e..5d615f5 100644 --- a/level_3/fake/c/private-make-operate_validate.c +++ b/level_3/fake/c/private-make-operate_validate.c @@ -72,12 +72,7 @@ extern "C" { } if (state_process->operation == fake_make_operation_type_build_e) { - if (arguments.used > 1) { - fake_print_error_too_many_arguments(data_make); - - *status = F_status_set_error(F_failure); - } - else if (arguments.used) { + if (arguments.used) { if (arguments.array[0].used) { f_string_static_t path_file = f_string_static_t_initialize; path_file.used = data_make->data->path_data_build.used + arguments.array[0].used; diff --git a/level_3/fake/documents/fakefile.txt b/level_3/fake/documents/fakefile.txt index 064b91a..d1577fb 100644 --- a/level_3/fake/documents/fakefile.txt +++ b/level_3/fake/documents/fakefile.txt @@ -93,6 +93,12 @@ Fakefile Documentation: Accepts an optional Content that is a file name to a build settings file to use instead of the default. This file name is relative to the data build directory (which can be changed by -D/--data parameter). + If the optional file name Content is specified, then it also supports additional modes to use instead of the default mode. + + When no additional Content after the "build" is specified, then the default (or program supplied) settings file and modes are used. + When the first Content after the "build" is specified as an empty string, then the default (or program supplied) settings file is used. + When the second Content after the "build" (and there is no third Content), then no modes are used. + - break\: Perform an exit from the current make operation. This only exists the current depth. diff --git a/level_3/fake/specifications/fakefile.txt b/level_3/fake/specifications/fakefile.txt index a9d24fb..edd7347 100644 --- a/level_3/fake/specifications/fakefile.txt +++ b/level_3/fake/specifications/fakefile.txt @@ -43,8 +43,8 @@ Fakefile Specification: The Section Operation Objects are\: - and: One or more Content. First Content is the condition or "no_dereference" (when "no_dereference", then the Second Content is the condition, etc..), remaining Content are specific to the condition. - - break: Zero or One Content. If specified, First content must be one of "success" or "failure". - - build: Zero or One Content. First Content represents file name of the settings file to use. + - break: Zero or one Content. If specified, First content must be one of "success" or "failure". + - build: Zero or more Content. First Content represents file name of the settings file to use, Second Content and on represent custom modes to use. - clean: Zero Content. - clone: Two or more Content representing paths to files. - compile: One or more Content as parameters to compiler. -- 1.8.3.1