From ebddf3f27c256b2cef608093fcc88561f9e08ef4 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 31 May 2021 17:43:44 -0500 Subject: [PATCH] Update: Redesign FSS Identify to be more consistent with FSS Read and FSS Write programs. This is not strictly required, but I believe making it as closely consistent with how FSS Read and FSS Write operate makes a lot of sense. The FSS Identify and FSS Read/Write programs operate differently and not everything can be the same. Summary of Redesign: - The "name" and "type" are now renamed to "Object" and "Content". - The parameter "-n/--name" is now "-o/--object". - The parameter "-t/--type" is now "-c/--content". - The parameter "-T/--total" is now "-t/--total". - Add new parameter "-n/--name" that accepts a name to filter by (This selects an Object just like it does in FSS Read/Write). - Add additional documentation to the "-h/--help" parameter message. - The "-t/--total" parameter should could across all files and not the individual files/pipe (this provides a single total). --- level_3/fss_identify/c/fss_identify.c | 113 ++++++++++++++++++++------ level_3/fss_identify/c/fss_identify.h | 30 ++++--- level_3/fss_identify/c/private-common.c | 9 ++ level_3/fss_identify/c/private-common.h | 17 ++++ level_3/fss_identify/c/private-fss_identify.c | 34 ++++++-- 5 files changed, 160 insertions(+), 43 deletions(-) diff --git a/level_3/fss_identify/c/fss_identify.c b/level_3/fss_identify/c/fss_identify.c index c5e4a45..fbc383e 100644 --- a/level_3/fss_identify/c/fss_identify.c +++ b/level_3/fss_identify/c/fss_identify.c @@ -23,12 +23,13 @@ extern "C" { fprintf(output.stream, "%c", f_string_eol_s[0]); - fll_program_print_help_option(output, context, fss_identify_short_name, fss_identify_long_name, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the Identifier name."); - fll_program_print_help_option(output, context, fss_identify_short_type, fss_identify_long_type, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the Identifier type."); + fll_program_print_help_option(output, context, fss_identify_short_content, fss_identify_long_content, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the Identifier content (the 4-digit hexidecimal type code)."); + fll_program_print_help_option(output, context, fss_identify_short_object, fss_identify_long_object, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Identifier object (the name)."); fprintf(output.stream, "%c", f_string_eol_s[0]); fll_program_print_help_option(output, context, fss_identify_short_line, fss_identify_long_line, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Identifier at the given line."); + fll_program_print_help_option(output, context, fss_identify_short_name, fss_identify_long_name, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); fll_program_print_help_option(output, context, fss_identify_short_total, fss_identify_long_total, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the total Identifiers found."); fll_program_print_help_usage(output, context, fss_identify_name, "filename(s)"); @@ -40,9 +41,9 @@ extern "C" { fprintf(output.stream, "%c", f_string_eol_s[0]); fprintf(output.stream, " If neither the "); - f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_object); fprintf(output.stream, " nor ", f_string_eol_s[0]); - f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_type); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_content); fprintf(output.stream, " are specified, then the default behavior is to print both.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); @@ -50,13 +51,22 @@ extern "C" { fprintf(output.stream, " When specifying the "); f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_total); fprintf(output.stream, " parameter, neither the "); - f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_object); fprintf(output.stream, " nor the "); - f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_type); + f_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_content); fprintf(output.stream, " parameter may be specified.%c", f_string_eol_s[0]); fprintf(output.stream, "%c", f_string_eol_s[0]); + fprintf(output.stream, " An FSS file is identified by the following format: '"); + f_color_print(output.stream, context.set.notable, "# Object-Content"); + fprintf(output.stream, "' where the Object, is a machine-name representing the name and may only consist of \"word\" characters and the Content is a 4-digit hexidecimal number representing a particular variant of the Object.%c", f_string_eol_s[0]); + fprintf(output.stream, " This identifier, if provided, must exist on the first line in a file and must begin with the pound character: '#'.%c", f_string_eol_s[0]); + fprintf(output.stream, " Whitespace must follow this pound character.%c", f_string_eol_s[0]); + fprintf(output.stream, " There may be multiple Object and Content pairs, separated by whitspace, such as: \"# fss-0002 fss-0000 iki-0002\".%c", f_string_eol_s[0]); + + fprintf(output.stream, "%c", f_string_eol_s[0]); + return F_none; } #endif // _di_fss_identify_print_help_ @@ -150,9 +160,9 @@ extern "C" { if (F_status_is_error_not(status)) { if (main->parameters[fss_identify_parameter_line].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter ", fll_error_print_error); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_line); - f_color_print(main->error.to.stream, main->context.set.error, "' requires a positive number.%c", f_string_eol_s[0]); + f_color_print(main->error.to.stream, main->context.set.error, " requires a positive number.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); } @@ -169,26 +179,83 @@ extern "C" { } if (F_status_is_error_not(status) && main->parameters[fss_identify_parameter_total].result == f_console_result_found) { - if (main->parameters[fss_identify_parameter_name].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); - f_color_print(main->error.to.stream, main->context.set.error, "' parameter with the '"); + if (main->parameters[fss_identify_parameter_object].result == f_console_result_found) { + f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the ", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_object); + f_color_print(main->error.to.stream, main->context.set.error, " parameter with the "); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_total); - f_color_print(main->error.to.stream, main->context.set.error, "' parameter.%c", f_string_eol_s[0]); + f_color_print(main->error.to.stream, main->context.set.error, " parameter.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); } - else if (main->parameters[fss_identify_parameter_type].result == f_console_result_found) { - f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the '", fll_error_print_error); - f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_type); - f_color_print(main->error.to.stream, main->context.set.error, "' parameter with the '"); + else if (main->parameters[fss_identify_parameter_content].result == f_console_result_found) { + f_color_print(main->error.to.stream, main->context.set.error, "%sCannot specify the ", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_content); + f_color_print(main->error.to.stream, main->context.set.error, " parameter with the "); f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_total); - f_color_print(main->error.to.stream, main->context.set.error, "' parameter.%c", f_string_eol_s[0]); + f_color_print(main->error.to.stream, main->context.set.error, " parameter.%c", f_string_eol_s[0]); status = F_status_set_error(F_parameter); } } + if (F_status_is_error_not(status)) { + if (main->parameters[fss_identify_parameter_name].result == f_console_result_found) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter ", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); + f_color_print(main->error.to.stream, main->context.set.error, " requires a string.%c", f_string_eol_s[0]); + + status = F_status_set_error(F_parameter); + } + else if (main->parameters[fss_identify_parameter_name].result == f_console_result_additional) { + const f_array_length_t index = main->parameters[fss_identify_parameter_name].values.array[main->parameters[fss_identify_parameter_name].values.used - 1]; + const f_array_length_t length = strnlen(arguments.argv[index], f_console_parameter_size); + const f_string_range_t range = macro_f_string_range_t_initialize(length); + + if (length == 0) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe parameter ", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); + f_color_print(main->error.to.stream, main->context.set.error, " does not allow zero length strings.%c", f_string_eol_s[0]); + + status = F_status_set_error(F_parameter); + } + else { + status = f_string_dynamic_resize(length, &data.name); + + if (F_status_is_error(status)) { + fll_error_print(main->error, F_status_set_fine(status), "f_utf_is_word", F_true); + } + } + + if (F_status_is_error_not(status)) { + + for (f_array_length_t i = range.start; i <= range.stop; ++i) { + + status = f_utf_is_word(arguments.argv[index] + i, length, F_true); + + if (F_status_is_error(status)) { + fll_error_print(main->error, F_status_set_fine(status), "f_utf_is_word", F_true); + + break; + } + else if (status == F_false) { + f_color_print(main->error.to.stream, main->context.set.error, "%sThe value '", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s", arguments.argv[index]); + f_color_print(main->error.to.stream, main->context.set.error, "' for the parameter ", fll_error_print_error); + f_color_print(main->error.to.stream, main->context.set.notable, "%s%s", f_console_symbol_long_enable_s, fss_identify_long_name); + f_color_print(main->error.to.stream, main->context.set.error, " may only contain word characters.%c", f_string_eol_s[0]); + + status = F_status_set_error(F_parameter); + + break; + } + + data.name.string[data.name.used++] = arguments.argv[index][i]; + } // for + } + } + } + f_string_range_t range = f_string_range_t_initialize; f_string_dynamic_t buffer = f_string_dynamic_t_initialize; f_file_t file = f_file_t_initialize; @@ -239,13 +306,8 @@ extern "C" { f_string_dynamic_resize(0, &buffer); if (F_status_is_error_not(status)) { - if (main->parameters[fss_identify_parameter_line].result == f_console_result_additional) { - - if (data.current < data.line) { - if (main->parameters[fss_identify_parameter_total].result == f_console_result_found) { - fprintf(main->output.stream, "%c%c", f_string_ascii_0_s[0], f_string_eol_s[0]); - } - } + if (main->parameters[fss_identify_parameter_total].result == f_console_result_found) { + fprintf(main->output.stream, "%llu%c", data.total, f_string_eol_s[0]); } } @@ -256,6 +318,7 @@ extern "C" { } } + fss_identify_data_delete(&data); fss_identify_main_delete(main); return status; diff --git a/level_3/fss_identify/c/fss_identify.h b/level_3/fss_identify/c/fss_identify.h index 582e213..2fae61d 100644 --- a/level_3/fss_identify/c/fss_identify.h +++ b/level_3/fss_identify/c/fss_identify.h @@ -59,15 +59,17 @@ extern "C" { #endif // _di_fss_identify_name_ #ifndef _di_fss_identify_defines_ - #define fss_identify_short_line "l" - #define fss_identify_short_name "n" - #define fss_identify_short_total "T" - #define fss_identify_short_type "t" - - #define fss_identify_long_line "line" - #define fss_identify_long_name "name" - #define fss_identify_long_total "total" - #define fss_identify_long_type "type" + #define fss_identify_short_content "c" + #define fss_identify_short_line "l" + #define fss_identify_short_name "n" + #define fss_identify_short_object "o" + #define fss_identify_short_total "t" + + #define fss_identify_long_content "content" + #define fss_identify_long_line "line" + #define fss_identify_long_name "name" + #define fss_identify_long_object "object" + #define fss_identify_long_total "total" enum { fss_identify_parameter_help, @@ -80,10 +82,11 @@ extern "C" { fss_identify_parameter_verbosity_debug, fss_identify_parameter_version, + fss_identify_parameter_content, fss_identify_parameter_line, fss_identify_parameter_name, + fss_identify_parameter_object, fss_identify_parameter_total, - fss_identify_parameter_type, }; #define fss_identify_console_parameter_t_initialize \ @@ -97,13 +100,14 @@ extern "C" { f_console_parameter_t_initialize(f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, 0, 0, f_console_type_inverse), \ f_console_parameter_t_initialize(f_console_standard_short_debug_s, f_console_standard_long_debug_s, 0, 0, f_console_type_inverse), \ f_console_parameter_t_initialize(f_console_standard_short_version_s, f_console_standard_long_version_s, 0, 0, f_console_type_inverse), \ + f_console_parameter_t_initialize(fss_identify_short_content, fss_identify_long_content, 0, 0, f_console_type_normal), \ f_console_parameter_t_initialize(fss_identify_short_line, fss_identify_long_line, 0, 1, f_console_type_normal), \ - f_console_parameter_t_initialize(fss_identify_short_name, fss_identify_long_name, 0, 0, f_console_type_normal), \ + f_console_parameter_t_initialize(fss_identify_short_name, fss_identify_long_name, 0, 1, f_console_type_normal), \ + f_console_parameter_t_initialize(fss_identify_short_object, fss_identify_long_object, 0, 0, f_console_type_normal), \ f_console_parameter_t_initialize(fss_identify_short_total, fss_identify_long_total, 0, 0, f_console_type_normal), \ - f_console_parameter_t_initialize(fss_identify_short_type, fss_identify_long_type, 0, 0, f_console_type_normal), \ } - #define fss_identify_total_parameters 13 + #define fss_identify_total_parameters 14 #endif // _di_fss_identify_defines_ #ifndef _di_fss_identify_data_t_ diff --git a/level_3/fss_identify/c/private-common.c b/level_3/fss_identify/c/private-common.c index 258cd3d..e6d4b34 100644 --- a/level_3/fss_identify/c/private-common.c +++ b/level_3/fss_identify/c/private-common.c @@ -5,6 +5,15 @@ extern "C" { #endif +#ifndef _di_fss_identify_data_delete_ + void fss_identify_data_delete(fss_identify_data_t *data) { + + if (!data) return; + + f_string_dynamic_resize(0, &data->name); + } +#endif // _di_fss_identify_data_delete_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-common.h b/level_3/fss_identify/c/private-common.h index cfb1ad4..97f07ac 100644 --- a/level_3/fss_identify/c/private-common.h +++ b/level_3/fss_identify/c/private-common.h @@ -17,20 +17,37 @@ extern "C" { * * current: The current position within the ids, used to determine when the line is matched. * line: The line number to select. + * total: The total ids across all files. + * name: The name to select. */ #ifndef _di_fss_identify_data_t_ typedef struct { f_array_length_t current; f_array_length_t line; + f_array_length_t total; + + f_string_dynamic_t name; } fss_identify_data_t; #define fss_identify_data_t_initialize \ { \ 0, \ 0, \ + 0, \ + f_string_dynamic_t_initialize, \ } #endif // _di_fss_identify_data_t_ +/** + * Fully deallocate all memory. + * + * @param data + * The data to deallocate. + */ +#ifndef _di_fss_identify_data_delete_ + extern void fss_identify_data_delete(fss_identify_data_t *data) f_attribute_visibility_internal; +#endif // _di_fss_identify_data_delete_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-fss_identify.c b/level_3/fss_identify/c/private-fss_identify.c index f66ea97..40bea8d 100644 --- a/level_3/fss_identify/c/private-fss_identify.c +++ b/level_3/fss_identify/c/private-fss_identify.c @@ -55,7 +55,7 @@ extern "C" { #ifndef _di_fss_identify_print_ void fss_identify_print(const fss_identify_main_t main, f_fll_id_t id) { - if (main.parameters[fss_identify_parameter_name].result == f_console_result_found || main.parameters[fss_identify_parameter_type].result != f_console_result_found) { + if (main.parameters[fss_identify_parameter_object].result == f_console_result_found || main.parameters[fss_identify_parameter_content].result != f_console_result_found) { f_string_static_t part = f_string_static_t_initialize; part.string = id.name; @@ -64,12 +64,12 @@ extern "C" { f_print_dynamic(main.output.stream, part); - if (main.parameters[fss_identify_parameter_name].result != f_console_result_found || main.parameters[fss_identify_parameter_type].result == f_console_result_found) { + if (main.parameters[fss_identify_parameter_object].result != f_console_result_found || main.parameters[fss_identify_parameter_content].result == f_console_result_found) { fprintf(main.output.stream, "%c", f_fss_type_header_part5); } } - if (main.parameters[fss_identify_parameter_name].result != f_console_result_found || main.parameters[fss_identify_parameter_type].result == f_console_result_found) { + if (main.parameters[fss_identify_parameter_object].result != f_console_result_found || main.parameters[fss_identify_parameter_content].result == f_console_result_found) { fprintf(main.output.stream, "%04x", id.type); } @@ -98,8 +98,14 @@ extern "C" { for (f_array_length_t i = 0; i < ids.used; ++i, ++data->current) { if (data->current == data->line) { + if (data->name.used) { + if (fl_string_dynamic_compare_string(ids.array[i].name, data->name, ids.array[i].used) != F_equal_to) { + continue; + } + } + if (main.parameters[fss_identify_parameter_total].result == f_console_result_found) { - fprintf(main.output.stream, "%c%c", f_string_ascii_1_s[0], f_string_eol_s[0]); + ++data->total; } else { fss_identify_print(main, ids.array[i]); @@ -112,11 +118,29 @@ extern "C" { } // for } else if (main.parameters[fss_identify_parameter_total].result == f_console_result_found) { - fprintf(main.output.stream, "%llu%c", ids.used, f_string_eol_s[0]); + if (data->name.used) { + + for (f_array_length_t i = 0; i < ids.used; ++i, ++data->current) { + + if (fl_string_dynamic_compare_string(ids.array[i].name, data->name, ids.array[i].used) == F_equal_to) { + ++data->total; + } + } // for + } + else { + data->total += ids.used; + } } else if (status == F_found || status == F_maybe) { for (f_array_length_t i = 0; i < ids.used; ++i) { + + if (data->name.used) { + if (fl_string_dynamic_compare_string(ids.array[i].name, data->name, ids.array[i].used) != F_equal_to) { + continue; + } + } + fss_identify_print(main, ids.array[i]); } // for } -- 1.8.3.1