From cc1aaf1b4ccf5b87449a085eaebd0d7eb0426c91 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 18 Aug 2020 22:09:20 -0500 Subject: [PATCH] Progress: featureless make. Implement the compiler and linker section operations. Rename and move the fake_build_execute() to fake_execute() to be shared among both the build and the make operations. --- level_3/fake/c/private-build.c | 54 ++--------- level_3/fake/c/private-build.h | 20 ----- level_3/fake/c/private-fake.c | 44 +++++++++ level_3/fake/c/private-fake.h | 20 +++++ level_3/fake/c/private-make.c | 149 +++++++++++++++++++++++++------ level_3/fake/c/private-make.h | 4 + level_3/fake/data/build/fakefile | 3 + level_3/fake/documents/fakefile.txt | 25 +++--- level_3/fake/specifications/fakefile.txt | 8 +- 9 files changed, 217 insertions(+), 110 deletions(-) diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index e5c90a8..d8e3cca 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -295,50 +295,6 @@ extern "C" { } #endif // _di_fake_build_copy_ -#ifndef _di_fake_build_execute_ - void fake_build_execute(const fake_data data, const fake_build_data data_build, const f_string_static program, const f_string_statics arguments, f_status *status) { - if (F_status_is_error(*status)) return; - - if (data.verbosity == fake_verbosity_verbose) { - printf("%s", program.string); - - for (f_array_length i = 0; i < arguments.used; i++) { - if (arguments.array[i].used == 0) continue; - - printf(" %s", arguments.array[i].string); - } // for - - printf("%c", f_string_eol[0]); - - // flush to stdout before executing command. - fflush(f_type_output); - } - - { - int result = 0; - - *status = fll_execute_program_environment(program.string, arguments, data_build.environment.names, data_build.environment.values, &result); - - if (result != 0) { - *status = F_status_set_error(F_failure); - } - else if (F_status_is_error(*status)) { - if (F_status_set_fine(*status) == F_file_found_not) { - if (data.verbosity != fake_verbosity_quiet) { - fprintf(f_type_error, "%c", f_string_eol[0]); - fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find program '"); - fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", program.string); - fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' for executing."); - } - } - else { - fake_print_error(data, F_status_set_fine(*status), "fll_execute_program_environment", F_true); - } - } - } - } -#endif // _di_fake_build_execute_ - #ifndef _di_fake_build_skeleton_ void fake_build_skeleton(const fake_data data, const fake_build_data data_build, const mode_t mode, const f_string_static file_stage, f_status *status) { if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; @@ -844,7 +800,7 @@ extern "C" { } } - fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_delete_simple(arguments); @@ -1067,7 +1023,7 @@ extern "C" { } } - fake_build_execute(data, data_build, data_build.setting.build_linker, arguments, status); + fake_execute(data, data_build.environment, data_build.setting.build_linker, arguments, status); f_macro_string_dynamic_delete_simple(file_name); f_macro_string_dynamic_delete_simple(source_path); @@ -2263,7 +2219,7 @@ extern "C" { break; } - fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); if (F_status_is_error(*status)) break; f_macro_string_dynamics_delete_simple(arguments); @@ -2471,7 +2427,7 @@ extern "C" { return; } - fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_delete_simple(arguments); @@ -2576,7 +2532,7 @@ extern "C" { return; } - fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_delete_simple(arguments); diff --git a/level_3/fake/c/private-build.h b/level_3/fake/c/private-build.h index 50a14a2..6f0a8ae 100644 --- a/level_3/fake/c/private-build.h +++ b/level_3/fake/c/private-build.h @@ -430,26 +430,6 @@ extern "C" { #endif // _di_fake_build_copy_ /** - * Execute the given command and arguments. - * - * Will print the command if in verbose mode. - * - * @param data - * The program data. - * @param data_build - * The build data. - * @param program - * The program to be executed. - * @param arguments - * The arguments to be passed to the program. - * @param status - * The return status. - */ -#ifndef _di_fake_build_execute_ - extern void fake_build_execute(const fake_data data, const fake_build_data data_build, const f_string_static program, const f_string_statics arguments, f_status *status) f_gcc_attribute_visibility_internal; -#endif // _di_fake_build_execute_ - -/** * Create all of the base directories inside the build directory. * * @param data diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index 1e7f47a..9b86ed8 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -6,6 +6,50 @@ extern "C" { #endif +#ifndef _di_fake_execute_ + void fake_execute(const fake_data data, const fake_environment environment, const f_string_static program, const f_string_statics arguments, f_status *status) { + if (F_status_is_error(*status)) return; + + if (data.verbosity == fake_verbosity_verbose) { + printf("%s", program.string); + + for (f_array_length i = 0; i < arguments.used; i++) { + if (arguments.array[i].used == 0) continue; + + printf(" %s", arguments.array[i].string); + } // for + + printf("%c", f_string_eol[0]); + + // flush to stdout before executing command. + fflush(f_type_output); + } + + { + int result = 0; + + *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &result); + + if (result != 0) { + *status = F_status_set_error(F_failure); + } + else if (F_status_is_error(*status)) { + if (F_status_set_fine(*status) == F_file_found_not) { + if (data.verbosity != fake_verbosity_quiet) { + fprintf(f_type_error, "%c", f_string_eol[0]); + fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find program '"); + fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", program.string); + fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' for executing."); + } + } + else { + fake_print_error(data, F_status_set_fine(*status), "fll_execute_program_environment", F_true); + } + } + } + } +#endif // _di_fake_execute_ + #ifndef _di_fake_file_buffer_ f_return_status fake_file_buffer(const fake_data data, const f_string path_file, f_string_dynamic *buffer) { f_file file = f_file_initialize; diff --git a/level_3/fake/c/private-fake.h b/level_3/fake/c/private-fake.h index 820ba39..0dcae98 100644 --- a/level_3/fake/c/private-fake.h +++ b/level_3/fake/c/private-fake.h @@ -39,6 +39,26 @@ extern "C" { #endif // _di_fake_environment_ /** + * Execute the given command and arguments. + * + * Will print the command if in verbose mode. + * + * @param data + * The program data. + * @param environment + * The environment variable data. + * @param program + * The program to be executed. + * @param arguments + * The arguments to be passed to the program. + * @param status + * The return status. + */ +#ifndef _di_fake_execute_ + extern void fake_execute(const fake_data data, const fake_environment environment, const f_string_static program, const f_string_statics arguments, f_status *status) f_gcc_attribute_visibility_internal; +#endif // _di_fake_execute_ + +/** * Load the contents of a file into the given buffer, handling all potential errors. * * @param data diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 24111bf..a1f78d1 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -334,41 +334,34 @@ extern "C" { } } + f_string_range *range_compiler = 0; + f_string_range *range_linker = 0; + data_make->setting_make.parameter.array[0].value.used = 1; data_make->setting_make.load_build = F_true; data_make->setting_make.fail = fake_make_operation_fail_type_exit; if (settings.objects.used) { - bool unmatched_load = F_true; bool unmatched_fail = F_true; + bool unmatched_load = F_true; for (f_array_length i = 0; i < settings.objects.used; i++) { - if (fl_string_dynamic_partial_compare_string(fake_make_setting_load_build, data_make->buffer, fake_make_setting_load_build_length, settings.objects.array[i]) == F_equal_to) { - if (unmatched_load) { + if (fl_string_dynamic_partial_compare_string(fake_make_setting_compiler, data_make->buffer, fake_make_setting_compiler_length, settings.objects.array[i]) == F_equal_to) { + if (range_compiler) { + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_compiler); + } + else { if (settings.contents.array[i].used) { - if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_yes, data_make->buffer, fake_common_setting_bool_yes_length, settings.contents.array[i].array[0]) == F_equal_to) { - data_make->setting_make.load_build = F_true; - } - else if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_no, data_make->buffer, fake_common_setting_bool_no_length, settings.contents.array[i].array[0]) == F_equal_to) { - data_make->setting_make.load_build = F_false; - } - else { - fake_print_error_fakefile_settings_content_invalid(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings); - } - - unmatched_load = F_false; + range_compiler = &settings.contents.array[i].array[0]; if (settings.contents.array[i].used > 1) { - fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build); + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_compiler); } } else { fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings); } } - else { - fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build); - } } else if (fl_string_dynamic_partial_compare_string(fake_make_setting_fail, data_make->buffer, fake_make_setting_fail_length, settings.objects.array[i]) == F_equal_to) { if (unmatched_fail) { @@ -400,6 +393,50 @@ extern "C" { fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_fail); } } + else if (fl_string_dynamic_partial_compare_string(fake_make_setting_linker, data_make->buffer, fake_make_setting_linker_length, settings.objects.array[i]) == F_equal_to) { + if (range_linker) { + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_linker); + } + else { + if (settings.contents.array[i].used) { + range_linker = &settings.contents.array[i].array[0]; + + if (settings.contents.array[i].used > 1) { + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_linker); + } + } + else { + fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings); + } + } + } + else if (fl_string_dynamic_partial_compare_string(fake_make_setting_load_build, data_make->buffer, fake_make_setting_load_build_length, settings.objects.array[i]) == F_equal_to) { + if (unmatched_load) { + if (settings.contents.array[i].used) { + if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_yes, data_make->buffer, fake_common_setting_bool_yes_length, settings.contents.array[i].array[0]) == F_equal_to) { + data_make->setting_make.load_build = F_true; + } + else if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_no, data_make->buffer, fake_common_setting_bool_no_length, settings.contents.array[i].array[0]) == F_equal_to) { + data_make->setting_make.load_build = F_false; + } + else { + fake_print_error_fakefile_settings_content_invalid(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings); + } + + unmatched_load = F_false; + + if (settings.contents.array[i].used > 1) { + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build); + } + } + else { + fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings); + } + } + else { + fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build); + } + } else if (fl_string_dynamic_partial_compare_string(fake_make_setting_parameter, data_make->buffer, fake_make_setting_parameter_length, settings.objects.array[i]) == F_equal_to) { if (settings.contents.array[i].used) { if (fl_string_dynamic_partial_compare_string(fake_make_setting_return, data_make->buffer, fake_make_setting_return_length, settings.contents.array[i].array[0]) == F_equal_to) { @@ -442,6 +479,31 @@ extern "C" { if (data_make->setting_make.load_build) { fake_build_load_setting(data, &data_make->setting_build, status); + + if (F_status_is_error(*status)) { + fake_print_error(data, *status, "fake_build_load_setting", F_true); + + f_macro_fss_set_delete_simple(settings); + return; + } + } + + // if either compiler or linker is specified, each will replace any existing build_compiler or build_linker, respectively. + if (range_compiler) { + data_make->setting_build.build_compiler.used = 0; + *status = fl_string_dynamic_partial_append(data_make->buffer, *range_compiler, &data_make->setting_build.build_compiler); + } + + if (F_status_is_fine(*status) && range_linker) { + data_make->setting_build.build_linker.used = 0; + *status = fl_string_dynamic_partial_append(data_make->buffer, *range_linker, &data_make->setting_build.build_linker); + } + + if (F_status_is_error(*status)) { + fake_print_error(data, *status, "fl_string_dynamic_partial_append", F_true); + + f_macro_fss_set_delete_simple(settings); + return; } f_string_map_multis define = f_string_map_multis_initialize; @@ -1414,9 +1476,24 @@ extern "C" { if (F_status_is_error(*status)) return; if (operation == fake_make_operation_type_archive) { - // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments); - //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status); - //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + if (data_make->setting_build.build_linker.used) { + fake_execute(data, data_make->environment, data_make->setting_build.build_linker, arguments, status); + + if (F_status_is_error(*status)) { + fake_print_error(data, F_status_set_fine(*status), "fake_execute", F_true); + return; + } + } + else { + if (data.verbosity != fake_verbosity_quiet) { + fprintf(f_type_error, "%c", f_string_eol[0]); + fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: No linker has been specified, cannot perform '"); + fl_color_print(f_type_error, data.context.notable, data.context.reset, fake_make_operation_archive); + fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' section operation."); + } + + *status = F_status_set_error(F_failure); + } return; } @@ -1436,9 +1513,25 @@ extern "C" { } if (operation == fake_make_operation_type_compile) { - // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments); - //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status); - //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + if (data_make->setting_build.build_compiler.used) { + fake_execute(data, data_make->environment, data_make->setting_build.build_compiler, arguments, status); + + if (F_status_is_error(*status)) { + fake_print_error(data, F_status_set_fine(*status), "fake_execute", F_true); + return; + } + } + else { + if (data.verbosity != fake_verbosity_quiet) { + fprintf(f_type_error, "%c", f_string_eol[0]); + fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: No compiler has been specified, cannot perform '"); + fl_color_print(f_type_error, data.context.notable, data.context.reset, fake_make_operation_compile); + fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' section operation."); + } + + *status = F_status_set_error(F_failure); + } + return; } @@ -1446,7 +1539,7 @@ extern "C" { // fake_make_assure_inside_project // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments); //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status); - //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status); return; } @@ -1459,7 +1552,7 @@ extern "C" { // fake_make_assure_inside_project // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments); //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status); - //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status); return; } @@ -1512,9 +1605,7 @@ extern "C" { if (operation == fake_make_operation_type_link) { // fake_make_assure_inside_project - // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments); - //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status); - //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status); + // @todo: create symlink. return; } diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index 683de3a..495f734 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -41,14 +41,18 @@ extern "C" { #define fake_macro_make_setting_delete_simple(setting) \ f_macro_string_map_multis_delete_simple(setting.parameter) + #define fake_make_setting_compiler "compiler" #define fake_make_setting_define "define" #define fake_make_setting_fail "fail" + #define fake_make_setting_linker "linker" #define fake_make_setting_load_build "load_build" #define fake_make_setting_parameter "parameter" #define fake_make_setting_return "return" + #define fake_make_setting_compiler_length 8 #define fake_make_setting_define_length 6 #define fake_make_setting_fail_length 4 + #define fake_make_setting_linker_length 6 #define fake_make_setting_load_build_length 10 #define fake_make_setting_parameter_length 9 #define fake_make_setting_return_length 6 diff --git a/level_3/fake/data/build/fakefile b/level_3/fake/data/build/fakefile index 2ae1288..2263346 100644 --- a/level_3/fake/data/build/fakefile +++ b/level_3/fake/data/build/fakefile @@ -4,6 +4,9 @@ settings: load_build yes fail exit + compiler gcc + linker ar + parameter verbose +v parameter verbose_fll +V diff --git a/level_3/fake/documents/fakefile.txt b/level_3/fake/documents/fakefile.txt index 78cf8dc..3ba3dd5 100644 --- a/level_3/fake/documents/fakefile.txt +++ b/level_3/fake/documents/fakefile.txt @@ -14,6 +14,9 @@ Fakefile Documentation: The build settings may also be specified in the Settings Section. The following settings are available (in addition to the build settings)\: + - compiler\: + This represents the name of the compiler program to use, such as "gcc". + - define\: This represents an environment variable to define on run. The environment variable name is case-sensitive. @@ -29,6 +32,9 @@ Fakefile Documentation: The return code for programs can still be retrieved through using the reserved iki vaiable "return". + - linker\: + This represents the name of the linker program to use, such as "ar". + - load_build\: This represents whether or not to load the load the build settings file. The first Content value may be "true" to load the build settings and "false" to not load the build settings file. @@ -74,13 +80,12 @@ Fakefile Documentation: The first Content must be either "file" or "directory". Use "file" to designate that this is a regular file being created. - The "directory" to designate that this is a directory file being created. + Use "directory" to designate that this is a directory file being created. - The second Content must be the file to be created. + The second Content must be the file to be created (be it a regular "file" or a "directory" file). - An optional third Content may be specified for "directory". - This third Content, if specified, may only be "recursive". - When specified, this will create all directories specified in the given directory file path. + - creates\: + Identical to "create", except that this will create all directories specified in the given directory file path. - define\: This represents an environment variable to define on run. @@ -94,12 +99,12 @@ Fakefile Documentation: Use "file" to designate that this is a regular file being deleted. The "directory" to designate that this is a directory file being deleted. - The second Content must be the file to be created. + The second Content must be the file to be deleted. + + When the first content is "directory" and that directory is not empty, then this will not delete the directory. - An optional third Content may be specified for "directory". - This third Content, if specified, may only be "recursive". - When specified, this will create all directories specified in the given directory file path. - If the directory is not empty, then "recursive" must be specified to delete the directory. + - deletes\: + Identical to "delete", except that when the first content is "directory" and that directory is not empty, then this will delete the directory. - else\: Performs a programmatic "else" condition. diff --git a/level_3/fake/specifications/fakefile.txt b/level_3/fake/specifications/fakefile.txt index ad01f9a..328306f 100644 --- a/level_3/fake/specifications/fakefile.txt +++ b/level_3/fake/specifications/fakefile.txt @@ -33,6 +33,8 @@ Fakefile Specification: - main: contains a list of Operation Objects and Content in FSS-0001 (Extended) format. The Settings Objects are\: + - archiver: Only one Content, which must only be a valid filename. + - compiler: Only one Content, which must only be a valid filename. - define: First Content represents variable name (case-sensitive), remaining Content represents varaiable value for IKI substitution. - fail: Only one Content, which must be either "exit", "warn" or "ignore" (quotes not required) (case-sensitive). - load_build: Only one Content, which must be either "yes" or "no" (quotes not required) (case-sensitive). @@ -45,9 +47,11 @@ Fakefile Specification: - build: Zero or One Content. First Content represents path to the settings file, relative to the project root. - clean: Zero Content. - compile: One or more Content as parameters to compiler. - - create: Two or three Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file, and third Content is "recursive" (case-sensitive) or is not provided. + - create: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file. + - creates: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file. - define: Two or more Content. - - delete: Two or three Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file, and third Content is "recursive" (case-sensitive) or is not provided. + - delete: One or more Content representing paths to files. + - deletes: One or more Content representing paths to files. - else: Zero Content. - fail: One Content. First Content must be one of "exit", "warn", or "ignore" (case-sensitive). - group: Two or more Content. First Content is group name or number, remaining Content are paths to files. -- 1.8.3.1