From c028a388ff0fcf388cd1d8804ff41c7b85387af5 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 30 Aug 2020 21:10:34 -0500 Subject: [PATCH] Progress: featureless make. Continue work on the if operation section if conditions. Looks like I needed some functionality in f_file, currently incomplete. --- level_0/f_conversion/c/conversion.h | 2 +- level_0/f_file/c/file.c | 56 ++++++++ level_0/f_file/c/file.h | 76 ++++++++++- level_2/fll_program/c/program.h | 1 + level_3/byte_dump/c/byte_dump.c | 14 +- level_3/fake/c/private-make.c | 224 ++++++++++++++++++++++++------- level_3/fake/c/private-make.h | 58 ++++---- level_3/fake/documents/fakefile.txt | 6 + level_3/fake/specifications/fakefile.txt | 22 ++- 9 files changed, 375 insertions(+), 84 deletions(-) diff --git a/level_0/f_conversion/c/conversion.h b/level_0/f_conversion/c/conversion.h index ea32d6c..9903840 100644 --- a/level_0/f_conversion/c/conversion.h +++ b/level_0/f_conversion/c/conversion.h @@ -28,7 +28,7 @@ extern "C" { /** * Provide custom conversion scale limits based on selected type sizes. * - * Utilize the f_type_number_* defines to determine the expected sizes to use for the sxcales. + * Utilize the f_type_number_* defines to determine the expected sizes to use for the scales. * * 64-bit is the designed default. */ diff --git a/level_0/f_file/c/file.c b/level_0/f_file/c/file.c index b5f6e18..e932512 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -1180,6 +1180,50 @@ extern "C" { } #endif // _di_f_file_mode_from_string_ +#ifndef _di_f_file_mode_read_ + f_return_status f_file_mode_read(const f_string path, mode_t *mode) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + if (mode == 0) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + struct stat stat_file; + + memset(&stat_file, 0, sizeof(struct stat)); + + f_status status = private_f_file_stat(path, F_true, &stat_file); + if (F_status_is_error(status)) { + return status; + } + + *mode = stat_file.st_mode; + + return F_none; + } +#endif // _di_f_file_mode_read_ + +#ifndef _di_f_file_mode_read_at_ + f_return_status f_file_mode_read_at(const int at_id, const f_string path, mode_t *mode) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + if (mode == 0) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + struct stat stat_file; + + memset(&stat_file, 0, sizeof(struct stat)); + + f_status status = private_f_file_stat(path, F_true, &stat_file); + if (F_status_is_error(status)) { + return status; + } + + *mode = stat_file.st_mode; + + return F_none; + } +#endif // _di_f_file_mode_read_at_ + #ifndef _di_f_file_mode_set_ f_return_status f_file_mode_set(const f_string path, const mode_t mode) { #ifndef _di_level_0_parameter_checking_ @@ -1200,6 +1244,18 @@ extern "C" { } #endif // _di_f_file_mode_set_at_ +#ifndef _di_f_file_mode_determine_ + f_return_status f_file_mode_to_mode(const f_file_mode mode_from, const uint8_t mode_replace, mode_t *mode_to) { + #ifndef _di_level_0_parameter_checking_ + if (mode_to == 0) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + // @todo + + return F_none; + } +#endif // _di_f_file_mode_determine_ + #ifndef _di_f_file_name_base_ f_return_status f_file_name_base(const f_string path, const f_string_length length, f_string_dynamic *name_base) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index f2e961e..5507571 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -1169,7 +1169,7 @@ extern "C" { * @param mode_change * The file mode values to change. * @param mode_replace - * The mode modes that should be replaced instead of simply changed. + * The modes designated to be replaced instead of simply changed. * @param directory_is * Set to TRUE if the file is a directory, FALSE otherwise. * @param mode @@ -1248,6 +1248,8 @@ extern "C" { * * @fixme the possibilities are a bit extensive and this needs additional review; remove this fixme when this review is completed. * + * @fixme apparently "u+g" is valid such that the mode from the group (g) is applied to the user (u) mode. + * * @param string * A NULL terminated string designating the desired mode, following the above string syntax. * @param umask @@ -1273,6 +1275,58 @@ extern "C" { #endif // _di_f_file_mode_from_string_ /** + * Get the current file mode as an f_file_mode. + * + * @param path + * The path file name. + * @param mode + * The read file mode. + * + * @return + * F_none on success. + * F_access_denied (with error bit) if access to the file was denied. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if the file was not found. + * F_loop (with error bit) on loop error. + * F_memory_out (with error bit) if out of memory. + * F_name (with error bit) on path name error. + * F_number_overflow (with error bit) on overflow error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fstat() + */ +#ifndef _di_f_file_mode_read_ + extern f_return_status f_file_mode_read(const f_string path, mode_t *mode); +#endif // _di_f_file_mode_read_ + +/** + * Get the current file mode as an f_file_mode. + * + * @param at_id + * The parent directory, as an open directory file descriptor, in which path is relative to. + * @param path + * The path file name. + * @param mode + * The read file mode. + * + * @return + * F_none on success. + * F_access_denied (with error bit) if access to the file was denied. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if the file was not found. + * F_loop (with error bit) on loop error. + * F_memory_out (with error bit) if out of memory. + * F_name (with error bit) on path name error. + * F_number_overflow (with error bit) on overflow error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fstatat() + */ +#ifndef _di_f_file_mode_read_at_ + extern f_return_status f_file_mode_read_at(const int at_id, const f_string path, mode_t *mode); +#endif // _di_f_file_mode_read_at_ + +/** * Change mode of a given file at the specified path. * * This does not set mode based on umask(), be sure to apply umask if so desired. @@ -1337,6 +1391,26 @@ extern "C" { #endif // _di_f_file_mode_set_at_ /** + * Convert an f_file_mode type to a mode_t type. + * + * @param mode_from + * The file mode to convert from. + * @param mode_replace + * The modes designated to be replaced instead of simply changed. + * @param mode_to + * The determined mode. + * + * @return + * F_none on success. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_file_mode_from_string() + */ +#ifndef _di_f_file_mode_determine_ + extern f_return_status f_file_mode_to_mode(const f_file_mode mode_from, const uint8_t mode_replace, mode_t *mode_to); +#endif // _di_f_file_mode_determine_ + +/** * Get the base name of a file path. * * @param path diff --git a/level_2/fll_program/c/program.h b/level_2/fll_program/c/program.h index 4afe1cb..311bd18 100644 --- a/level_2/fll_program/c/program.h +++ b/level_2/fll_program/c/program.h @@ -315,6 +315,7 @@ extern "C" { #ifndef _di_fll_program_parameter_additional_rip_ extern f_return_status fll_program_parameter_additional_rip(const f_string *argv, const f_string_lengths additional, f_string_dynamics *destination); #endif // _di_fll_program_parameter_additional_rip_ + /** * Mash together all additional arguments associated with a given console parameter. * diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c index acafe36..993b831 100644 --- a/level_3/byte_dump/c/byte_dump.c +++ b/level_3/byte_dump/c/byte_dump.c @@ -256,14 +256,14 @@ extern "C" { if (data->parameters[byte_dump_parameter_first].result == f_console_result_additional && data->parameters[byte_dump_parameter_last].result == f_console_result_additional) { if (data->first > data->last) { - fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '"); - fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, byte_dump_long_first); - fl_color_print(f_type_error, data->context.error, data->context.reset, "' value cannot be greater than the parameter '"); - fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, byte_dump_long_last); - fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' value."); + fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '"); + fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, byte_dump_long_first); + fl_color_print(f_type_error, data->context.error, data->context.reset, "' value cannot be greater than the parameter '"); + fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, byte_dump_long_last); + fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' value."); - byte_dump_delete_data(data); - return F_status_set_error(status); + byte_dump_delete_data(data); + return F_status_set_error(status); } // store last position as a relative offset from first instead of an absolute position. diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 43ffc9a..04ff9b8 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -1538,6 +1538,9 @@ extern "C" { else if (operation_if == fake_make_operation_if_type_false_next) { operation_if = fake_make_operation_if_type_false; } + else if (operation_if == fake_make_operation_if_type_false_always_next) { + operation_if = fake_make_operation_if_type_false_always; + } fake_make_operate_validate(data, section->name, operation, *operation_name, arguments[i], &operation_if, data_make, section_stack, status); @@ -1547,6 +1550,10 @@ extern "C" { operation_if = fake_make_operation_if_type_else_true_next; continue; } + else if (operation_if == fake_make_operation_if_type_false_always) { + operation_if = fake_make_operation_if_type_else_false_next_always; + continue; + } else if (operation_if == fake_make_operation_if_type_else_false) { operation_if = 0; continue; @@ -1576,6 +1583,16 @@ extern "C" { break; } } + + if (operation_if == fake_make_operation_if_type_false) { + operation_if = fake_make_operation_if_type_else_true_next; + } + else if (operation_if == fake_make_operation_if_type_false_always) { + operation_if = fake_make_operation_if_type_else_false_next_always; + } + else if (operation_if == fake_make_operation_if_type_else_false) { + operation_if = 0; + } } if (operation_if == fake_make_operation_if_type_else_true || operation_if == fake_make_operation_if_type_else_false) { @@ -1587,8 +1604,8 @@ extern "C" { else if (operation_if == fake_make_operation_if_type_true) { operation_if = fake_make_operation_if_type_else_false_next; } - else if (operation_if == fake_make_operation_if_type_false) { - operation_if = fake_make_operation_if_type_else_true_next; + else if (operation_if == fake_make_operation_if_type_false_always) { + operation_if = fake_make_operation_if_type_else_false_next_always; } if (F_status_is_error(*status)) { @@ -1666,8 +1683,8 @@ extern "C" { *status = F_status_set_error(F_failure); } - // ensure an error is returned during recursion if the last known section operation failed. - if (success == F_false && F_status_is_fine(*status)) { + // ensure an error is returned during recursion if the last known section operation failed, except for the main operation. + if (success == F_false && F_status_is_fine(*status) && section_stack->used > 1) { *status = F_status_set_error(F_failure); } @@ -1830,7 +1847,7 @@ extern "C" { } if (operation == fake_make_operation_type_else) { - if (*operation_if == fake_make_operation_if_type_else_false_next) { + if (*operation_if == fake_make_operation_if_type_else_false_next || *operation_if == fake_make_operation_if_type_else_false_next_always) { *operation_if = fake_make_operation_if_type_else_false; } else if (*operation_if != fake_make_operation_if_type_else_true_next) { @@ -1959,8 +1976,6 @@ extern "C" { return; } - // @todo: these conversions need to be UTF-8 friendly. - if (*operation_if == fake_make_operation_if_type_if_success) { if (success) { *operation_if = fake_make_operation_if_type_true_next; @@ -1985,7 +2000,49 @@ extern "C" { if (*operation_if == fake_make_operation_if_type_if_mode) { *operation_if = fake_make_operation_if_type_false_next; - // @todo: handle first mode parameter and then filepath parameters. + + bool is = F_false; + + if (fl_string_dynamic_compare_string(fake_make_operation_argument_is, arguments.array[1], fake_make_operation_argument_is_length) == F_equal_to) { + is = F_true; + } + + f_file_mode mode_rule = 0; + mode_t mode_match = 0; + uint8_t replace = 0; + + // @fixme: mode_rule needs to be converted to a mode_t. + *status = fake_make_get_id_mode(data, data_make->print, arguments.array[1], &mode_rule, &replace); + if (F_status_is_error(*status)) return; + + mode_t mode_file = 0; + + for (f_array_length i = 2; i < arguments.used; i++, mode_file = 0) { + + *status = f_file_mode_read(arguments.array[i].string, &mode_file); + if (F_status_is_error(*status)) { + fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_read", arguments.array[i].string, "get mode of", F_true, F_true, data_make->print); + break; + } + + if (is) { + if (mode_match == mode_file) { + // @todo success + } + else { + // @todo failure + } + } + else { + if (mode_match & mode_file) { + // @todo success + } + else { + // @todo failure + } + } + } // for + return; } @@ -2055,20 +2112,18 @@ extern "C" { if (F_status_is_error(*status)) return; mode_t mode = 0; - - struct stat stat_file; + mode_t mode_file = 0; for (f_array_length i = 1; i < arguments.used; i++) { mode = 0; - memset(&stat_file, 0, sizeof(struct stat)); - *status = f_file_stat(arguments.array[i].string, F_true, &stat_file); + *status = f_file_mode_read(arguments.array[i].string, &mode_file); if (F_status_is_error(*status)) { - fake_print_message_file(data, F_status_set_fine(*status), "f_file_stat", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); + fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_read", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); break; } - *status = f_file_mode_determine(stat_file.st_mode, mode_rule, replace, f_macro_file_type_is_directory(stat_file.st_mode), &mode); + *status = f_file_mode_determine(mode_file, mode_rule, replace, f_macro_file_type_is_directory(mode_file), &mode); if (F_status_is_error(*status)) { fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_determine", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); break; @@ -2100,21 +2155,19 @@ extern "C" { if (F_status_is_error(*status)) return; mode_t mode = 0; - - struct stat stat_file; + mode_t mode_file = 0; for (f_array_length i = 1; i < arguments.used; i++) { // @todo recursive. mode = 0; - memset(&stat_file, 0, sizeof(struct stat)); - *status = f_file_stat(arguments.array[i].string, F_true, &stat_file); + *status = f_file_mode_read(arguments.array[i].string, &mode_file); if (F_status_is_error(*status)) { - fake_print_message_file(data, F_status_set_fine(*status), "f_file_stat", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); + fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_read", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); break; } - *status = f_file_mode_determine(stat_file.st_mode, mode_rule, replace, f_macro_file_type_is_directory(stat_file.st_mode), &mode); + *status = f_file_mode_determine(mode_file, mode_rule, replace, f_macro_file_type_is_directory(mode_file), &mode); if (F_status_is_error(*status)) { fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_determine", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print); break; @@ -2695,7 +2748,6 @@ extern "C" { *status = F_status_set_error(status_file); } else if (F_status_is_error(status_file)) { - // @todo: print warning file. fake_print_message_file(data, *status, "f_file_is", data.file_data_build_fakefile.string, "find", F_true, F_true, data_make->print); *status = status_file; } @@ -2850,7 +2902,7 @@ extern "C" { return; } - if (*operation_if == fake_make_operation_if_type_true || *operation_if == fake_make_operation_if_type_false) { + if (*operation_if == fake_make_operation_if_type_true || *operation_if == fake_make_operation_if_type_false || *operation_if == fake_make_operation_if_type_false_always) { if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { printf("%c", f_string_eol[0]); fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: Must not be used inside an ", data_make->print.prefix); @@ -2864,7 +2916,7 @@ extern "C" { return; } - if (*operation_if != fake_make_operation_if_type_else_true_next && *operation_if != fake_make_operation_if_type_else_false_next) { + if (*operation_if != fake_make_operation_if_type_else_true_next && *operation_if != fake_make_operation_if_type_else_false_next && *operation_if != fake_make_operation_if_type_else_false_next_always) { if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { printf("%c", f_string_eol[0]); fl_color_print_line(data_make->print.to, data_make->print.context, data.context.reset, "%s: Has no preceding if condition.", data_make->print.prefix); @@ -2987,7 +3039,7 @@ extern "C" { } if (operation == fake_make_operation_type_if) { - if (*operation_if == fake_make_operation_if_type_true || *operation_if == fake_make_operation_if_type_false) { + if (*operation_if == fake_make_operation_if_type_true || *operation_if == fake_make_operation_if_type_false || *operation_if == fake_make_operation_if_type_false_always) { if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { printf("%c", f_string_eol[0]); fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: Must not be used after another '", data_make->print.prefix); @@ -3065,7 +3117,7 @@ extern "C" { 3, 2, 2, - 3, + 4, 3, 1, }; @@ -3088,7 +3140,7 @@ extern "C" { } *status = F_status_set_error(F_failure); - *operation_if = fake_make_operation_if_type_false_next; // @todo: there really needs to be a fail_always to not execute either block on these kinds of errors. + *operation_if = fake_make_operation_if_type_false_always_next; return; } @@ -3102,7 +3154,7 @@ extern "C" { } *status = F_status_set_error(F_failure); - *operation_if = fake_make_operation_if_type_false_next; // @todo: there really needs to be a fail_always to not execute either block on these kinds of errors. + *operation_if = fake_make_operation_if_type_false_always_next; } return; @@ -3110,13 +3162,28 @@ extern "C" { if (*operation_if == fake_make_operation_if_type_if_mode || *operation_if == fake_make_operation_if_type_if_owner || *operation_if == fake_make_operation_if_type_if_group || *operation_if == fake_make_operation_if_type_if_is || *operation_if == fake_make_operation_if_type_if_exists) { if (*operation_if == fake_make_operation_if_type_if_mode) { + + if (fl_string_dynamic_compare_string(fake_make_operation_argument_is, arguments.array[1], fake_make_operation_argument_is_length) == F_equal_to_not) { + if (fl_string_dynamic_compare_string(fake_make_operation_argument_has, arguments.array[1], fake_make_operation_argument_has_length) == F_equal_to_not) { + if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { + printf("%c", f_string_eol[0]); + fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: Unsupported mode type '", data_make->print.prefix); + fl_color_print(data_make->print.to, data.context.notable, data.context.reset, "%s", arguments.array[1].string); + fl_color_print_line(data_make->print.to, data_make->print.context, data.context.reset, "'."); + } + + *status = F_status_set_error(F_failure); + return; + } + } + f_file_mode mode_rule = 0; uint8_t replace = 0; - *status = fake_make_get_id_mode(data, data_make->print, arguments.array[1], &mode_rule, &replace); + *status = fake_make_get_id_mode(data, data_make->print, arguments.array[2], &mode_rule, &replace); if (F_status_is_error(*status)) return; - i = 2; + i = 3; } if (*operation_if == fake_make_operation_if_type_if_owner) { @@ -3138,14 +3205,10 @@ extern "C" { } if (*operation_if == fake_make_operation_if_type_if_is) { - // block = 0x1 (0000 0001) - // character = 0x2 (0000 0010) - // directory = 0x4 (0000 0100) - // fifo = 0x8 (0000 1000) - // link = 0x10 (0001 0000) - // regular = 0x20 (0010 0000) - // socket = 0x40 (0100 0000) - // invalid = 0x80 (1000 0000) + // block = 0x1 (0000 0001) link = 0x10 (0001 0000) + // character = 0x2 (0000 0010) regular = 0x20 (0010 0000) + // directory = 0x4 (0000 0100) socket = 0x40 (0100 0000) + // fifo = 0x8 (0000 1000) invalid = 0x80 (1000 0000) uint8_t type_file = 0; for (i = 1; i < arguments.used; i++) { @@ -3189,7 +3252,7 @@ extern "C" { if (type_file & 0x80) { *status = F_status_set_error(F_failure); - *operation_if = fake_make_operation_if_type_false_next; // @todo: there really needs to be a fail_always to not execute either block on these kinds of errors. + *operation_if = fake_make_operation_if_type_false_always_next; return; } @@ -3206,7 +3269,7 @@ extern "C" { if (F_status_is_error(status_file)) { fake_print_message_section_operation_path_outside(data, F_status_set_fine(status_file), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string, data_make->print); - *operation_if = fake_make_operation_if_type_false_next; // @todo: there really needs to be a fail_always to not execute either block on these kinds of errors. + *operation_if = fake_make_operation_if_type_false_always_next; if (F_status_is_fine(*status)) { if (F_status_set_fine(status_file) == F_false) { @@ -3228,7 +3291,7 @@ extern "C" { if (F_status_is_error(status_file)) { fake_print_message_file(data, F_status_set_fine(status_file), "f_file_exists", arguments.array[i].string, "find", F_true, F_true, data_make->print); - *operation_if = fake_make_operation_if_type_false_next; // @todo: there really needs to be a fail_always to not execute either block on these kinds of errors. + *operation_if = fake_make_operation_if_type_false_always_next; if (F_status_is_fine(*status)) { *status = F_status_set_error(status_file); @@ -3242,17 +3305,80 @@ extern "C" { } if (*operation_if == fake_make_operation_if_type_if_defined) { - // @todo: handle first parameter/environment parameter and then define name parameters. + if (fl_string_dynamic_compare_string(fake_make_operation_argument_environment, arguments.array[1], fake_make_operation_argument_environment_length) == F_equal_to_not) { + if (fl_string_dynamic_compare_string(fake_make_operation_argument_parameter, arguments.array[1], fake_make_operation_argument_parameter_length) == F_equal_to_not) { + if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { + printf("%c", f_string_eol[0]); + fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: Unsupported define type '", data_make->print.prefix); + fl_color_print(data_make->print.to, data.context.notable, data.context.reset, "%s", arguments.array[1].string); + fl_color_print_line(data_make->print.to, data_make->print.context, data.context.reset, "'."); + } + + *status = F_status_set_error(F_failure); + } + } + return; } - // @todo: for each of these, handle converting all arguments to integers/numbers and then processing conditions in order. - //fake_make_operation_if_type_if_equal - //fake_make_operation_if_type_if_equal_not (needs to be applied to all, so use separate logic block.) - //fake_make_operation_if_type_if_greater - //fake_make_operation_if_type_if_greater_equal - //fake_make_operation_if_type_if_less - //fake_make_operation_if_type_if_less_equal + if (*operation_if == fake_make_operation_if_type_if_equal || *operation_if == fake_make_operation_if_type_if_equal_not) { + // nothing to validate. + return; + } + + if (*operation_if == fake_make_operation_if_type_if_greater || *operation_if == fake_make_operation_if_type_if_greater_equal || *operation_if == fake_make_operation_if_type_if_less || *operation_if == fake_make_operation_if_type_if_less_equal) { + f_status status_number = F_none; + f_string_range range = f_string_range_initialize; + f_number_unsigned number = 0; + bool is_negative = F_false; + + // @fixme there needs to handle converting numbers with decimals (like 1.01), perhaps operate on them as strings or provide a special processor. + for (i = 1; i < arguments.used; i++, status_number = F_none) { + if (arguments.array[i].used) { + range.start = 0; + range.stop = arguments.array[i].used - 1; + + if (arguments.array[i].string[0] == '+') { + range.start = 1; + } + else if (arguments.array[i].string[0] == '-') { + range.start = 1; + is_negative = F_true; + } + + if (range.start > range.stop) { + status_number = F_status_set_error(F_failure); + } + else { + status_number = fl_conversion_string_to_number_unsigned(arguments.array[i].string, &number, range); + } + } + else { + status_number = F_status_set_error(F_failure); + } + + if (F_status_is_error(status_number)) { + *status = F_status_set_error(F_failure); + + if (data.verbosity != fake_verbosity_quiet && data_make->print.to) { + printf("%c", f_string_eol[0]); + + if (number > f_type_number_size_unsigned) { + fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: The number '", data_make->print.prefix); + fl_color_print(data_make->print.to, data.context.notable, data.context.reset, "%c%s", arguments.array[i].string); + fl_color_print_line(data_make->print.to, data_make->print.context, data.context.reset, "' may only be between the ranges -%llu to %llu.", f_type_number_size_unsigned, f_type_number_size_unsigned); + } + else { + fl_color_print(data_make->print.to, data_make->print.context, data.context.reset, "%s: Invalid or unsupported number provided '", data_make->print.prefix); + fl_color_print(data_make->print.to, data.context.notable, data.context.reset, "%s", arguments.array[i].string); + fl_color_print_line(data_make->print.to, data_make->print.context, data.context.reset, "'."); + } + } + } + } // for + + return; + } } } @@ -3262,7 +3388,7 @@ extern "C" { } *status = F_status_set_error(F_failure); - *operation_if = fake_make_operation_if_type_false_next; + *operation_if = fake_make_operation_if_type_false_always_next; return; } diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index f39e5ba..19f4367 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -59,7 +59,6 @@ extern "C" { #define fake_make_setting_return_length 6 #endif // _di_fake_make_setting_ -// @todo "operate" should use a call stack, but do not allow recursive calls (check to see if named operation is already on the call stack). #ifndef _di_fake_make_operation_ #define fake_make_operation_archive "archive" #define fake_make_operation_build "build" @@ -152,29 +151,37 @@ extern "C" { #define fake_make_operation_total 28 - #define fake_make_operation_argument_failure "failure" - #define fake_make_operation_argument_file "file" - #define fake_make_operation_argument_directory "directory" - #define fake_make_operation_argument_error "error" - #define fake_make_operation_argument_exit "exit" - #define fake_make_operation_argument_ignore "ignore" - #define fake_make_operation_argument_point "point" - #define fake_make_operation_argument_recursive "recursive" - #define fake_make_operation_argument_success "success" - #define fake_make_operation_argument_target "target" - #define fake_make_operation_argument_warn "warn" - - #define fake_make_operation_argument_failure_length 7 - #define fake_make_operation_argument_file_length 4 - #define fake_make_operation_argument_directory_length 9 - #define fake_make_operation_argument_error_length 5 - #define fake_make_operation_argument_exit_length 4 - #define fake_make_operation_argument_ignore_length 6 - #define fake_make_operation_argument_point_length 5 - #define fake_make_operation_argument_recursive_length 9 - #define fake_make_operation_argument_success_length 7 - #define fake_make_operation_argument_target_length 6 - #define fake_make_operation_argument_warn_length 4 + #define fake_make_operation_argument_environment "environment" + #define fake_make_operation_argument_failure "failure" + #define fake_make_operation_argument_file "file" + #define fake_make_operation_argument_directory "directory" + #define fake_make_operation_argument_error "error" + #define fake_make_operation_argument_exit "exit" + #define fake_make_operation_argument_has "has" + #define fake_make_operation_argument_ignore "ignore" + #define fake_make_operation_argument_is "is" + #define fake_make_operation_argument_parameter "parameter" + #define fake_make_operation_argument_point "point" + #define fake_make_operation_argument_recursive "recursive" + #define fake_make_operation_argument_success "success" + #define fake_make_operation_argument_target "target" + #define fake_make_operation_argument_warn "warn" + + #define fake_make_operation_argument_environment_length 11 + #define fake_make_operation_argument_failure_length 7 + #define fake_make_operation_argument_file_length 4 + #define fake_make_operation_argument_directory_length 9 + #define fake_make_operation_argument_error_length 5 + #define fake_make_operation_argument_exit_length 4 + #define fake_make_operation_argument_has_length 3 + #define fake_make_operation_argument_ignore_length 6 + #define fake_make_operation_argument_is_length 2 + #define fake_make_operation_argument_parameter_length 9 + #define fake_make_operation_argument_point_length 5 + #define fake_make_operation_argument_recursive_length 9 + #define fake_make_operation_argument_success_length 7 + #define fake_make_operation_argument_target_length 6 + #define fake_make_operation_argument_warn_length 4 #define fake_make_operation_argument_if_defined "defined" #define fake_make_operation_argument_if_equal "==" @@ -211,9 +218,12 @@ extern "C" { enum { fake_make_operation_if_type_else_false = 1, fake_make_operation_if_type_else_false_next, + fake_make_operation_if_type_else_false_next_always, fake_make_operation_if_type_else_true, fake_make_operation_if_type_else_true_next, fake_make_operation_if_type_false, + fake_make_operation_if_type_false_always, + fake_make_operation_if_type_false_always_next, fake_make_operation_if_type_false_next, fake_make_operation_if_type_if_defined, fake_make_operation_if_type_if_equal, diff --git a/level_3/fake/documents/fakefile.txt b/level_3/fake/documents/fakefile.txt index e2c6941..7c0ccbf 100644 --- a/level_3/fake/documents/fakefile.txt +++ b/level_3/fake/documents/fakefile.txt @@ -153,31 +153,37 @@ Fakefile Documentation: compare all parameters to be equal. requires 2 or more after the "==". for example, "if == 'a' 'b' 'c' 'd'" would test: 'a' == 'b' && 'b' == 'c' && 'c' == 'd'. + this performs only string-based comparisons. > "left string" "right string"\: compare "left" to "right" for greater than. requires 2 or more after the ">". for example, "if > 0 1 2 3" would test: 0 > 1 && 1 > 2 && 2 > 3. + this performs only number-based comparisons. < "left string" "right string"\: compare "left" to "right" for less than. requires 2 or more after the ">". for example, "if < 0 1 2 3" would test: 0 < 1 && 1 < 2 && 2 < 3. + this performs only number-based comparisons. >= "left string" "right string"\: compare "left" to "right" for greater than or equal to. requires 2 or more after the ">=". for example, "if >= 0 1 2 3" would test: 0 >= 1 && 1 >= 2 && 2 >= 3. + this performs only number-based comparisons. <= "left string" "right string"\: compare "left" to "right" for less than or equal to. requires 2 or more after the ">=". for example, "if <= 0 1 2 3" would test: 0 <= 1 && 1 <= 2 && 2 <= 3. + this performs only number-based comparisons. <> "left" "right"\: compare all parameters to be not equal. requires 2 or more after the "==". for example, "if <> 'a' 'b' 'c'" would test: 'a' <> 'b' && 'b' <> 'c' && 'a' <> 'c'. + this performs only string-based comparisons. exists "file path"\: test if file exists. diff --git a/level_3/fake/specifications/fakefile.txt b/level_3/fake/specifications/fakefile.txt index 4465a0d..92591d4 100644 --- a/level_3/fake/specifications/fakefile.txt +++ b/level_3/fake/specifications/fakefile.txt @@ -77,7 +77,7 @@ Fakefile Specification: - ==: Two or more Content. - >: Two or more Content. - <: Two or more Content. - - <=: Two or more Content. + - >=: Two or more Content. - <=: Two or more Content. - <>: Two or more Content. - defined: First Content is either "parameter" or "environment". Second or more Content are valid names, such that for "parameter" it is a valid IKI name and for "environment" it is a valid environment variable name. @@ -86,4 +86,22 @@ Fakefile Specification: - is: First Content is a list of "block", "character", "directory", "fifo", "link", "regular" , or "socket" followed by "for" and then the Remaining Content that are paths to files. - mode: First Content is either "is" or "has". Second Content is a valid file mode. Third or more Content are paths to files. - owner: First Content is the name of an owner. Second or more Content are paths to files. - - succeed: has no other Content. + - success: has no other Content. + + The "if" Section Operation conditions and numbers\: + The numbers may be represented in any of the forms: + 1) decimal: all numbers without a base-type prefix are of base-type 10, referred to as decimal. + 2) binary: all numbers with the prefix "0b" (uppercase or lowercase 'b') are of base-type 2, referred to as binary. + 3) octal: all numbers with the prefix "0o" (that is zero followed by the letter o, uppercase or lowercase 'o') are of base-type 8, referred to as octal. + 4) duodecimal: all numbers with the prefix "0d" (uppercase or lowercase 'd') are of base-type 12, referred to as duodecimal. + 5) hexadecimal: all numbers with the prefix "0x" (uppercase or lowercase 'x') are of base-type 16, referred to as hexadecimal. + + (At this time) The numbers may be of a max value of 2^64, or 18446744073709551615, positive or negative. + (At this time) The numbers may only be whole numbers. + Note: there are plans to impose no limits on the number size or any decimal values, but this requires significant work is not to be implemented at this time. + + Only the following "if" Section Operation conditions operate using these numbers: + - > + - < + - >= + - <= -- 1.8.3.1