From 0af7e4b5fd83758aa9c6d9cb69a5cb264ce59af9 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 5 May 2020 23:14:13 -0500 Subject: [PATCH] Progress: begin re-implementing fake program (Featureless Make) The goal here will be to mimic the current FSS build scripts fist. Then update the FSS build scripts to the more generalized design. Then implement the traditional fakefile process (a makefile alternative). Currently has "skeleton" mode, which may or may not be implemented. This was added as a stub just in case I decide to implement it. --- level_3/fake/c/fake.c | 309 ++++++++++++++ level_3/fake/c/fake.h | 701 +++++++++++++++++++++++++++++++ level_3/fake/c/main.c | 14 + level_3/fake/c/private-build.c | 65 +++ level_3/fake/c/private-build.h | 36 ++ level_3/fake/c/private-clean.c | 12 + level_3/fake/c/private-clean.h | 19 + level_3/fake/c/private-fake.c | 713 ++++++++++++++++++++++++++++++++ level_3/fake/c/private-fake.h | 120 ++++++ level_3/fake/c/private-make.c | 12 + level_3/fake/c/private-make.h | 19 + level_3/fake/c/private-skeleton.c | 12 + level_3/fake/c/private-skeleton.h | 19 + level_3/fake/data/build/dependencies | 20 + level_3/fake/data/build/process_post.sh | 113 +++++ level_3/fake/data/build/process_pre.sh | 113 +++++ level_3/fake/data/build/settings | 35 ++ 17 files changed, 2332 insertions(+) create mode 100644 level_3/fake/c/fake.c create mode 100644 level_3/fake/c/fake.h create mode 100644 level_3/fake/c/main.c create mode 100644 level_3/fake/c/private-build.c create mode 100644 level_3/fake/c/private-build.h create mode 100644 level_3/fake/c/private-clean.c create mode 100644 level_3/fake/c/private-clean.h create mode 100644 level_3/fake/c/private-fake.c create mode 100644 level_3/fake/c/private-fake.h create mode 100644 level_3/fake/c/private-make.c create mode 100644 level_3/fake/c/private-make.h create mode 100644 level_3/fake/c/private-skeleton.c create mode 100644 level_3/fake/c/private-skeleton.h create mode 100644 level_3/fake/data/build/dependencies create mode 100644 level_3/fake/data/build/process_post.sh create mode 100644 level_3/fake/data/build/process_pre.sh create mode 100644 level_3/fake/data/build/settings diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c new file mode 100644 index 0000000..8ae5443 --- /dev/null +++ b/level_3/fake/c/fake.c @@ -0,0 +1,309 @@ +#include +#include "private-fake.h" +#include "private-build.h" +#include "private-clean.h" +#include "private-make.h" +#include "private-skeleton.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fake_print_help_ + f_return_status fake_print_help(const fl_color_context context) { + fll_program_print_help_header(context, fake_name_long, fake_version); + + fll_program_print_help_option(context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print this help message."); + fll_program_print_help_option(context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on light backgrounds."); + fll_program_print_help_option(context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on dark backgrounds."); + fll_program_print_help_option(context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color."); + fll_program_print_help_option(context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number."); + + printf("%c", f_string_eol); + + fll_program_print_help_option(context, fake_short_path_build, fake_long_path_build, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom build directory."); + fll_program_print_help_option(context, fake_short_defines, fake_long_defines, f_console_symbol_short_enable, f_console_symbol_long_enable, " Override custom defines with these defines."); + fll_program_print_help_option(context, fake_short_mode, fake_long_mode, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use this mode when processing the build settings."); + fll_program_print_help_option(context, fake_short_process, fake_long_process, f_console_symbol_short_enable, f_console_symbol_long_enable, " Process name for storing build states."); + fll_program_print_help_option(context, fake_short_settings, fake_long_settings, f_console_symbol_short_enable, f_console_symbol_long_enable, "Use this settings file, from within the source settings directory."); + fll_program_print_help_option(context, fake_short_path_work, fake_long_path_work, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use includes/libraries from this directory instead of system."); + + printf("%c", f_string_eol); + + fll_program_print_help_option(context, fake_short_path_source_build, fake_long_path_source_build, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the build source files."); + fll_program_print_help_option(context, fake_short_path_source_codes, fake_long_path_source_codes, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the compiled source files, such as c."); + fll_program_print_help_option(context, fake_short_path_source_common, fake_long_path_source_common, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the common source files."); + fll_program_print_help_option(context, fake_short_path_source_data, fake_long_path_source_data, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the data source files."); + fll_program_print_help_option(context, fake_short_path_source_documents, fake_long_path_source_documents, f_console_symbol_short_enable, f_console_symbol_long_enable, "Custom path to the documents source files."); + fll_program_print_help_option(context, fake_short_path_source_licenses, fake_long_path_source_licenses, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the license source files."); + fll_program_print_help_option(context, fake_short_path_source_settings, fake_long_path_source_settings, f_console_symbol_short_enable, f_console_symbol_long_enable, " Custom path to the settings source files."); + + printf("%c%c", f_string_eol, f_string_eol); + + fl_color_print(f_standard_output, context.important, context.reset, " Special Options: "); + + fll_program_print_help_option_long(context, fake_long_documents_disabled, f_console_symbol_long_enable, " Forcibly do not build documents files."); + fll_program_print_help_option_long(context, fake_long_documents_enabled, f_console_symbol_long_enable, " Forcibly do build documents files."); + fll_program_print_help_option_long(context, fake_long_shared_disabled, f_console_symbol_long_enable, "Forcibly do not build shared files."); + fll_program_print_help_option_long(context, fake_long_shared_enabled, f_console_symbol_long_enable, " Forcibly do build shared files."); + fll_program_print_help_option_long(context, fake_long_static_disabled, f_console_symbol_long_enable, "Forcibly do not build static files."); + fll_program_print_help_option_long(context, fake_long_static_enabled, f_console_symbol_long_enable, " Forcibly do build static files."); + + printf("%c%c", f_string_eol, f_string_eol); + + fl_color_print(f_standard_output, context.important, context.reset, " Operations: "); + + fll_program_print_help_option_other(context, fake_other_operation_build, " Build or compile the code based on build settings file."); + fll_program_print_help_option_other(context, fake_other_operation_clean, " Delete all build files."); + fll_program_print_help_option_other(context, fake_other_operation_make, " Build or compile the code based on fakefile."); + fll_program_print_help_option_other(context, fake_other_operation_skeleton, "Build a skeleton directory structure."); + + fll_program_print_help_usage(context, fake_name, "operation"); + + printf(" When performing the "); + fl_color_print(f_standard_output, context.notable, context.reset, "%s", fake_other_operation_build); + printf(" operation, the "); + fl_color_print(f_standard_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, fake_long_mode); + printf(" parameter specifies a name (limited to alpha-numeric, underscore, and dash) to be used in addition to the global."); + printf("%c", f_string_eol); + + printf(" For example, when a "); + fl_color_print(f_standard_output, context.notable, context.reset, "%s", fake_long_mode); + printf(" of 'fll_monolithic' is specified, build libaries from both 'build_libraries' and 'build_libraries-fll_monolithic' are used (but not 'build_libraries-fll_level')."); + + printf("%c", f_string_eol); + + return f_none; + } +#endif // _di_fake_print_help_ + +#ifndef _di_fake_main_ + f_return_status fake_main(const f_console_arguments arguments, fake_data *data) { + f_status status = f_none; + + uint8_t operations[fake_operations_total] = fake_operations_initialize; + + { + f_console_parameters parameters = { data->parameters, fake_total_parameters }; + f_console_parameter_ids choices = f_console_parameter_ids_initialize; + + // Identify priority of color parameters. + { + f_console_parameter_id ids[3] = { fake_parameter_no_color, fake_parameter_light, fake_parameter_dark }; + choices.id = ids; + choices.used = 3; + + status = fll_program_parameter_process(arguments, parameters, choices, &data->remaining, &data->context); + + if (f_status_is_error(status)) { + fake_delete_data(data); + return f_status_set_error(status); + } + } + + // Determine order of operations. + { + uint8_t order_total = 0; + uint8_t operations_id[fake_operations_total] = fake_operations_initialize; + + if (data->parameters[fake_parameter_operation_build].result == f_console_result_found) { + operations[0] = fake_operation_build; + operations_id[0] = fake_parameter_operation_build; + order_total = 1; + } + + if (data->parameters[fake_parameter_operation_clean].result == f_console_result_found) { + if (order_total) { + if (data->parameters[fake_parameter_operation_build].locations.array[0] < data->parameters[fake_parameter_operation_clean].locations.array[0]) { + operations[0] = fake_operation_build; + operations[1] = fake_operation_clean; + + operations_id[0] = fake_parameter_operation_build; + operations_id[1] = fake_parameter_operation_clean; + } + else { + operations[0] = fake_operation_clean; + operations[1] = fake_operation_build; + + operations_id[0] = fake_parameter_operation_clean; + operations_id[1] = fake_parameter_operation_build; + } + + order_total = 2; + } + else { + operations[0] = fake_operation_clean; + operations_id[0] = fake_parameter_operation_clean; + order_total = 1; + } + } + + if (data->parameters[fake_parameter_operation_make].result == f_console_result_found) { + if (order_total) { + uint8_t i = 0; + + for (; i < order_total; i++) { + if (data->parameters[fake_parameter_operation_make].locations.array[0] < data->parameters[operations_id[i]].locations.array[0]) break; + } // for + + if (i == order_total) { + operations[order_total] = fake_operation_make; + operations_id[order_total] = fake_parameter_operation_make; + } + else { + for (uint8_t j = order_total; j > i; j-- ) { + operations[j] = operations[j - 1]; + operations_id[j] = operations_id[j - 1]; + } // for + + operations[i] = fake_operation_make; + operations_id[i] = fake_parameter_operation_make; + } + + order_total++; + } + else { + operations[0] = fake_operation_make; + operations_id[0] = fake_parameter_operation_make; + order_total = 1; + } + } + + if (data->parameters[fake_parameter_operation_skeleton].result == f_console_result_found) { + if (order_total) { + uint8_t i = 0; + + for (; i < order_total; i++) { + if (data->parameters[fake_parameter_operation_skeleton].locations.array[0] < data->parameters[operations_id[i]].locations.array[0]) break; + } // for + + if (i == order_total) { + operations[order_total] = fake_operation_skeleton; + operations_id[order_total] = fake_parameter_operation_skeleton; + } + else { + for (uint8_t j = order_total; j > i; j--) { + operations[j] = operations[j - 1]; + operations_id[j] = operations_id[j - 1]; + } // for + + operations[i] = fake_operation_skeleton; + operations_id[i] = fake_parameter_operation_skeleton; + } + + order_total++; + } + else { + operations[0] = fake_operation_skeleton; + } + } + } + } + + status = f_none; + + if (data->parameters[fake_parameter_help].result == f_console_result_found) { + fake_print_help(data->context); + } + else if (data->parameters[fake_parameter_version].result == f_console_result_found) { + fll_program_print_version(fake_version); + } + else if (operations[0]) { + status = fake_process_console_parameters(arguments, data); + + if (f_status_is_error(status)) { + fake_delete_data(data); + return f_status_set_error(status); + } + + status = fake_load_settings_data(*data, &data->settings_data); + + if (f_status_is_error(status)) { + fake_delete_data(data); + return f_status_set_error(status); + } + + for (uint8_t i = 0; i < fake_operations_total && operations[i]; i++) { + data->operation = operations[i]; + + if (operations[i] == fake_operation_build) { + status = fake_build_execute_process_script(*data, data->settings_data.process_pre); + if (f_status_is_error(status)) { + // @todo handle errors. + break; + } + + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the operation '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", fake_other_operation_build); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is not yet implemented."); + + status = fake_build_execute_process_script(*data, data->settings_data.process_post); + if (f_status_is_error(status)) { + // @todo handle errors. + break; + } + } + else if (operations[i] == fake_operation_clean) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the operation '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", fake_other_operation_clean); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is not yet implemented."); + } + else if (operations[i] == fake_operation_make) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the operation '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", fake_other_operation_make); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is not yet implemented."); + } + else if (operations[i] == fake_operation_skeleton) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the operation '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", fake_other_operation_skeleton); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is not yet implemented."); + } + } // for + } + else { + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify an operation."); + status = f_status_set_error(f_invalid_parameter); + } + + fake_delete_data(data); + return status; + } +#endif // _di_fake_main_ + +#ifndef _di_fake_delete_data_ + f_return_status fake_delete_data(fake_data *data) { + + for (f_string_length i = 0; i < fake_total_parameters; i++) { + f_macro_string_lengths_delete_simple(data->parameters[i].locations); + f_macro_string_lengths_delete_simple(data->parameters[i].additional); + } // for + + f_macro_string_lengths_delete_simple(data->remaining); + + f_macro_string_dynamic_delete_simple(data->defines); + f_macro_string_dynamics_delete_simple(data->mode); + f_macro_string_dynamic_delete_simple(data->process); + f_macro_string_dynamic_delete_simple(data->settings); + + f_macro_string_dynamic_delete_simple(data->path_build); + f_macro_string_dynamic_delete_simple(data->path_work); + + f_macro_string_dynamic_delete_simple(data->path_source_build); + f_macro_string_dynamic_delete_simple(data->path_source_common); + f_macro_string_dynamic_delete_simple(data->path_source_data); + f_macro_string_dynamic_delete_simple(data->path_source_documents); + f_macro_string_dynamic_delete_simple(data->path_source_codes); + f_macro_string_dynamic_delete_simple(data->path_source_licenses); + f_macro_string_dynamic_delete_simple(data->path_source_settings); + + fake_macro_settings_data_delete_simple(data->settings_data); + + fl_macro_color_context_delete_simple(data->context); + + return f_none; + } +#endif // _di_fake_delete_data_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h new file mode 100644 index 0000000..909d280 --- /dev/null +++ b/level_3/fake/c/fake.h @@ -0,0 +1,701 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * The Feautureless Make System (aka fake) used as a package build tool. + * + * This program is intented only to build source code into binaries. + * It specifically does not install, test, or package some project. + * It does provide the built binaries and scripts in a consistent location for other programs to operate on. + * + * This currently only supports a few select languages. + * Additional languages can be provided via explicit operations. + * + * The built sources are placed in the build directory with the following structure: + * - build/ + * - data/ + * - documents/ + * - includes/ + * - libraries/ + * - script/ + * - shared/ + * - static/ + * - objects/ + * - programs/ + * - script/ + * - shared/ + * - static/ + * - settings/ + * + * The "data/" directory contains all file data, such as firmware or files commonly found under /usr/share in a standard GNU Linux system. + * The "data/" direcory may also contain build-time data. + * The "documents/" directory contains all documentation after any build-time processing. + * The "libraries/" and "programs/" directories contains the sub-directories "script/", "shared/", and "static/". + * The "libraries/" directory will contain compiled libraries or library-like scripts in their respective sub-directories. + * The "objects/" directory will contain any compile object files. + * The "progams/" directory will contain compiled programs or program-like scripts in their respective sub-directories. + * The "settings/" directory contains all configuration data, such as files commonly found under /etc in a standard GNU Linux system. + * + * @todo this will eventually support fakefile, which is akin to makefile. + * All of the setting data will be loaded and available for a fakefile. + * + * @todo update the below documentation and clean it up (this is the build settings documentation). + * + * "build_compiler" + * + * "build_libraries" + * + * "build_linker" + * + * "build_shared" + * + * "build_sources_headers" + * "build_sources_library" + * "build_sources_program" + * "build_sources_settings" + * "build_sources_shell" + * + * "build_static" + * + * "defines_all" + * "defines_shared" + * "defines_static" + * + * "flags_all" + * "flags_library" + * "flags_program" + * "flags_shared" + * "flags_static" + * + * "path_language" + * + * "process_pre" + * - This represents the name of a script to run (either a path to the script by prepending '/' or './', or the name a script found via PATH environment variable). + * - This script will receive three types of parameters, if relevant (1: the operation name, will always be present) (2: -m mode, such that "mode" is the mode value) (3: -d defines, such that "defines" is the combine defines). + * - This script is run before the operation, for each operation. + * - This script also accepts the color mode parameters as "+n" for no color and "+l" for light color. + * - The path of the script, when using './' is relative to the 'data/build/settings/' directory. + * + * "process_post" + * - Identical to "pre_process", except that this script is run after the operation, for each operation. + * - Also (always) receives a parameter: "-r result, such that "result" is the numeric value representing the return status of the operation. + * + * "project_level" This needs to be changed (maybe "build_includes_path"), such that the value is "level_1" instead of "1', for example. There needs to be additional include sub-directory support for header directories. + * "project_name" + * + * "version_major" + * "version_micro" + * "version_minor" + * + * The data/ is intended to contain additional data, the following are special use or reserved: + * "data/build/": The build related settings are stored here, such as process_pre.sh or the settings configuration "data/build/settings". + * "data/settings/": Any configuration settings files, like those found under "/etc/". + * "data/common/": Any common data files, like those found under "/usr/share/". + * "data/documents/": Any documentation data files, like those found under "/usr/share/man/". + */ +#ifndef _fake_h + +// libc includes +#include +#include +#include +#include + +// fll-0 includes +#include +#include +#include +#include +#include + +// fll-1 includes +#include +#include +#include +#include + +// fll-2 includes +#include +#include +#include +#include + +// Temporary include, remove this. +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fake_version_ + #define fake_major_version "0" + #define fake_minor_version "5" + #define fake_micro_version "0" + #define fake_version fake_major_version "." fake_minor_version "." fake_micro_version +#endif // _di_fake_version_ + +#ifndef _di_fake_name_ + #define fake_name "fake" + #define fake_name_long "Featureless Make" +#endif // _di_fake_name_ + +#ifndef _di_fake_default_allocation_step_ + // Set to at least 4 to provide a UTF-8 friendly allocation step. + #define fake_default_allocation_step 4 +#endif // _di_fake_default_allocation_step_ + +#ifndef _di_fake_defaults_ + #define fake_default_path_build "build/" + #define fake_default_path_build_documents "build/documents/" + #define fake_default_path_build_includes "build/includes/" + #define fake_default_path_build_libaries "build/libaries/" + #define fake_default_path_build_libaries_script "build/libaries/script/" + #define fake_default_path_build_libaries_shared "build/libaries/shared/" + #define fake_default_path_build_libaries_static "build/libaries/static/" + #define fake_default_path_build_objects "build/objects/" + #define fake_default_path_build_process "build/process/" + #define fake_default_path_build_programs "build/programs/" + #define fake_default_path_build_programs_script "build/programs/script/" + #define fake_default_path_build_programs_shared "build/programs/shared/" + #define fake_default_path_build_programs_static "build/programs/static/" + #define fake_default_path_build_settings "build/settings/" + #define fake_default_path_work "" + + #define fake_default_path_build_length 6 + #define fake_default_path_build_documents_length 16 + #define fake_default_path_build_includes_length 15 + #define fake_default_path_build_libaries_length 15 + #define fake_default_path_build_libaries_script_length 22 + #define fake_default_path_build_libaries_shared_length 22 + #define fake_default_path_build_libaries_static_length 22 + #define fake_default_path_build_objects_length 14 + #define fake_default_path_build_process_length 14 + #define fake_default_path_build_programs_length 15 + #define fake_default_path_build_programs_script_length 22 + #define fake_default_path_build_programs_shared_length 22 + #define fake_default_path_build_programs_static_length 22 + #define fake_default_path_build_settings_length 15 + #define fake_default_path_work_length 0 + + #define fake_default_defines "" + #define fake_default_mode "" + #define fake_default_process "" + #define fake_default_settings "settings" + + #define fake_default_defines_length 0 + #define fake_default_mode_length 0 + #define fake_default_process_length 0 + #define fake_default_settings_length 8 + + #define fake_default_path_source_build "data/build/" + #define fake_default_path_source_codes "sources/" + #define fake_default_path_source_common "data/common/" + #define fake_default_path_source_data "data/" + #define fake_default_path_source_documents "data/documents/" + #define fake_default_path_source_licenses "licenses/" + #define fake_default_path_source_settings "data/build/" + + #define fake_default_path_source_build_length 11 + #define fake_default_path_source_codes_length 8 + #define fake_default_path_source_common_length 12 + #define fake_default_path_source_data_length 5 + #define fake_default_path_source_documents_length 15 + #define fake_default_path_source_licenses_length 9 + #define fake_default_path_source_settings_length 11 + + #define fake_default_language_c "c/" + #define fake_default_language_cpp "c++/" + #define fake_default_language_shell "shell/" + + #define fake_default_language_c_length 2 + #define fake_default_language_cpp_length 4 + #define fake_default_language_shell_length 6 +#endif // _di_fake_defaults_ + +#ifndef _di_settings_data_ + typedef struct { + f_string_dynamic build_compiler; + f_string_dynamic build_libraries; + f_string_dynamic build_linker; + f_string_dynamic build_shared; + f_string_dynamic build_sources_headers; + f_string_dynamic build_sources_library; + f_string_dynamic build_sources_program; + f_string_dynamic build_sources_settings; + f_string_dynamic build_sources_shell; + f_string_dynamic build_static; + f_string_dynamic defines_all; + f_string_dynamic defines_shared; + f_string_dynamic defines_static; + f_string_dynamic flags_all; + f_string_dynamic flags_library; + f_string_dynamic flags_program; + f_string_dynamic flags_shared; + f_string_dynamic flags_static; + f_string_dynamic path_language; + f_string_dynamic process_post; + f_string_dynamic process_pre; + f_string_dynamic project_level; + f_string_dynamic project_name; + f_string_dynamic version_major; + f_string_dynamic version_micro; + f_string_dynamic version_minor; + } fake_settings_data; + + #define fake_settings_data_initialize { f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize, f_string_dynamic_initialize } + + #define fake_macro_settings_build_clear(settings_data) \ + f_macro_string_dynamic_clear(settings_data.build_compiler) \ + f_macro_string_dynamic_clear(settings_data.build_libraries) \ + f_macro_string_dynamic_clear(settings_data.build_linker) \ + f_macro_string_dynamic_clear(settings_data.build_shared) \ + f_macro_string_dynamic_clear(settings_data.build_sources_headers) \ + f_macro_string_dynamic_clear(settings_data.build_sources_library) \ + f_macro_string_dynamic_clear(settings_data.build_sources_program) \ + f_macro_string_dynamic_clear(settings_data.build_sources_settings) \ + f_macro_string_dynamic_clear(settings_data.build_sources_shell) \ + f_macro_string_dynamic_clear(settings_data.build_static) \ + f_macro_string_dynamic_clear(settings_data.defines_all) \ + f_macro_string_dynamic_clear(settings_data.defines_shared) \ + f_macro_string_dynamic_clear(settings_data.defines_static) \ + f_macro_string_dynamic_clear(settings_data.flags_all) \ + f_macro_string_dynamic_clear(settings_data.flags_library) \ + f_macro_string_dynamic_clear(settings_data.flags_program) \ + f_macro_string_dynamic_clear(settings_data.flags_shared) \ + f_macro_string_dynamic_clear(settings_data.flags_static) \ + f_macro_string_dynamic_clear(settings_data.path_language) \ + f_macro_string_dynamic_clear(settings_data.process_post) \ + f_macro_string_dynamic_clear(settings_data.process_pre) \ + f_macro_string_dynamic_clear(settings_data.project_level) \ + f_macro_string_dynamic_clear(settings_data.project_name) \ + f_macro_string_dynamic_clear(settings_data.version_major) \ + f_macro_string_dynamic_clear(settings_data.version_micro) \ + f_macro_string_dynamic_clear(settings_data.version_minor) + + #define fake_macro_settings_data_delete(status, settings_data) \ + f_macro_string_dynamic_delete(status, settings_data.build_compiler) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_libraries) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_linker) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_shared) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_sources_headers) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_sources_library) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_sources_program) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_sources_settings) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_sources_shell) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.build_static) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.defines_all) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.defines_shared) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.defines_static) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.flags_all) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.flags_library) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.flags_program) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.flags_shared) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.flags_static) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.path_language) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.process_post) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.process_pre) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.project_level) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.project_name) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.version_major) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.version_micro) \ + if (status == f_none) f_macro_string_dynamic_delete(status, settings_data.version_minor) + + #define fake_macro_settings_data_destroy(status, settings_data, length) \ + f_macro_string_dynamic_delete(status, settings_data.build_compiler) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_libraries) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_linker) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_shared) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_sources_headers) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_sources_library) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_sources_program) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_sources_settings) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_sources_shell) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.build_static) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.defines_all) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.defines_shared) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.defines_static) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.flags_all) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.flags_library) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.flags_program) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.flags_shared) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.flags_static) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.path_language) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.process_post) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.process_pre) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.project_level) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.project_name) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.version_major) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.version_micro) \ + if (status == f_none) f_macro_string_dynamic_destroy(status, settings_data.version_minor) + + #define fake_macro_settings_data_delete_simple(settings_data) \ + f_macro_string_dynamic_delete_simple(settings_data.build_compiler) \ + f_macro_string_dynamic_delete_simple(settings_data.build_libraries) \ + f_macro_string_dynamic_delete_simple(settings_data.build_linker) \ + f_macro_string_dynamic_delete_simple(settings_data.build_shared) \ + f_macro_string_dynamic_delete_simple(settings_data.build_sources_headers) \ + f_macro_string_dynamic_delete_simple(settings_data.build_sources_library) \ + f_macro_string_dynamic_delete_simple(settings_data.build_sources_program) \ + f_macro_string_dynamic_delete_simple(settings_data.build_sources_settings) \ + f_macro_string_dynamic_delete_simple(settings_data.build_sources_shell) \ + f_macro_string_dynamic_delete_simple(settings_data.build_static) \ + f_macro_string_dynamic_delete_simple(settings_data.defines_all) \ + f_macro_string_dynamic_delete_simple(settings_data.defines_shared) \ + f_macro_string_dynamic_delete_simple(settings_data.defines_static) \ + f_macro_string_dynamic_delete_simple(settings_data.flags_all) \ + f_macro_string_dynamic_delete_simple(settings_data.flags_library) \ + f_macro_string_dynamic_delete_simple(settings_data.flags_program) \ + f_macro_string_dynamic_delete_simple(settings_data.flags_shared) \ + f_macro_string_dynamic_delete_simple(settings_data.flags_static) \ + f_macro_string_dynamic_delete_simple(settings_data.path_language) \ + f_macro_string_dynamic_delete_simple(settings_data.process_post) \ + f_macro_string_dynamic_delete_simple(settings_data.process_pre) \ + f_macro_string_dynamic_delete_simple(settings_data.project_level) \ + f_macro_string_dynamic_delete_simple(settings_data.project_name) \ + f_macro_string_dynamic_delete_simple(settings_data.version_major) \ + f_macro_string_dynamic_delete_simple(settings_data.version_micro) \ + f_macro_string_dynamic_delete_simple(settings_data.version_minor) + + #define fake_macro_settings_data_destroy_simple(settings_data, length) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_compiler) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_libraries) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_linker) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_shared) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_sources_headers) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_sources_library) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_sources_program) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_sources_settings) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_sources_shell) \ + f_macro_string_dynamic_destroy_simple(settings_data.build_static) \ + f_macro_string_dynamic_destroy_simple(settings_data.defines_all) \ + f_macro_string_dynamic_destroy_simple(settings_data.defines_shared) \ + f_macro_string_dynamic_destroy_simple(settings_data.defines_static) \ + f_macro_string_dynamic_destroy_simple(settings_data.flags_all) \ + f_macro_string_dynamic_destroy_simple(settings_data.flags_library) \ + f_macro_string_dynamic_destroy_simple(settings_data.flags_program) \ + f_macro_string_dynamic_destroy_simple(settings_data.flags_shared) \ + f_macro_string_dynamic_destroy_simple(settings_data.flags_static) \ + f_macro_string_dynamic_destroy_simple(settings_data.path_language) \ + f_macro_string_dynamic_destroy_simple(settings_data.process_post) \ + f_macro_string_dynamic_destroy_simple(settings_data.process_pre) \ + f_macro_string_dynamic_destroy_simple(settings_data.project_level) \ + f_macro_string_dynamic_destroy_simple(settings_data.project_name) \ + f_macro_string_dynamic_destroy_simple(settings_data.version_major) \ + f_macro_string_dynamic_destroy_simple(settings_data.version_micro) \ + f_macro_string_dynamic_destroy_simple(settings_data.version_minor) + + #define fake_settings_name_build_compiler "build_compiler" + #define fake_settings_name_build_libraries "build_libraries" + #define fake_settings_name_build_linker "build_linker" + #define fake_settings_name_build_shared "build_shared" + #define fake_settings_name_build_sources_headers "build_sources_headers" + #define fake_settings_name_build_sources_library "build_sources_library" + #define fake_settings_name_build_sources_program "build_sources_program" + #define fake_settings_name_build_sources_settings "build_sources_settings" + #define fake_settings_name_build_sources_shell "build_sources_shell" + #define fake_settings_name_build_static "build_static" + #define fake_settings_name_defines_all "defines_all" + #define fake_settings_name_defines_shared "defines_shared" + #define fake_settings_name_defines_static "defines_static" + #define fake_settings_name_flags_all "flags_all" + #define fake_settings_name_flags_library "flags_library" + #define fake_settings_name_flags_program "flags_program" + #define fake_settings_name_flags_shared "flags_shared" + #define fake_settings_name_flags_static "flags_static" + #define fake_settings_name_path_language "path_language" + #define fake_settings_name_process_post "process_post" + #define fake_settings_name_process_pre "process_pre" + #define fake_settings_name_project_level "project_level" + #define fake_settings_name_project_name "project_name" + #define fake_settings_name_version_major "version_major" + #define fake_settings_name_version_micro "version_micro" + #define fake_settings_name_version_minor "version_minor" + + #define fake_settings_name_build_compiler_length 14 + #define fake_settings_name_build_libraries_length 15 + #define fake_settings_name_build_linker_length 12 + #define fake_settings_name_build_shared_length 12 + #define fake_settings_name_build_sources_headers_length 21 + #define fake_settings_name_build_sources_library_length 21 + #define fake_settings_name_build_sources_program_length 21 + #define fake_settings_name_build_sources_settings_length 22 + #define fake_settings_name_build_sources_shell_length 19 + #define fake_settings_name_build_static_length 12 + #define fake_settings_name_defines_all_length 11 + #define fake_settings_name_defines_shared_length 14 + #define fake_settings_name_defines_static_length 14 + #define fake_settings_name_flags_all_length 9 + #define fake_settings_name_flags_library_length 13 + #define fake_settings_name_flags_program_length 13 + #define fake_settings_name_flags_shared_length 12 + #define fake_settings_name_flags_static_length 12 + #define fake_settings_name_path_language_length 13 + #define fake_settings_name_process_post_length 12 + #define fake_settings_name_process_pre_length 11 + #define fake_settings_name_project_level_length 13 + #define fake_settings_name_project_name_length 12 + #define fake_settings_name_version_major_length 13 + #define fake_settings_name_version_micro_length 13 + #define fake_settings_name_version_minor_length 13 + + #define fake_settings_total 26 +#endif // _di_settings_data_ + +#ifndef _di_fake_build_language_ + enum { + fake_build_language_c = 1, + fake_build_language_cpp, + fake_build_language_shell, + }; + + #define fake_build_language_c "c" + #define fake_build_language_cpp "c++" + #define fake_build_language_shell "shell" +#endif // _di_fake_build_language_ + +#ifndef _di_fake_defines_ + enum { + fake_operation_build = 1, + fake_operation_clean, + fake_operation_make, + fake_operation_skeleton, + }; + + #define fake_operations_total 4 + #define fake_operations_initialize { 0, 0, 0, 0 } + + #define fake_short_defines "d" + #define fake_short_mode "m" + #define fake_short_process "p" + #define fake_short_settings "s" + + #define fake_short_path_build "b" + #define fake_short_path_work "w" + + #define fake_short_path_source_build "B" + #define fake_short_path_source_common "O" + #define fake_short_path_source_data "D" + #define fake_short_path_source_documents "M" + #define fake_short_path_source_codes "C" + #define fake_short_path_source_licenses "L" + #define fake_short_path_source_settings "S" + + #define fake_long_defines "defines" + #define fake_long_mode "mode" + #define fake_long_process "process" + #define fake_long_settings "settings" + + #define fake_long_path_build "build" + #define fake_long_path_work "work" + + #define fake_long_path_source_build "source_build" + #define fake_long_path_source_common "source_common" + #define fake_long_path_source_data "source_data" + #define fake_long_path_source_documents "source_documents" + #define fake_long_path_source_codes "source_codes" + #define fake_long_path_source_licenses "source_licenses" + #define fake_long_path_source_settings "source_settings" + + // these special parameters are provided in such a way that they mimic the traditional ./configure script. + #define fake_long_documents_disabled "disable-doc" + #define fake_long_documents_enabled "enable-doc" + #define fake_long_shared_disabled "disable-shared" + #define fake_long_shared_enabled "enable-shared" + #define fake_long_static_disabled "disable-static" + #define fake_long_static_enabled "enable-static" + + #define fake_other_operation_build "build" + #define fake_other_operation_clean "clean" + #define fake_other_operation_make "make" + #define fake_other_operation_skeleton "skeleton" + + #define fake_other_operation_build_length 5 + #define fake_other_operation_clean_length 5 + #define fake_other_operation_make_length 4 + #define fake_other_operation_skeleton_length 8 + + enum { + fake_parameter_help, + fake_parameter_light, + fake_parameter_dark, + fake_parameter_no_color, + fake_parameter_version, + + fake_parameter_defines, + fake_parameter_mode, + fake_parameter_process, + fake_parameter_settings, + + fake_parameter_path_build, + fake_parameter_path_work, + + fake_parameter_path_source_build, + fake_parameter_path_source_common, + fake_parameter_path_source_data, + fake_parameter_path_source_documents, + fake_parameter_path_source_codes, + fake_parameter_path_source_licenses, + fake_parameter_path_source_settings, + + fake_parameter_documents_disabled, + fake_parameter_documents_enabled, + fake_parameter_shared_disabled, + fake_parameter_shared_enabled, + fake_parameter_static_disabled, + fake_parameter_static_enabled, + + fake_parameter_operation_build, + fake_parameter_operation_clean, + fake_parameter_operation_make, + fake_parameter_operation_skeleton, + }; + + #define fake_console_parameter_initialize \ + { \ + f_console_parameter_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \ + f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \ + f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, 0, f_console_type_inverse), \ + f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \ + f_console_parameter_initialize(fake_short_defines, fake_long_defines, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_mode, fake_long_mode, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_process, fake_long_process, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_settings, fake_long_settings, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_build, fake_long_path_build, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_work, fake_long_path_work, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_build, fake_long_path_source_build, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_common, fake_long_path_source_common, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_data, fake_long_path_source_data, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_documents, fake_long_path_source_documents, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_codes, fake_long_path_source_codes, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_licenses, fake_long_path_source_licenses, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(fake_short_path_source_settings, fake_long_path_source_settings, 0, 1, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_documents_disabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_documents_enabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_shared_disabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_shared_enabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_static_disabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, fake_long_static_enabled, 0, 0, f_console_type_normal), \ + f_console_parameter_initialize(0, 0, fake_other_operation_build, 0, f_console_type_other), \ + f_console_parameter_initialize(0, 0, fake_other_operation_clean, 0, f_console_type_other), \ + f_console_parameter_initialize(0, 0, fake_other_operation_make, 0, f_console_type_other), \ + f_console_parameter_initialize(0, 0, fake_other_operation_skeleton, 0, f_console_type_other), \ + } + + #define fake_total_parameters 28 +#endif // _di_fake_defines_ + +#ifndef _di_fake_data_ + typedef struct { + f_console_parameter parameters[fake_total_parameters]; + + f_string_lengths remaining; + bool process_pipe; + + uint8_t operation; + + f_string_dynamic defines; + f_string_dynamics mode; + f_string_dynamic process; + f_string_dynamic settings; + + + f_string_dynamic path_build; + f_string_dynamic path_work; + + f_string_dynamic path_source_build; + f_string_dynamic path_source_common; + f_string_dynamic path_source_data; + f_string_dynamic path_source_documents; + f_string_dynamic path_source_codes; + f_string_dynamic path_source_licenses; + f_string_dynamic path_source_settings; + + fake_settings_data settings_data; + + fl_color_context context; + } fake_data; + + #define fake_data_initialize \ + { \ + fake_console_parameter_initialize, \ + f_string_lengths_initialize, \ + f_false, \ + 0, \ + f_string_dynamic_initialize, \ + f_string_dynamics_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + f_string_dynamic_initialize, \ + fake_settings_data_initialize, \ + fl_color_context_initialize, \ + } +#endif // _di_fake_data_ + +/** + * Print help to standard output. + * + * @param context + * The color context settings. + * + * @return + * f_none on success. + */ +#ifndef _di_fake_print_help_ + extern f_return_status fake_print_help(const fl_color_context context); +#endif // _di_fake_print_help_ + +/** + * Execute main program. + * + * Be sure to call fake_delete_data() after executing this. + * + * @param arguments + * The parameters passed to the process. + * @param data + * The program data. + * + * @return + * f_none on success. + * Status codes (with error bit) are returned on any problem. + * + * @see fake_delete_data() + */ +#ifndef _di_fake_main_ + extern f_return_status fake_main(const f_console_arguments arguments, fake_data *data); +#endif // _di_fake_main_ + +/** + * Deallocate data. + * + * Be sure to call this after executing fake_main(). + * + * @param data + * The program data. + * + * @return + * f_none on success. + * Status codes (with error bit) are returned on any problem. + * + * @see fake_main() + */ +#ifndef _di_fake_delete_data_ + extern f_return_status fake_delete_data(fake_data *data); +#endif // _di_fake_delete_data_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fake_h diff --git a/level_3/fake/c/main.c b/level_3/fake/c/main.c new file mode 100644 index 0000000..0cfad3f --- /dev/null +++ b/level_3/fake/c/main.c @@ -0,0 +1,14 @@ +#include + +int main(const unsigned long argc, const f_string *argv) { + const f_console_arguments arguments = { argc, argv }; + fake_data data = fake_data_initialize; + + f_status status = fake_main(arguments, &data); + + if (f_status_is_error(status)) { + return 1; + } + + return 0; +} diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c new file mode 100644 index 0000000..b525148 --- /dev/null +++ b/level_3/fake/c/private-build.c @@ -0,0 +1,65 @@ +#include +#include "private-fake.h" +#include "private-build.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fake_build_execute_process_script_ + f_return_status fake_build_execute_process_script(const fake_data data, const f_string_dynamic process_script) { + if (process_script.used == 0) return f_none; + + f_status status = f_none; + f_string_dynamic path = f_string_dynamic_initialize; + + if (process_script.string[0] != '/') { + status = fl_string_dynamic_append(data.path_source_settings, &path); + } + + if (!f_status_is_error(status)) { + status = fl_string_dynamic_append(process_script, &path); + } + + if (f_status_is_error(status)) { + fake_print_error(data.context, f_status_set_fine(status), "fl_string_dynamic_append", f_true); + + f_macro_string_dynamic_delete_simple(path); + return status; + } + + // @todo: add all arguments and possibly fss settings. + f_string_dynamics arguments = f_string_dynamics_initialize; + f_string_dynamic argument[1] = f_string_dynamic_initialize; + int results = 0; + + argument[0].string = (f_string) fake_other_operation_build; + argument[0].size = fake_other_operation_build_length; + argument[0].used = fake_other_operation_build_length; + + arguments.array = argument; + arguments.size = 1; + arguments.used = 1; + + status = fll_execute_path(path.string, arguments, &results); + + if (f_status_is_error(status)) { + if (f_status_set_fine(status) == f_failure) { + fl_color_print(f_standard_error, data.context.error, data.context.reset, "ERROR: Failed to execute script: "); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%s", path.string); + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "."); + } + else { + fake_print_error(data.context, status, "fll_execute_program", f_true); + } + } + + f_macro_string_dynamic_delete_simple(path); + + return status; + } +#endif // _di_fake_execute_process_pre_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/private-build.h b/level_3/fake/c/private-build.h new file mode 100644 index 0000000..492012b --- /dev/null +++ b/level_3/fake/c/private-build.h @@ -0,0 +1,36 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + */ +#ifndef _PRIVATE_build_h +#define _PRIVATE_build_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Execute the Pre-Process or Post-pocess build script. + * + * @param data + * The program data. + * @param process_script + * The setting_data file name fo the appropriate process script. + * This is expected to be eithe data.settings_data.process_pre or data.settings_data.process_post. + * + * @return + * f_none on success. + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_fake_build_execute_process_script_ + extern f_return_status fake_build_execute_process_script(const fake_data data, const f_string_dynamic process_script) f_gcc_attribute_visibility_internal; +#endif // _di_fake_build_execute_process_script_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_build_h diff --git a/level_3/fake/c/private-clean.c b/level_3/fake/c/private-clean.c new file mode 100644 index 0000000..a85ade6 --- /dev/null +++ b/level_3/fake/c/private-clean.c @@ -0,0 +1,12 @@ +#include +#include "private-fake.h" +#include "private-clean.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/private-clean.h b/level_3/fake/c/private-clean.h new file mode 100644 index 0000000..01e125c --- /dev/null +++ b/level_3/fake/c/private-clean.h @@ -0,0 +1,19 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + */ +#ifndef _PRIVATE_clean_h +#define _PRIVATE_clean_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_clean_h diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c new file mode 100644 index 0000000..213c339 --- /dev/null +++ b/level_3/fake/c/private-fake.c @@ -0,0 +1,713 @@ +#include +#include "private-fake.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fake_load_settings_data_ + f_return_status fake_load_settings_data(const fake_data data, fake_settings_data *settings_data) { + f_status status = f_none; + f_file file = f_file_initialize; + f_string_dynamic buffer = f_string_dynamic_initialize; + f_string_dynamic path = f_string_dynamic_initialize; + + status = fl_string_dynamic_append(data.path_source_settings, &path); + + if (!f_status_is_error(status)) { + status = fl_string_dynamic_append(data.settings, &path); + } + + if (f_status_is_error(status)) { + fake_print_error(data.context, f_status_set_fine(status), "fl_string_dynamic_append", f_true); + + f_macro_string_dynamic_delete_simple(path); + return status; + } + + { + f_string name_function = f_string_initialize; + + name_function = "f_file_exists"; + status = f_file_exists(path.string); + + if (status == f_true) { + name_function = "f_file_open"; + status = f_file_open(&file, path.string); + + if (status == f_none) { + name_function = "fl_file_read_position"; + status = fl_file_read(&file, &buffer); + + f_file_close(&file); + } + } + else if (status == f_false) { + status = f_status_set_error(f_file_not_found); + } + + if (f_status_is_error(status)) { + fake_print_error_file(data.context, f_status_set_fine(status), name_function, path.string, "file", f_true); + + f_macro_string_dynamic_delete_simple(buffer); + f_macro_string_dynamic_delete_simple(path); + return status; + } + } + + if (buffer.used > 0) { + f_fss_objects objects = f_fss_objects_initialize; + f_fss_contents contents = f_fss_contents_initialize; + f_string_location location = f_string_location_initialize; + + location.start = 0; + location.stop = buffer.used - 1; + + status = fll_fss_basic_read(&buffer, &location, &objects, &contents); + + if (f_status_is_error(status)) { + f_macro_fss_objects_delete_simple(objects); + f_macro_fss_contents_delete_simple(contents); + f_macro_string_dynamic_delete_simple(buffer); + + if (status == f_status_set_error(f_incomplete_utf_on_stop)) { + fl_color_print(f_standard_error, data.context.error, data.context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at stop position (at "); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%d", location.start); + fl_color_print(f_standard_error, data.context.error, data.context.reset, " of settings file '"); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%s", path.string); + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "')."); + } + else if (status == f_status_set_error(f_incomplete_utf_on_stop)) { + fl_color_print(f_standard_error, data.context.error, data.context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at end of string (at "); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%d", location.start); + fl_color_print(f_standard_error, data.context.error, data.context.reset, " of settings file '"); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%s", path.string); + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "')."); + } + else { + fake_print_error(data.context, f_status_set_fine(status), "fll_fss_basic_read", true); + } + + f_macro_fss_objects_delete_simple(objects); + f_macro_fss_contents_delete_simple(contents); + f_macro_string_dynamic_delete_simple(buffer); + f_macro_string_dynamic_delete_simple(path); + + return status; + } + + { + const f_string setting_names[] = { + fake_settings_name_build_compiler, + fake_settings_name_build_libraries, + fake_settings_name_build_linker, + fake_settings_name_build_shared, + fake_settings_name_build_sources_headers, + fake_settings_name_build_sources_library, + fake_settings_name_build_sources_program, + fake_settings_name_build_sources_settings, + fake_settings_name_build_sources_shell, + fake_settings_name_build_static, + fake_settings_name_defines_all, + fake_settings_name_defines_shared, + fake_settings_name_defines_static, + fake_settings_name_flags_all, + fake_settings_name_flags_library, + fake_settings_name_flags_program, + fake_settings_name_flags_shared, + fake_settings_name_flags_static, + fake_settings_name_path_language, + fake_settings_name_process_post, + fake_settings_name_process_pre, + fake_settings_name_project_level, + fake_settings_name_project_name, + fake_settings_name_version_major, + fake_settings_name_version_micro, + fake_settings_name_version_minor, + }; + + const f_string_length setting_lengths[] = { + fake_settings_name_build_compiler_length, + fake_settings_name_build_libraries_length, + fake_settings_name_build_linker_length, + fake_settings_name_build_shared_length, + fake_settings_name_build_sources_headers_length, + fake_settings_name_build_sources_library_length, + fake_settings_name_build_sources_program_length, + fake_settings_name_build_sources_settings_length, + fake_settings_name_build_sources_shell_length, + fake_settings_name_build_static_length, + fake_settings_name_defines_all_length, + fake_settings_name_defines_shared_length, + fake_settings_name_defines_static_length, + fake_settings_name_flags_all_length, + fake_settings_name_flags_library_length, + fake_settings_name_flags_program_length, + fake_settings_name_flags_shared_length, + fake_settings_name_flags_static_length, + fake_settings_name_path_language_length, + fake_settings_name_process_post_length, + fake_settings_name_process_pre_length, + fake_settings_name_project_level_length, + fake_settings_name_project_name_length, + fake_settings_name_version_major_length, + fake_settings_name_version_micro_length, + fake_settings_name_version_minor_length, + }; + + f_string_dynamic *setting_values[] = { + &settings_data->build_compiler, + &settings_data->build_libraries, + &settings_data->build_linker, + &settings_data->build_shared, + &settings_data->build_sources_headers, + &settings_data->build_sources_library, + &settings_data->build_sources_program, + &settings_data->build_sources_settings, + &settings_data->build_sources_shell, + &settings_data->build_static, + &settings_data->defines_all, + &settings_data->defines_shared, + &settings_data->defines_static, + &settings_data->flags_all, + &settings_data->flags_library, + &settings_data->flags_program, + &settings_data->flags_shared, + &settings_data->flags_static, + &settings_data->path_language, + &settings_data->process_post, + &settings_data->process_pre, + &settings_data->project_level, + &settings_data->project_name, + &settings_data->version_major, + &settings_data->version_micro, + &settings_data->version_minor, + }; + + status = fll_fss_snatch_mash_together(buffer, objects, contents, setting_names, setting_lengths, setting_values, fake_settings_total, " ", 1); + + if (status == f_none) { + for (f_array_length i = 0; i < data.mode.used; i++) { + f_string_dynamic settings_mode_name_dynamic[fake_settings_total]; + f_string settings_mode_names[fake_settings_total]; + f_string_length setting_mode_lengths[fake_settings_total]; + + memset(&settings_mode_name_dynamic, 0, sizeof(f_string_dynamic) * fake_settings_total); + memset(&settings_mode_names, 0, sizeof(f_string) * fake_settings_total); + + for (f_string_length j = 0; j < fake_settings_total; j++) { + setting_mode_lengths[j] = setting_lengths[j] + 1 + data.mode.array[i].used; + + f_macro_string_dynamic_new(status, settings_mode_name_dynamic[j], setting_mode_lengths[j]); + if (f_status_is_error(status)) break; + + memcpy(settings_mode_name_dynamic[j].string, setting_names[j], setting_lengths[j]); + memcpy(settings_mode_name_dynamic[j].string + setting_lengths[j] + 1, data.mode.array[i].string, data.mode.array[i].used); + settings_mode_name_dynamic[j].string[setting_lengths[j]] = '-'; + + settings_mode_names[j] = settings_mode_name_dynamic[j].string; + } // for + + if (status == f_none) { + status = fll_fss_snatch_mash_together(buffer, objects, contents, settings_mode_names, setting_mode_lengths, setting_values, fake_settings_total, " ", 1); + } + + for (f_string_length j = 0; j < fake_settings_total; j++) { + f_macro_string_dynamic_delete_simple(settings_mode_name_dynamic[j]); + } // for + + if (f_status_is_error(status)) break; + } // for + + if (f_status_is_error(status)) { + fake_print_error(data.context, f_status_set_fine(status), "f_macro_string_dynamic_new", f_true); + + f_macro_fss_objects_delete_simple(objects); + f_macro_fss_contents_delete_simple(contents); + f_macro_string_dynamic_delete_simple(buffer); + f_macro_string_dynamic_delete_simple(path); + return status; + } + } + + if (f_status_is_error(status)) { + if (status == f_status_set_error(f_string_too_large)) { + fl_color_print(f_standard_error, data.context.error, data.context.reset, "ERROR: a setting in the build settings file '"); + fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%s", path); + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "' is too long."); + } + else { + fake_print_error(data.context, f_status_set_fine(status), "fl_string_dynamic_partial_mash", f_true); + } + } + } + + f_macro_fss_objects_delete_simple(objects); + f_macro_fss_contents_delete_simple(contents); + } + + f_macro_string_dynamic_delete_simple(buffer); + f_macro_string_dynamic_delete_simple(path); + + return status; + } +#endif // _di_fake_load_settings_data_ + +#ifndef _di_fake_print_error_ + f_return_status fake_print_error(const fl_color_context context, const f_status status, const f_string function, const bool fallback) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter in function "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", function); + fl_color_print_line(f_standard_error, context.error, context.reset, "()."); + return f_none; + } + + if (status == f_error_allocation || status == f_error_reallocation) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to allocate memory in function "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", function); + fl_color_print_line(f_standard_error, context.error, context.reset, "()."); + return f_none; + } + + if (fallback) { + fl_color_print(f_standard_error, context.error, context.reset, "UNKNOWN ERROR: ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%d", status); + fl_color_print(f_standard_error, context.error, context.reset, ") in function "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", function); + fl_color_print_line(f_standard_error, context.error, context.reset, "()."); + } + + return f_unknown; + } +#endif // _di_fake_print_error_ + +#ifndef _di_fake_print_error_file_ + f_return_status fake_print_error_file(const fl_color_context context, const f_status status, const f_string function, const f_string file_name, const f_string file_or_directory, const bool fallback) { + + if (status == f_file_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: failed to find file '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_directory_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: failed to find directory '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling ", function, file_name); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", function); + fl_color_print(f_standard_error, context.error, context.reset, "() for the %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_invalid_name) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Invalid %s name '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_out_of_memory) { + fl_color_print(f_standard_error, context.error, context.reset, "CRITICAL ERROR: Unable to allocate memory, while trying to access %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_number_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Overflow while trying to access %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_invalid_directory) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Invalid directory while trying to access %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_access_denied) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Access denied while trying to access %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (status == f_loop) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Loop while trying to access %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + return f_none; + } + + if (fake_print_error(context, status, function, f_false) == f_unknown && fallback) { + fl_color_print(f_standard_error, context.error, context.reset, "UNKNOWN ERROR: ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%d", status); + fl_color_print(f_standard_error, context.error, context.reset, ") occurred for %s '", file_or_directory); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", file_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + + return f_unknown; + } +#endif // _di_fake_print_error_file_ + +#ifndef _di_fake_print_error_parameter_missing_value_ + void fake_print_error_parameter_missing_value(const fl_color_context context, const f_string parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: The parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter); + fl_color_print_line(f_standard_error, context.error, context.reset, "' was specified, but no value was given."); + } +#endif // _di_fake_print_error_parameter_missing_value_ + +#ifndef _di_fake_print_error_parameter_too_many_ + void fake_print_error_parameter_too_many(const fl_color_context context, const f_string parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter); + fl_color_print_line(f_standard_error, context.error, context.reset, "' specified too many times."); + } +#endif // _di_fake_print_error_parameter_too_many_ + +#ifndef _di_fake_process_console_parameters_ + f_return_status fake_process_console_parameters(const f_console_arguments arguments, fake_data *data) { + f_status status = f_none; + + // @todo move as many of the inline error printing code into more general functions where possible to provide more accurate error reporting. + + { + const uint8_t total = 4; + + const uint8_t parameter_ids[] = { + fake_parameter_operation_build, + fake_parameter_operation_clean, + fake_parameter_operation_make, + fake_parameter_operation_skeleton, + }; + + const f_string parameter_names[] = { + fake_other_operation_build, + fake_other_operation_clean, + fake_other_operation_make, + fake_other_operation_skeleton, + }; + + for (uint8_t i = 0; i < total; i++) { + if (data->parameters[parameter_ids[i]].total > 1) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the operation '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' specified too many times."); + + return f_status_set_error(f_invalid_parameter); + } + } // for + } + + { + const uint8_t total = 2; + + const uint8_t parameter_ids[] = { + fake_parameter_process, + fake_parameter_settings, + }; + + const f_string parameter_names[] = { + fake_long_process, + fake_long_settings, + }; + + const f_string parameter_defaults[] = { + fake_default_process, + fake_default_settings, + }; + + const f_string_length parameter_default_lengths[] = { + fake_default_process_length, + fake_default_settings_length, + }; + + f_string_dynamic *parameter_values[] = { + &data->process, + &data->settings, + }; + + for (uint8_t i = 0; i < total; i++) { + if (data->parameters[parameter_ids[i]].result == f_console_result_found) { + fake_print_error_parameter_missing_value(data->context, parameter_names[i]); + return f_status_set_error(f_invalid_parameter); + } + else if (data->parameters[parameter_ids[i]].result == f_console_result_additional) { + if (data->parameters[parameter_ids[i]].total > 1) { + fake_print_error_parameter_too_many(data->context, parameter_names[i]); + return f_status_set_error(f_invalid_parameter); + } + + f_string_length location = data->parameters[parameter_ids[i]].additional.array[0]; + f_string_length length = strnlen(arguments.argv[location], f_console_max_size); + + if (length > 0) { + status = fl_string_append(arguments.argv[location], 0, length - 1, parameter_values[i]); + + if (f_status_is_error(status)) { + if (status == f_status_set_error(f_string_too_large)) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is too long."); + } + else { + fake_print_error(data->context, f_status_set_fine(status), "fl_string_append", f_true); + } + + return status; + } + } + + if (length == 0 || status == f_no_data) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' must not be empty and must not contain only whitespace."); + } + } + else if (parameter_default_lengths[i] > 0) { + f_macro_string_dynamic_resize(status, (*parameter_values[i]), parameter_default_lengths[i]); + + if (f_status_is_error(status)) { + fake_print_error(data->context, f_status_set_fine(status), "f_macro_string_dynamic_resize", f_true); + return status; + } + + memcpy(parameter_values[i]->string, parameter_defaults[i], parameter_default_lengths[i]); + parameter_values[i]->used = parameter_default_lengths[i]; + } + } // for + } + + if (data->parameters[fake_parameter_defines].result == f_console_result_found) { + fake_print_error_parameter_missing_value(data->context, fake_long_defines); + return f_status_set_error(f_invalid_parameter); + } + + { + const uint8_t total = 9; + + const uint8_t parameter_ids[] = { + fake_parameter_path_build, + fake_parameter_path_source_build, + fake_parameter_path_source_codes, + fake_parameter_path_source_common, + fake_parameter_path_source_data, + fake_parameter_path_source_documents, + fake_parameter_path_source_licenses, + fake_parameter_path_source_settings, + fake_parameter_path_work, + }; + + const f_string parameter_names[] = { + fake_long_path_build, + fake_long_path_source_build, + fake_long_path_source_codes, + fake_long_path_source_common, + fake_long_path_source_data, + fake_long_path_source_documents, + fake_long_path_source_licenses, + fake_long_path_source_settings, + fake_long_path_work, + }; + + const f_string parameter_defaults[] = { + fake_default_path_build, + fake_default_path_source_build, + fake_default_path_source_codes, + fake_default_path_source_common, + fake_default_path_source_data, + fake_default_path_source_documents, + fake_default_path_source_licenses, + fake_default_path_source_settings, + fake_default_path_work, + }; + + const f_string_length parameter_default_lengths[] = { + fake_default_path_build_length, + fake_default_path_source_build_length, + fake_default_path_source_codes_length, + fake_default_path_source_common_length, + fake_default_path_source_data_length, + fake_default_path_source_documents_length, + fake_default_path_source_licenses_length, + fake_default_path_source_settings_length, + fake_default_path_work_length, + }; + + const bool parameters_required[] = { + f_true, + f_true, + f_true, + f_false, + f_true, + f_false, + f_false, + f_false, + f_false, + }; + + f_string_dynamic *parameter_values[] = { + &data->path_build, + &data->path_source_build, + &data->path_source_codes, + &data->path_source_common, + &data->path_source_data, + &data->path_source_documents, + &data->path_source_licenses, + &data->path_source_settings, + &data->path_work, + }; + + for (uint8_t i = 0; i < total; i++) { + if (data->parameters[parameter_ids[i]].result == f_console_result_found) { + fake_print_error_parameter_missing_value(data->context, parameter_names[i]); + return f_status_set_error(f_invalid_parameter); + } + else if (data->parameters[parameter_ids[i]].result == f_console_result_additional) { + if (data->parameters[parameter_ids[i]].additional.used > 1) { + fake_print_error_parameter_too_many(data->context, parameter_names[i]); + return f_status_set_error(f_invalid_parameter); + } + + status = fl_console_parameter_to_string_dynamic_directory(arguments.argv[data->parameters[parameter_ids[i]].additional.array[0]], parameter_values[i]); + + if (f_status_is_error(status)) { + if (fake_print_error(data->context, f_status_set_fine(status), "fl_console_parameter_to_string_dynamic_directory", f_false) == f_unknown) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to process parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'."); + } + + return status; + } + } + else if (parameter_default_lengths[i] > 0) { + f_macro_string_dynamic_new(status, (*parameter_values[i]), parameter_default_lengths[i]); + + if (f_status_is_error(status)) { + if (fake_print_error(data->context, f_status_set_fine(status), "f_macro_string_dynamic_new", f_false) == f_unknown) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to load default for the parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'."); + } + + return status; + } + + memcpy(parameter_values[i]->string, parameter_defaults[i], parameter_default_lengths[i]); + parameter_values[i]->used = parameter_default_lengths[i]; + } + + if (parameter_values[i]->used > 0) { + struct stat directory_stat; + + memset(&directory_stat, 0, sizeof(struct stat)); + + status = f_file_stat(parameter_values[i]->string, &directory_stat); + + if (status == f_status_set_error(f_file_not_found)) status = f_status_set_error(f_directory_not_found); + + if (f_status_is_error(status)) { + if (f_status_set_fine(status) != f_directory_not_found || parameters_required[i]) { + fake_print_error_file(data->context, f_status_set_fine(status), "f_file_stat", parameter_values[i]->string, "directory", f_true); + return status; + } + } + } + else if (parameters_required[i]) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: No valid path for the (required) directory parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, parameter_names[i]); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' was found."); + + return f_status_set_error(f_directory_not_found); + } + } // for + } + + if (data->parameters[fake_parameter_defines].result == f_console_result_additional) { + status = fll_program_parameter_additional_rip_mash(" ", 1, arguments.argv, data->parameters[fake_parameter_defines].additional, &data->defines); + + if (f_status_is_error(status)) { + if (status == f_status_set_error(f_string_too_large)) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the (combined) parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, fake_long_defines); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' is too long."); + } + else { + fake_print_error(data->context, f_status_set_fine(status), "fll_program_parameter_additional_rip_mash", f_true); + } + + return status; + } + } + + if (data->parameters[fake_parameter_mode].result == f_console_result_found) { + fake_print_error_parameter_missing_value(data->context, fake_long_mode); + return f_status_set_error(f_invalid_parameter); + } + else if (data->parameters[fake_parameter_mode].result == f_console_result_additional) { + status = fll_program_parameter_additional_rip(arguments.argv, data->parameters[fake_parameter_mode].additional, &data->mode); + + if (f_status_is_error(status)) { + if (fake_print_error(data->context, f_status_set_fine(status), "fll_program_parameter_additional_rip", f_false) == f_unknown) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to process the parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, fake_long_mode); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'."); + } + + return status; + } + + f_array_length i = 0; + f_string_length j = 0; + f_string_length width_max = 0; + + for (; i < data->mode.used; i++) { + for (j = 0; j < data->mode.array[i].used; j++) { + width_max = data->mode.array[i].used - j; + + status = f_utf_is_word_dash_plus(data->mode.array[i].string + j, width_max); + + if (f_status_is_error(status)) { + if (fake_print_error(data->context, f_status_set_fine(status), "f_utf_is_word_dash_plus", f_false) == f_unknown) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to process the parameter '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, fake_long_mode); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'."); + } + + return status; + } + + if (status == f_false) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, fake_long_mode); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameters value '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", data->mode.array[i].string); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' contains non-word, non-dash, and non-plus characters."); + + return f_status_set_error(f_invalid_parameter); + } + } // for + } // for + } + + return f_none; + } +#endif // _di_fake_process_console_parameters_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/private-fake.h b/level_3/fake/c/private-fake.h new file mode 100644 index 0000000..47a0cbf --- /dev/null +++ b/level_3/fake/c/private-fake.h @@ -0,0 +1,120 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + */ +#ifndef _PRIVATE_fake_h +#define _PRIVATE_fake_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Find the build settings file, load it, validate it, and process it. + * + * @param data + * The program data. + * @param settings_data + * All settings data from the build settings file are loaded into this. + * These settings will have any specified mode property applied. + * + * @return + * f_none on success. + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_fake_load_settings_data_ + extern f_return_status fake_load_settings_data(const fake_data data, fake_settings_data *settings_data) f_gcc_attribute_visibility_internal; +#endif // _di_fake_load_settings_data_ + +/** + * Print generic error messages. + * + * @param context + * The color context. + * @param status + * The status code representing an error. + * @param function + * The name of the function where the error happened. + * @param fallback + * Set to f_true to print the fallback error message for unknown errors. + * + * @return + * f_none is returned on successful print of known errors. + * f_unknown is returned if the status code has no print message. + */ +#ifndef _di_fake_print_error_ + extern f_return_status fake_print_error(const fl_color_context context, const f_status status, const f_string function, const bool fallback) f_gcc_attribute_visibility_internal; +#endif // _di_fake_print_error_ + +/** + * Print file/directory error messages. + * + * @param context + * The color context. + * @param status + * The error status code to report on. + * @param function + * The function call that returned the error. + * @param file_name + * The name of the file or directory. + * @param file_or_directory + * A string that should be either 'file' or 'directory' used when printing the message. + * @param fallback + * Set to f_true to print the fallback error message for unknown errors. + * + * @return + * f_none is returned on successful print of known errors. + * f_unknown is returned if the status code has no print message. + */ +#ifndef _di_fake_print_error_file_ + extern f_return_status fake_print_error_file(const fl_color_context context, const f_status status, const f_string function, const f_string file_name, const f_string file_or_directory, const bool fallback) f_gcc_attribute_visibility_internal; +#endif // _di_fake_print_error_file_ + +/** + * Print an error message for when the parameter is missing its accompanying value. + * + * @param context + * The color context. + * @param parameter + * The parameter name. + */ +#ifndef _di_fake_print_error_parameter_missing_value_ + extern void fake_print_error_parameter_missing_value(const fl_color_context context, const f_string parameter) f_gcc_attribute_visibility_internal; +#endif // _di_fake_print_error_parameter_missing_value_ + +/** + * Print an error message for when the parameter is specified too many times. + * + * @param context + * The color context. + * @param parameter + * The parameter name. + */ +#ifndef _di_fake_print_error_parameter_too_many_ + extern void fake_print_error_parameter_too_many(const fl_color_context context, const f_string parameter) f_gcc_attribute_visibility_internal; +#endif // _di_fake_print_error_parameter_too_many_ + +/** + * Validate console arguments and print any relating error messages. + * + * @param arguments + * The parameters passed to the process. + * @param data + * The program data. + * + * @return + * f_none on success. + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_fake_process_console_parameters_ + extern f_return_status fake_process_console_parameters(const f_console_arguments arguments, fake_data *data) f_gcc_attribute_visibility_internal; +#endif // _di_validate_console_parameters_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_fake_h diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c new file mode 100644 index 0000000..ff48fa6 --- /dev/null +++ b/level_3/fake/c/private-make.c @@ -0,0 +1,12 @@ +#include +#include "private-fake.h" +#include "private-make.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h new file mode 100644 index 0000000..1907540 --- /dev/null +++ b/level_3/fake/c/private-make.h @@ -0,0 +1,19 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + */ +#ifndef _PRIVATE_make_h +#define _PRIVATE_make_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_make_h diff --git a/level_3/fake/c/private-skeleton.c b/level_3/fake/c/private-skeleton.c new file mode 100644 index 0000000..7e1d1ff --- /dev/null +++ b/level_3/fake/c/private-skeleton.c @@ -0,0 +1,12 @@ +#include +#include "private-fake.h" +#include "private-skeleton.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/private-skeleton.h b/level_3/fake/c/private-skeleton.h new file mode 100644 index 0000000..f9d2ff8 --- /dev/null +++ b/level_3/fake/c/private-skeleton.h @@ -0,0 +1,19 @@ +/** + * FLL - Level 3 + * + * Project: Featureless Make + * API Version: 0.5 + * Licenses: lgplv2.1 + */ +#ifndef _PRIVATE_skeleton_h +#define _PRIVATE_skeleton_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_skeleton_h diff --git a/level_3/fake/data/build/dependencies b/level_3/fake/data/build/dependencies new file mode 100644 index 0000000..7794fe9 --- /dev/null +++ b/level_3/fake/data/build/dependencies @@ -0,0 +1,20 @@ +f_type +f_status +f_memory +f_string +f_color +f_console +f_conversion +f_fss +f_file +f_print +f_utf +fl_color +fl_console +fl_file +fl_fss +fl_string +fl_utf +fll_fss +fll_execute +fll_program diff --git a/level_3/fake/data/build/process_post.sh b/level_3/fake/data/build/process_post.sh new file mode 100644 index 0000000..c961671 --- /dev/null +++ b/level_3/fake/data/build/process_post.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# license: lgpl-2.1 +# programmer: Kevin Day +# +# The purpose of this script is to provide an example for the post-process part of Fake. +# Despite being an example, it is intended to be actually used when using fake to build the fake project. +# +process_post_main(){ + local grab_next= + local do_color=normal + local i=0 + local p= + local t=0 + + # custom color codes. + local c_reset="\\033[0m" + local c_title="\\033[1;33m" + local c_error="\\033[1;31m" + local c_warning="\\033[0;33m" + local c_highlight="\\033[1;32m" + local c_notice="\\033[0;01m" + local c_important="\\033[0;32m" + local c_subtle="\\033[1;30m" + local c_prefix="\\" + + # the three supported parameters. + local operation= + local mode= + local defines= + + # grab all supported parameters, ignoring duplicates. + if [[ $# -gt 0 ]] ; then + t=$# + + while [[ $i -lt $t ]] ; do + let i=$i+1 + p="${!i}" + + if [[ $grab_next == "" ]] ; then + if [[ $p == "build" || $p == "clean" || $p == "make" || $p == "skeleton" ]] ; then + if [[ $operation == "" ]] ; then + operation=$p + fi + elif [[ $p == "-m" ]] ; then + grab_next="mode" + elif [[ $p == "-d" ]] ; then + grab_next="defines" + elif [[ $p == "+n" ]] ; then + if [[ $do_color == "normal" ]] ; then + do_color=none + fi + elif [[ $p == "+l" ]] ; then + if [[ $do_color == "normal" ]] ; then + do_color=light + fi + fi + else + if [[ $grab_next == "mode" ]] ; then + if [[ $mode == "" ]] ; then + mode=$p + fi + elif [[ $grab_next == "defines" ]] ; then + if [[ $defines == "" ]] ; then + defines=$p + fi + fi + + grab_next= + fi + done + + p= + fi + + if [[ $do_color == "light" ]] ; then + c_error="\\033[1;31m" + c_warning="\\033[0;31m" + c_title="\\033[1;34m" + c_highlight="\\033[0;34m" + c_notice="\\033[0;01m" + c_important="\\033[0;35m" + elif [[ $do_color == "none" ]] ; then + c_reset= + c_title= + c_error= + c_warning= + c_highlight= + c_notice= + c_important= + c_subtle= + c_prefix= + fi + + echo + echo -e "${c_title}Done Processing Operation: $c_reset$c_notice$operation$c_reset" + + if [[ $mode != "" ]] ; then + echo -e " Mode: $c_reset$c_notice$mode$c_reset" + fi + + if [[ $defines != "" ]] ; then + echo -e " Defines: $c_reset$c_notice$defines$c_reset" + fi + + echo + + # cleanup and return + unset process_post_main + return 0 +} + +# note: "$@" is necessary to preserve quoted arguments when passing though. +process_post_main "$@" diff --git a/level_3/fake/data/build/process_pre.sh b/level_3/fake/data/build/process_pre.sh new file mode 100644 index 0000000..563e2a3 --- /dev/null +++ b/level_3/fake/data/build/process_pre.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# license: lgpl-2.1 +# programmer: Kevin Day +# +# The purpose of this script is to provide an example for the pre-process part of Fake. +# Despite being an example, it is intended to be actually used when using fake to build the fake project. +# +process_pre_main(){ + local grab_next= + local do_color=normal + local i=0 + local p= + local t=0 + + # custom color codes. + local c_reset="\\033[0m" + local c_title="\\033[1;33m" + local c_error="\\033[1;31m" + local c_warning="\\033[0;33m" + local c_highlight="\\033[1;32m" + local c_notice="\\033[0;01m" + local c_important="\\033[0;32m" + local c_subtle="\\033[1;30m" + local c_prefix="\\" + + # the three supported parameters. + local operation= + local mode= + local defines= + + # grab all supported parameters, ignoring duplicates. + if [[ $# -gt 0 ]] ; then + t=$# + + while [[ $i -lt $t ]] ; do + let i=$i+1 + p="${!i}" + + if [[ $grab_next == "" ]] ; then + if [[ $p == "build" || $p == "clean" || $p == "make" || $p == "skeleton" ]] ; then + if [[ $operation == "" ]] ; then + operation=$p + fi + elif [[ $p == "-m" ]] ; then + grab_next="mode" + elif [[ $p == "-d" ]] ; then + grab_next="defines" + elif [[ $p == "+n" ]] ; then + if [[ $do_color == "normal" ]] ; then + do_color=none + fi + elif [[ $p == "+l" ]] ; then + if [[ $do_color == "normal" ]] ; then + do_color=light + fi + fi + else + if [[ $grab_next == "mode" ]] ; then + if [[ $mode == "" ]] ; then + mode=$p + fi + elif [[ $grab_next == "defines" ]] ; then + if [[ $defines == "" ]] ; then + defines=$p + fi + fi + + grab_next= + fi + done + + p= + fi + + if [[ $do_color == "light" ]] ; then + c_error="\\033[1;31m" + c_warning="\\033[0;31m" + c_title="\\033[1;34m" + c_highlight="\\033[0;34m" + c_notice="\\033[0;01m" + c_important="\\033[0;35m" + elif [[ $do_color == "none" ]] ; then + c_reset= + c_title= + c_error= + c_warning= + c_highlight= + c_notice= + c_important= + c_subtle= + c_prefix= + fi + + echo + echo -e "${c_title}Begin Processing Operation: $c_reset$c_notice$operation$c_reset" + + if [[ $mode != "" ]] ; then + echo -e " Mode: $c_reset$c_notice$mode$c_reset" + fi + + if [[ $defines != "" ]] ; then + echo -e " Defines: $c_reset$c_notice$defines$c_reset" + fi + + echo + + # cleanup and return + unset process_pre_main + return 0 +} + +# note: "$@" is necessary to preserve quoted arguments when passing though. +process_pre_main "$@" diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings new file mode 100644 index 0000000..eb339c4 --- /dev/null +++ b/level_3/fake/data/build/settings @@ -0,0 +1,35 @@ +# fss-0000 + +project_name fake +project_level 3 + +process_pre ./process_pre.sh +process_post ./process_post.sh + +version_major 0 +version_minor 5 +version_micro 0 + +build_compiler gcc +build_linker ar +build_libraries -lc +build_libraries_fll -lfll_execute -lfll_fss -lfll_program -lfl_utf -lfl_string -lfl_file -lfl_fss -lfl_console -lfl_color -lf_utf -lf_print -lf_file -lf_conversion -lf_console -lf_memory +build_libraries_fll-level -lfll_2 -lfll_1 -lfll_0 +build_libraries_fll-monolithic -lfll +build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-skeleton.c +build_sources_program main.c +build_sources_headers fake.h +build_sources_bash +build_sources_settings +build_shared yes +build_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE -lfake -- 1.8.3.1