From 7f0414504565fbc754427b518232f8c5ca5a90db Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Fri, 8 Nov 2019 19:25:07 -0600 Subject: [PATCH] Progress: rewriting fss_* programs and all dependencies I am changing the parameters and design of the fss_* programs, such as fss_basic_read. There is no work done on the fss_*_write programs yet. There were a lot of changes in the dependencies, including cleanups and improvements. The parameters passed to the fss_* functions will now be more consistent across each of them. This should make scripting much easier. There is a lot of incomplete work and I am focused currently on getting fss_basic_read to work as desired. I halted my work on f_conversion and fl_console to make sure none of these changes are lost. I do not expect this commit to compile with everything due to the incomplete work. I would rather post incomplete code than risk losing code as has happened in the past. --- level_0/f_console/c/console.c | 2 +- level_0/f_console/c/console.h | 23 +- level_0/f_conversion/c/conversion.c | 391 ++++++++++++--- level_0/f_conversion/c/conversion.h | 201 ++++++-- level_0/f_conversion/data/build/dependencies | 1 + level_0/f_conversion/data/build/settings | 6 +- level_0/f_fss/c/fss.h | 19 +- level_0/f_status/c/status.h | 8 +- level_0/f_string/c/string.h | 8 +- level_0/f_type/c/type.h | 66 ++- level_0/f_utf/c/utf.h | 4 +- level_1/fl_color/c/color.c | 2 +- level_1/fl_color/c/color.h | 2 +- level_1/fl_console/c/console.c | 147 +++++- level_1/fl_console/c/console.h | 79 ++++ level_1/fl_console/data/build/dependencies | 1 + level_1/fl_console/data/build/settings | 2 +- level_1/fl_file/c/file.c | 2 +- level_1/fl_fss/c/fss.c | 20 +- level_1/fl_fss/c/fss_basic.c | 4 +- level_1/fl_fss/c/fss_basic_list.c | 6 +- level_1/fl_fss/c/fss_extended.c | 8 +- level_1/fl_fss/c/fss_extended_list.c | 8 +- level_1/fl_status/c/status.c | 18 +- level_1/fl_status/c/status.h | 18 +- level_2/fll_fss/c/fss_basic.c | 2 +- level_2/fll_fss/c/fss_basic_list.c | 2 +- level_2/fll_fss/c/fss_extended.c | 2 +- level_2/fll_fss/c/fss_extended_list.c | 2 +- level_2/fll_fss/c/fss_status.c | 2 +- level_2/fll_program/c/program.c | 3 + level_2/fll_status/c/status.c | 24 +- level_3/byte_dump/c/byte_dump.c | 1 + level_3/byte_dump/c/byte_dump.h | 2 +- level_3/byte_dump/c/private-byte_dump.c | 10 +- level_3/byte_dump/c/private-byte_dump.h | 2 +- level_3/firewall/c/firewall.c | 9 +- level_3/firewall/c/firewall.h | 2 +- level_3/firewall/c/private-firewall.c | 16 +- level_3/firewall/c/private-firewall.h | 16 +- .../fss_basic_list_read/c/fss_basic_list_read.c | 213 ++++++--- .../fss_basic_list_read/c/fss_basic_list_read.h | 40 +- .../c/private-fss_basic_list_read.c | 239 +++++++++- .../c/private-fss_basic_list_read.h | 90 +++- .../fss_basic_list_write/c/fss_basic_list_write.c | 3 +- .../fss_basic_list_write/c/fss_basic_list_write.h | 2 +- level_3/fss_basic_read/c/fss_basic_read.c | 260 ++++++---- level_3/fss_basic_read/c/fss_basic_read.h | 32 +- level_3/fss_basic_read/c/private-fss_basic_read.c | 522 +++++++++++++++++---- level_3/fss_basic_read/c/private-fss_basic_read.h | 111 ++++- level_3/fss_basic_write/c/fss_basic_write.c | 3 +- level_3/fss_basic_write/c/fss_basic_write.h | 2 +- .../c/fss_extended_list_read.c | 195 +++++--- .../c/fss_extended_list_read.h | 40 +- .../c/private-fss_extended_list_read.c | 239 +++++++++- .../c/private-fss_extended_list_read.h | 90 +++- level_3/fss_extended_read/c/fss_extended_read.c | 220 ++++++--- level_3/fss_extended_read/c/fss_extended_read.h | 28 +- .../c/private-fss_extended_read.c | 229 ++++++++- .../c/private-fss_extended_read.h | 84 ++++ level_3/fss_extended_write/c/fss_extended_write.c | 6 +- level_3/fss_extended_write/c/fss_extended_write.h | 2 +- level_3/fss_status_code/c/fss_status_code.c | 11 +- level_3/fss_status_code/c/fss_status_code.h | 2 +- level_3/init/c/init.h | 2 +- level_3/init/c/private-init.h | 4 +- level_3/status_code/c/status_code.c | 11 +- level_3/status_code/c/status_code.h | 2 +- 68 files changed, 3053 insertions(+), 770 deletions(-) diff --git a/level_0/f_console/c/console.c b/level_0/f_console/c/console.c index 6196f15..dbfcd29 100644 --- a/level_0/f_console/c/console.c +++ b/level_0/f_console/c/console.c @@ -8,7 +8,7 @@ extern "C" { f_return_status f_console_identify(const f_string input, f_console_id *result) { #ifndef _di_level_0_parameter_checking_ if (result == 0) return f_status_set_error(f_invalid_parameter); - #endif // _di_level_0_parameter_checking_ + #endif // _di_level_0_parameter_checking_f const f_string_length length = strnlen(input, 3); diff --git a/level_0/f_console/c/console.h b/level_0/f_console/c/console.h index cbaf57c..dce50d7 100644 --- a/level_0/f_console/c/console.h +++ b/level_0/f_console/c/console.h @@ -132,10 +132,13 @@ extern "C" { * * - has_additional: Designates that a parameter will have a given number of additional arguments, such as 'blue' in '--color blue'. * - type: One of the f_console_type_* codes, defining how this parameter is to be processed. - * - result: A code representing that the parameter was found and how it was found ('-h' vs '--help'). - * - total: A number representing the total number of times this parameter was found ('-h -h' would result in a total of 2). - * - location: The last location in argv[] where this parameter was found. + * + * - result: A code representing that the parameter is found and how it is found ('-h' vs '--help'). + * - total: A number representing the total number of times this parameter is found ('-h -h' would result in a total of 2). + * + * - location: The last location in argv[] where this parameter is found. * - location_sub: The last sub-location at location in argv (only used by short parameters, such as -h or +l). + * - locations: All locations within argv where this parameter is found (order is preserved). * - additional: An array of locations representing where in the argv[] the additional arguments are found. */ #ifndef _di_f_console_parameter_ @@ -152,18 +155,21 @@ extern "C" { f_string_length location; f_string_length location_sub; + f_string_lengths locations; f_string_lengths additional; } f_console_parameter; - #define f_console_parameter_initialize(symbol_short, symbol_long, symbol_other, has_additional, type_value) { symbol_short, symbol_long, symbol_other, has_additional, type_value, f_console_result_none, 0, 0, 0, f_string_lengths_initialize } + #define f_console_parameter_initialize(symbol_short, symbol_long, symbol_other, has_additional, type_value) { symbol_short, symbol_long, symbol_other, has_additional, type_value, f_console_result_none, 0, 0, 0, f_string_lengths_initialize, f_string_lengths_initialize } #endif // _di_f_console_parameter_ /** * Provide a helper structure for references and processing parameters. * - * The f_console_parameters is designed for passing this to a function as a single argument. - * The "parameters" property is intended to be populated with an aray of f_console_parameter_id whose size is defined by the "used" property. - * This follows the idea of f_string_dynamic and has a "used" instead of length, but because this is not intended to be dynamically allocated there is no "size" property. + * Designed for passing this to a function as a single argument. + * + * parameter: Intended to be populated with an array of f_console_parameter_id whose size is defined by the "used" property. + * This is not intended to be dynamically allocated, so there is no "size" property. + * order: */ #ifndef _di_f_console_parameters_ typedef struct { @@ -204,7 +210,8 @@ extern "C" { #ifndef _di_f_console_arguments_ typedef struct { const unsigned long argc; - const f_string *argv; + + const f_string *argv; } f_console_arguments; #endif // _di_f_console_arguments_ diff --git a/level_0/f_conversion/c/conversion.c b/level_0/f_conversion/c/conversion.c index 4f57bd8..dca1b35 100644 --- a/level_0/f_conversion/c/conversion.c +++ b/level_0/f_conversion/c/conversion.c @@ -4,8 +4,19 @@ extern "C" { #endif -#ifndef _di_f_is_decimal_ - f_return_status f_is_decimal(const int8_t character) { +#ifndef _di_f_conversion_character_is_binary_ + f_return_status f_conversion_character_is_binary(const int8_t character) { + + if (character == 0x30 || character == 0x31) { + return f_true; + } + + return f_false; + } +#endif // _di_f_conversion_character_is_binary_ + +#ifndef _di_f_conversion_character_is_decimal_ + f_return_status f_conversion_character_is_decimal(const int8_t character) { if (character > 0x29 && character < 0x40) { return f_true; @@ -13,10 +24,10 @@ extern "C" { return f_false; } -#endif // _di_f_is_decimal_ +#endif // _di_f_conversion_character_is_decimal_ -#ifndef _di_f_is_hexidecimal_ - f_return_status f_is_hexidecimal(const int8_t character) { +#ifndef _di_f_conversion_character_is_hexidecimal_ + f_return_status f_conversion_character_is_hexidecimal(const int8_t character) { if (character > 0x29 && character < 0x40) { return f_true; @@ -30,35 +41,63 @@ extern "C" { return f_false; } -#endif // _di_f_is_hexidecimal_ +#endif // _di_f_conversion_character_is_hexidecimal_ -#ifndef _di_f_character_to_decimal_ - f_return_status f_character_to_decimal(const int8_t character, unsigned long *decimal) { +#ifndef _di_f_conversion_character_is_octal_ + f_return_status f_conversion_character_is_octal(const int8_t character) { + + if (character > 0x29 && character < 0x38) { + return f_true; + } + + return f_false; + } +#endif // _di_f_conversion_character_is_octal_ + +#ifndef _di_f_conversion_character_to_binary_ + f_return_status f_conversion_character_to_binary(const int8_t character, uint64_t *number) { #ifndef _di_level_0_parameter_checking_ - if (decimal == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_0_parameter_checking_ switch (character) { - case 0x30: *decimal = 0; break; - case 0x31: *decimal = 1; break; - case 0x32: *decimal = 2; break; - case 0x33: *decimal = 3; break; - case 0x34: *decimal = 4; break; - case 0x35: *decimal = 5; break; - case 0x36: *decimal = 6; break; - case 0x37: *decimal = 7; break; - case 0x38: *decimal = 8; break; - case 0x39: *decimal = 9; break; + case 0x30: *number = 0; break; + case 0x31: *number = 1; break; default: - return f_no_data; + return f_status_set_error(f_invalid_number); } return f_none; } -#endif // _di_f_character_to_decimal_ +#endif // _di_f_conversion_character_to_binary_ -#ifndef _di_f_character_to_hexidecimal_ - f_return_status f_character_to_hexidecimal(const int8_t character, unsigned long *decimal) { +#ifndef _di_f_conversion_character_to_decimal_ + f_return_status f_conversion_character_to_decimal(const int8_t character, uint64_t *number) { + #ifndef _di_level_0_parameter_checking_ + if (number == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + switch (character) { + case 0x30: *number = 0; break; + case 0x31: *number = 1; break; + case 0x32: *number = 2; break; + case 0x33: *number = 3; break; + case 0x34: *number = 4; break; + case 0x35: *number = 5; break; + case 0x36: *number = 6; break; + case 0x37: *number = 7; break; + case 0x38: *number = 8; break; + case 0x39: *number = 9; break; + default: + return f_status_set_error(f_invalid_number); + } + + return f_none; + } +#endif // _di_f_conversion_character_to_decimal_ + +#ifndef _di_f_conversion_character_to_hexidecimal_ + f_return_status f_conversion_character_to_hexidecimal(const int8_t character, uint64_t *decimal) { #ifndef _di_level_0_parameter_checking_ if (decimal == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_0_parameter_checking_ @@ -87,92 +126,306 @@ extern "C" { case 0x65: *decimal = 14; break; case 0x66: *decimal = 15; break; default: - return f_no_data; + return f_status_set_error(f_invalid_number); } return f_none; } -#endif // _di_f_character_to_hexidecimal_ +#endif // _di_f_conversion_character_to_hexidecimal_ -#ifndef _di_f_string_to_decimal_ - f_return_status f_string_to_decimal(const f_string string, unsigned long *decimal, const f_string_location location) { +#ifndef _di_f_conversion_character_to_octal_ + f_return_status f_conversion_character_to_octal(const int8_t character, uint64_t *number) { #ifndef _di_level_0_parameter_checking_ - if (decimal == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + switch (character) { + case 0x30: *number = 0; break; + case 0x31: *number = 1; break; + case 0x32: *number = 2; break; + case 0x33: *number = 3; break; + case 0x34: *number = 4; break; + case 0x35: *number = 5; break; + case 0x36: *number = 6; break; + case 0x37: *number = 7; break; + default: + return f_status_set_error(f_invalid_number); + } + + return f_none; + } +#endif // _di_f_conversion_character_to_octal_ + +#ifndef _di_f_conversion_string_to_binary_unsigned_ + f_return_status f_conversion_string_to_binary_unsigned(const f_string string, uint64_t *number, const f_string_location location) { + #ifndef _di_level_0_parameter_checking_ + if (string == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); if (location.start < 0) return f_status_set_error(f_invalid_parameter); - if (location.stop <= location.start) return f_status_set_error(f_invalid_parameter); + if (location.stop < location.start) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + bool scale = 0; + uint64_t digit = 0; + uint64_t converted = 0; + + // @todo: needs overflow/underflow detection. + for (f_string_length i = location.start; i <= location.stop; i++) { + if (f_conversion_character_to_binary(string[i], &digit) == f_none) { + if (scale) { + converted <<= 1; + converted += digit; + } + else if (digit != 0) { + scale = 1; + converted = digit; + } + } + else { + return f_status_set_error(f_invalid_number); + } + } // for + + *number = converted; + return f_none; + } +#endif // _di_f_conversion_string_to_binary_unsigned_ + +#ifndef _di_f_conversion_string_to_decimal_unsigned_ + f_return_status f_conversion_string_to_decimal_unsigned(const f_string string, uint64_t *number, const f_string_location location) { + #ifndef _di_level_0_parameter_checking_ if (string == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); + if (location.start < 0) return f_status_set_error(f_invalid_parameter); + if (location.stop < location.start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_0_parameter_checking_ - f_string_length current_location = location.start; - unsigned long scale = 0; - unsigned long digit = 0; - unsigned long decimal_value = 0; + bool scale = 0; + uint64_t digit = 0; + uint64_t converted = 0; - while (current_location < location.stop) { - if (f_character_to_decimal(string[current_location], &digit) == f_none) { + // @todo: needs overflow/underflow detection. + for (f_string_length i = location.start; i <= location.stop; i++) { + if (f_conversion_character_to_decimal(string[i], &digit) == f_none) { - // when the scale exists, then we need to make the number larger, for this function the scale is base 10 - if (scale > 0) { - decimal_value = 10 * decimal_value; - decimal_value += digit; + if (scale) { + converted *= 10; + converted += digit; } - else { + else if (digit != 0) { scale = 1; - decimal_value = digit; + converted = digit; } } else { - return f_no_data; + return f_status_set_error(f_invalid_number); } + } // for + + *number = converted; + return f_none; + } +#endif // _di_f_conversion_string_to_decimal_unsigned_ - ++current_location; - } // while +#ifndef _di_f_conversion_string_to_hexidecimal_unsigned_ + f_return_status f_conversion_string_to_hexidecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location) { + #ifndef _di_level_0_parameter_checking_ + if (string == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); + if (location.start < 0) return f_status_set_error(f_invalid_parameter); + if (location.stop < location.start) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ - *decimal = decimal_value; + bool scale = 0; + uint64_t digit = 0; + uint64_t converted = 0; + // @todo: needs overflow/underflow detection. + for (f_string_length i = location.start; i <= location.stop; i++) { + if (f_conversion_character_to_hexidecimal(string[i], &digit) == f_none) { + + if (scale) { + converted <<= 4; + converted += digit; + } + else if (digit != 0) { + scale = 1; + converted = digit; + } + } + else { + return f_status_set_error(f_invalid_number); + } + } // for + + *number = converted; return f_none; } -#endif // _di_f_string_to_decimal_ +#endif // _di_f_conversion_string_to_hexidecimal_unsigned_ -#ifndef _di_f_string_to_hexidecimal_ - f_return_status f_string_to_hexidecimal(const f_string string, unsigned long *decimal, const f_string_location location) { +#ifndef _di_f_conversion_string_to_octal_unsigned_ + f_return_status f_conversion_string_to_octal_unsigned(const f_string string, uint64_t *number, const f_string_location location) { #ifndef _di_level_0_parameter_checking_ - if (decimal == 0) return f_status_set_error(f_invalid_parameter); - if (location.start < 0) return f_status_set_error(f_invalid_parameter); - if (location.stop <= location.start) return f_status_set_error(f_invalid_parameter); if (string == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); + if (location.start < 0) return f_status_set_error(f_invalid_parameter); + if (location.stop < location.start) return f_status_set_error(f_invalid_parameter); #endif // _di_level_0_parameter_checking_ - f_string_length current_location = location.start; - unsigned long scale = 0; - unsigned long digit = 0; - unsigned long decimal_value = 0; + bool scale = 0; + uint64_t digit = 0; + uint64_t converted = 0; - while (current_location < location.stop) { - if (f_character_to_hexidecimal(string[current_location], &digit) == f_none) { + // @todo: needs overflow/underflow detection. + for (f_string_length i = location.start; i <= location.stop; i++) { + if (f_conversion_character_to_octal(string[i], &digit) == f_none) { - // when the scale exists, then we need to make the number larger, for this function the scale is base 16. - if (scale > 0) { - decimal_value <<= 4; - decimal_value += digit; + // when the scale exists, then we need to make the number larger, for this function the scale is base 8. + if (scale) { + converted *= 8; + converted += digit; } - else { + else if (digit != 0) { scale = 1; - decimal_value = digit; + converted = digit; } } else { - return f_no_data; + return f_status_set_error(f_invalid_number); } + } // for - ++current_location; - } // while + *number = converted; + return f_none; + } +#endif // _di_f_conversion_string_to_octal_unsigned_ + +#ifndef _di_f_conversion_string_to_number_unsigned_ + f_return_status f_conversion_string_to_number_unsigned(const f_string string, uint64_t *number, const f_string_location location) { + #ifndef _di_level_0_parameter_checking_ + if (string == 0) return f_status_set_error(f_invalid_parameter); + if (number == 0) return f_status_set_error(f_invalid_parameter); + if (location.start < 0) return f_status_set_error(f_invalid_parameter); + if (location.stop < location.start) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ - *decimal = decimal_value; + bool scale = 0; + uint64_t digit = 0; + uint64_t converted = 0; + uint8_t width = 0; + uint8_t width_max = 0; + uint8_t mode = 0; + f_string_length j = 0; + f_string_length offset = 0; + f_status status = f_none; - return f_none; + for (f_string_length i = location.start; i <= location.stop; i++) { + width = f_macro_utf_byte_width_is(string[i]); + + if (width == 0) { + if (isspace(string[i])) { + if (mode == 0) { + offset++; + continue; + } + + return f_status_set_error(f_invalid_number); + } + } + else { + if (mode == 0) { + width_max = (location.stop - i) + 1; + + status = f_utf_is_whitespace(string + i, width_max); + + if (status == f_true) { + offset = i + 1; + continue; + } + + if (f_status_is_error(status)) { + if (status == f_status_set_error(f_maybe)) { + status = f_status_set_error(f_incomplete_utf); + } + + return status; + } + } + + return f_status_set_error(f_invalid_number); + } + + if (string[i] == 0x30) { + j = i + 1; + + // immediate next value must be either '0', 'x', 'X', 'o', 'O', 'b', or 'B'. + if (j > location.stop) { + *number = 0; + return f_none; + } + else if (string[j] == 0x30) { + mode = 10; + } + else if (string[j] == 0x78 || string[j] == 0x58) { + mode = 16; + offset += 2; + } + else if (string[j] == 0x6f || string[j] == 0x4f) { + mode = 8; + offset += 2; + } + else if (string[j] == 0x62 || string[j] == 0x42) { + mode = 2; + offset += 2; + } + else { + return f_status_set_error(f_invalid_number); + } + + break; + } + + // plus sign is not allowed. + if (string[i] == 0x2b) { + return f_status_set_error(f_invalid_number); + } + + // negative sign is not allowed. + if (string[i] == 0x2d) { + return f_status_set_error(f_negative_number); + } + + if (f_conversion_character_is_decimal(string[i]) == f_true) { + mode = 10; + break; + } + + return f_status_set_error(f_negative_number); + } // for + + if (mode == 0) { + return f_no_data; + } + + f_string_location location_offset = f_string_location_initialize; + location_offset.start = location.start + offset; + location_offset.stop = location.stop; + + if (mode == 10) { + return f_conversion_string_to_decimal_unsigned(string, number, location_offset); + } + + if (mode == 16) { + return f_conversion_string_to_hexidecimal_unsigned(string, number, location_offset); + } + + if (mode == 8) { + return f_conversion_string_to_octal_unsigned(string, number, location_offset); + } + + return f_conversion_string_to_binary_unsigned(string, number, location_offset); } -#endif // _di_f_string_to_hexidecimal_ +#endif // _di_f_conversion_string_to_number_unsigned_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_conversion/c/conversion.h b/level_0/f_conversion/c/conversion.h index 9e47bc4..cd94168 100644 --- a/level_0/f_conversion/c/conversion.h +++ b/level_0/f_conversion/c/conversion.h @@ -11,18 +11,34 @@ #define _F_conversion_h // libc includes +#include #include // fll-0 includes #include #include #include +#include #ifdef __cplusplus extern "C" { #endif /** + * Convert a single character into the binary digit that it represents. + * + * @param character + * The character to validate. + * + * @return + * f_true if character is a binary. + * f_false if character is not a binary. + */ +#ifndef _di_f_conversion_character_is_binary_ + extern f_return_status f_conversion_character_is_binary(const int8_t character); +#endif // _di_f_conversion_character_is_binary_ + +/** * Convert a single character into the decimal value that it represents. * * @param character @@ -32,9 +48,9 @@ extern "C" { * f_true if character is a decimal. * f_false if character is not a decimal. */ -#ifndef _di_f_is_decimal_ - extern f_return_status f_is_decimal(const int8_t character); -#endif // _di_f_is_decimal_ +#ifndef _di_f_conversion_character_is_decimal_ + extern f_return_status f_conversion_character_is_decimal(const int8_t character); +#endif // _di_f_conversion_character_is_decimal_ /** * Convert a single character into the hexidecimal digit that it represents. @@ -46,93 +62,210 @@ extern "C" { * f_true if character is a hexidecimal. * f_false if character is not a hexidecimal. */ -#ifndef _di_f_is_hexidecimal_ - extern f_return_status f_is_hexidecimal(const int8_t character); -#endif // _di_f_is_hexidecimal_ +#ifndef _di_f_conversion_character_is_hexidecimal_ + extern f_return_status f_conversion_character_is_hexidecimal(const int8_t character); +#endif // _di_f_conversion_character_is_hexidecimal_ + +/** + * Convert a single character into the octal digit that it represents. + * + * @param character + * The character to validate. + * + * @return + * f_true if character is an octal. + * f_false if character is not an octal. + */ +#ifndef _di_f_conversion_character_is_octal_ + extern f_return_status f_conversion_character_is_octal(const int8_t character); +#endif // _di_f_conversion_character_is_octal_ /** * Convert a single character into the digit that it represents. * * @param character * The character to convert. - * @param decimal + * @param number * This will store the value of the converted character. - * This value is not changed when f_no_data is returned. + * This value is only changed on success. * * @return * f_none if character was converted to a decimal. - * f_no_data if no conversion was made due to non-decimal values being found. + * f_invalid_number (with error bit) if no conversion was made due to non-decimal values being found. * f_invalid_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_character_to_decimal_ - extern f_return_status f_character_to_decimal(const int8_t character, unsigned long *decimal); -#endif // _di_f_character_to_decimal_ +#ifndef _di_f_conversion_character_to_decimal_ + extern f_return_status f_conversion_character_to_decimal(const int8_t character, uint64_t *number); +#endif // _di_f_conversion_character_to_decimal_ /** * Convert a single character into the hexidecimal digit that it represents. * * @param character * The character to convert. - * @param decimal + * @param number + * This will store the value of the converted character. + * This value is only changed on success. + * + * @return + * f_none if character was converted to a hexidecimal. + * f_invalid_number (with error bit) if no conversion was made due to non-hexidecimal values being found. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_conversion_character_to_hexidecimal_ + extern f_return_status f_conversion_character_to_hexidecimal(const int8_t character, uint64_t *number); +#endif // _di_f_conversion_character_to_hexidecimal_ + +/** + * Convert a single character into the octal digit that it represents. + * + * @param character + * The character to convert. + * @param number * This will store the value of the converted character. - * This value is not changed when f_no_data is returned. + * This value is only changed on success. * * @return * f_none if character was converted to a hexidecimal. - * f_no_data if no conversion was made due to non-hexidecimal values being found. + * f_invalid_number (with error bit) if no conversion was made due to non-hexidecimal values being found. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_conversion_character_to_octal_ + extern f_return_status f_conversion_character_to_octal(const int8_t character, uint64_t *number); +#endif // _di_f_conversion_character_to_octal_ + +/** + * Convert a series of positive binary number characters into a uint64_t. + * + * This will stop at one of the following: EOS, location.stop, or a non-digit. + * This works like atoi, except there is a start/stop range. + * This will not process signed statuses (+/-). + * + * @param string + * The string to convert. + * @param number + * This will store the value of the converted string. + * This value is only changed on success. + * @param location + * The start/stop range to convert. + * + * @return + * f_none if the binary string was converted to an unsigned long. + * f_invalid_number (with error bit) if no conversion was made due to non-binary values being found. * f_invalid_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_character_to_hexidecimal_ - extern f_return_status f_character_to_hexidecimal(const int8_t character, unsigned long *decimal); -#endif // _di_f_character_to_hexidecimal_ +#ifndef _di_f_conversion_string_to_binary_unsigned_ + extern f_return_status f_conversion_string_to_binary_unsigned(const f_string string, uint64_t *number, const f_string_location location); +#endif // _di_f_conversion_string_to_binary_unsigned_ /** - * Convert a series of positive decimal numbers characters into an unsigned long. + * Convert a series of positive decimal number characters into an uint64_t. * - * This will stop at one of the following: EOS, max_length, or a non-digit. + * This will stop at one of the following: EOS, location.stop, or a non-digit. * This works like atoi, except there is a start/stop range. * This will not process signed statuses (+/-). * * @param string * The string to convert. - * @param decimal + * @param number * This will store the value of the converted string. - * This value is not changed when f_no_data is returned. + * This value is only changed on success. * @param location * The start/stop range to convert. * * @return * f_none if the decimal string was converted to an unsigned long. - * f_no_data if no conversion was made due to non-decimal values being found. + * f_invalid_number (with error bit) if no conversion was made due to non-decimal values being found. * f_invalid_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_string_to_decimal_ - extern f_return_status f_string_to_decimal(const f_string string, unsigned long *decimal, const f_string_location location); -#endif // _di_f_string_to_decimal_ +#ifndef _di_f_conversion_string_to_decimal_unsigned_ + extern f_return_status f_conversion_string_to_decimal_unsigned(const f_string string, uint64_t *number, const f_string_location location); +#endif // _di_f_conversion_string_to_decimal_unsigned_ /** - * Convert a series of positive hexidecimal numbers characters into an unsigned long. + * Convert a series of positive hexidecimal number characters into an uint64_t. * - * This will stop at one of the following: EOS, max_length, or a non-digit. + * This will stop at one of the following: EOS, location.stop, or a non-digit. * This works like atoi, except there is a start/stop range. * This will not process signed statuses (+/-). * * @param string * The string to convert. - * @param decimal + * @param number * This will store the value of the converted string. - * This value is not changed when f_no_data is returned. + * This value is only changed on success. * @param location * The start/stop range to convert. * * @return * f_none if the hexidecimal string was converted to an unsigned long. - * f_no_data if no conversion was made due to non-hexidecimal values being found. + * f_invalid_number (with error bit) if no conversion was made due to non-hexidecimal values being found. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_conversion_string_to_hexidecimal_unsigned_ + extern f_return_status f_conversion_string_to_hexidecimal_unsigned(const f_string string, uint64_t *number, const f_string_location location); +#endif // _di_f_conversion_string_to_hexidecimal_unsigned_ + +/** + * Convert a series of positive octal number characters into an uint64_t. + * + * This will stop at one of the following: EOS, location.stop, or a non-digit. + * This works like atoi, except there is a start/stop range. + * This will not process signed statuses (+/-). + * + * @param string + * The string to convert. + * @param number + * This will store the value of the converted string. + * This value is only changed on success. + * @param location + * The start/stop range to convert. + * + * @return + * f_none if the octal string was converted to an unsigned long. + * f_invalid_number (with error bit) if no conversion was made due to non-octal values being found. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_conversion_string_to_octal_unsigned_ + extern f_return_status f_conversion_string_to_octal_unsigned(const f_string string, uint64_t *number, const f_string_location location); +#endif // _di_f_conversion_string_to_octal_unsigned_ + +/** + * Convert a series of positive number characters into an uint64_t. + * + * This will stop at one of the following: EOS, location.stop, or a non-digit. + * This works like atoi, except there is a start/stop range. + * This will process signed statuses (+/-). + * This will detect based types as follows: + * - hexidecimals begin with either '0x' or '0X'. + * - octals begin with either '0o' or '0O'. + * - binaries begin with either '0b' or '0B'. + * - decimal is used for all other cases. + * + * Leading 0's and whitespace are ignored. + * Whitespace after the first digit is considered invalid. + * + * @param string + * The string to convert. + * @param number + * This will store the value of the converted string. + * This value is only changed on success. + * @param location + * The start/stop range to convert. + * + * @return + * f_none on success. + * f_no_data is returned if string only contains valid whitespace. * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_invalid_number (with error bit) if parameter is not a number. + * f_negative_number (with error bit) on negative value. + * f_underflow (with error bit) on underflow. + * f_overflow (with error bit) on overflow. + * f_incomplete_utf (with error bit) if an incomplete UTF-8 fragment is found. */ -#ifndef _di_f_string_to_hexidecimal_ - extern f_return_status f_string_to_hexidecimal(const f_string string, unsigned long *decimal, const f_string_location location); -#endif // _di_f_string_to_hexidecimal_ +#ifndef _di_f_conversion_string_to_number_unsigned_ + extern f_return_status f_conversion_string_to_number_unsigned(const f_string string, uint64_t *number, const f_string_location location); +#endif // _di_f_conversion_string_to_number_unsigned_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_conversion/data/build/dependencies b/level_0/f_conversion/data/build/dependencies index d8175f5..13b45c7 100644 --- a/level_0/f_conversion/data/build/dependencies +++ b/level_0/f_conversion/data/build/dependencies @@ -2,3 +2,4 @@ f_type f_status f_memory f_string +f_utf diff --git a/level_0/f_conversion/data/build/settings b/level_0/f_conversion/data/build/settings index 2ec7741..643c071 100644 --- a/level_0/f_conversion/data/build/settings +++ b/level_0/f_conversion/data/build/settings @@ -9,10 +9,10 @@ version_micro 0 build_compiler gcc build_linker ar -build_libraries -lc -build_libraries_fll -lf_memory +build_libraries -lc +build_libraries_fll -lf_utf -lf_memory build_sources_library conversion.c -build_sources_program +build_sources_program build_sources_headers conversion.h build_sources_bash build_sources_settings diff --git a/level_0/f_fss/c/fss.h b/level_0/f_fss/c/fss.h index 6f20e2c..fb2c755 100644 --- a/level_0/f_fss/c/fss.h +++ b/level_0/f_fss/c/fss.h @@ -130,7 +130,8 @@ extern "C" { */ #ifndef _di_f_fss_header_ typedef struct { - f_fss_id type; + f_fss_id type; + f_string_length length; } f_fss_header; @@ -146,7 +147,8 @@ extern "C" { */ #ifndef _di_f_fss_headers_ typedef struct { - f_fss_header *array; + f_fss_header *array; + f_string_length size; f_string_length used; } f_fss_headers; @@ -192,7 +194,8 @@ extern "C" { */ #ifndef _di_fss_objects_ typedef struct { - f_fss_object *array; + f_fss_object *array; + f_string_length size; f_string_length used; } f_fss_objects; @@ -223,9 +226,10 @@ extern "C" { */ #ifndef _di_fss_content_ typedef struct { - f_string_location *array; // the array of locations - f_array_length size; // total amount of allocated space - f_array_length used; // total number of allocated spaces used + f_string_location *array; + + f_array_length size; + f_array_length used; } f_fss_content; #define f_fss_content_initialize { 0, 0, 0 } @@ -250,7 +254,8 @@ extern "C" { */ #ifndef _di_f_fss_contents_ typedef struct { - f_fss_content *array; + f_fss_content *array; + f_array_length size; f_array_length used; } f_fss_contents; diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 4ae60c1..ec3e090 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -198,9 +198,11 @@ enum { f_underflow, f_overflow, f_divide_by_zero, - f_cannot_be_negative, - f_cannot_be_positive, - f_cannot_be_zero, + f_negative_number, + f_positive_number, + f_zero_number, + f_decimal_number, + f_invalid_number, #endif // _di_f_status_digits_ #ifndef _di_f_status_buffers_ diff --git a/level_0/f_string/c/string.h b/level_0/f_string/c/string.h index 9c7bf52..116965e 100644 --- a/level_0/f_string/c/string.h +++ b/level_0/f_string/c/string.h @@ -94,7 +94,7 @@ extern "C" { #endif // _di_f_string_ #ifndef _di_f_string_length_ - typedef long f_string_length; + typedef uint64_t f_string_length; #define f_string_length_printf string_format_long_integer @@ -119,8 +119,8 @@ extern "C" { #ifndef _di_f_string_lengths_ typedef struct { f_string_length *array; - f_array_length size; - f_array_length used; + f_array_length size; + f_array_length used; } f_string_lengths; #define f_string_lengths_initialize { 0, 0, 0 } @@ -183,7 +183,7 @@ extern "C" { #define f_string_locations_initialize {0, 0, 0} - #define f_clear_string_locations(locations) f_macro_memory_structure_clear(locations) + #define f_macro_string_locations_clear(locations) f_macro_memory_structure_clear(locations) #define f_macro_string_locations_new(status, locations, length) f_macro_memory_structure_new(status, locations, f_string_location, length) diff --git a/level_0/f_type/c/type.h b/level_0/f_type/c/type.h index f8bdf08..3a22311 100644 --- a/level_0/f_type/c/type.h +++ b/level_0/f_type/c/type.h @@ -11,6 +11,7 @@ #define _F_types_h // libc includes +#include #include #ifdef __cplusplus @@ -18,13 +19,6 @@ extern "C" { #endif /** - * Boolean type. - */ -#ifndef _di_f_type_bool_ - typedef uint8_t f_bool; -#endif // _di_f_type_bool_ - -/** * Status type. */ #ifndef _di_f_type_status_ @@ -41,6 +35,22 @@ extern "C" { #endif // _di_f_type_status_ /** + * Conditional 128-bit support. + * + * This should work in GCC, but other compilers this may not be available. + * When not supported, these will fallback to 64-bit. + */ +#ifndef _di_f_type_int_128_ + #ifdef __SIZEOF_INT128__ + typedef __int128_t f_int_128; + typedef __uint128_t f_uint_128; + #else + typedef int64_t f_int_128; + typedef uint64_t f_uint_128; + #endif // __SIZEOF_INT128__ +#endif // _di_f_type_int_128_ + +/** * Defines the maximum size to be supported. * * The size is to be the (max supported size - 1) such that that last number can be used for overflow operations. @@ -53,23 +63,27 @@ extern "C" { * For example, f_type_size_8_signed is 2^7, or 0 to 127, therefore the max size here is 127. */ #ifndef _di_f_type_sizes_ - #define f_type_size_8_unsigned 0xfe - #define f_type_size_8_signed 0x7e - #define f_type_size_16_unsigned 0xfffe - #define f_type_size_16_signed 0x7ffe - #define f_type_size_32_unsigned 0xfffffffe - #define f_type_size_32_signed 0x7ffffffe - #define f_type_size_64_unsigned 0xfffffffffffffffe - #define f_type_size_64_signed 0x7ffffffffffffffe + #define f_type_size_8_unsigned 0xfe + #define f_type_size_8_signed 0x7e + #define f_type_size_16_unsigned 0xfffe + #define f_type_size_16_signed 0x7ffe + #define f_type_size_32_unsigned 0xfffffffe + #define f_type_size_32_signed 0x7ffffffe + #define f_type_size_64_unsigned 0xfffffffffffffffe + #define f_type_size_64_signed 0x7ffffffffffffffe + //#define f_type_size_128_unsigned 0xfffffffffffffffffffffffe + //#define f_type_size_128_signed 0x7ffffffffffffffffffffffe - #define f_type_size_max_8_unsigned 0xff - #define f_type_size_max_8_signed 0x7f - #define f_type_size_max_16_unsigned 0xffff - #define f_type_size_max_16_signed 0x7fff - #define f_type_size_max_32_unsigned 0xffffffff - #define f_type_size_max_32_signed 0x7fffffff - #define f_type_size_max_64_unsigned 0xffffffffffffffff - #define f_type_size_max_64_signed 0x7fffffffffffffff + #define f_type_size_max_8_unsigned 0xff + #define f_type_size_max_8_signed 0x7f + #define f_type_size_max_16_unsigned 0xffff + #define f_type_size_max_16_signed 0x7fff + #define f_type_size_max_32_unsigned 0xffffffff + #define f_type_size_max_32_signed 0x7fffffff + #define f_type_size_max_64_unsigned 0xffffffffffffffff + #define f_type_size_max_64_signed 0x7fffffffffffffff + //#define f_type_size_max_128_unsigned 0xffffffffffffffffffffffff + //#define f_type_size_max_128_signed 0x7fffffffffffffffffffffff #endif // _di_f_type_sizes_ /** @@ -90,9 +104,9 @@ extern "C" { * Defines a variable to be used by arrays. */ #ifndef _di_f_array_length_ - typedef long f_array_length; - typedef int f_array_length_short; - typedef long long f_array_length_long; + typedef uint64_t f_array_length; + typedef uint32_t f_array_length_short; + typedef f_int_128 f_array_length_long; #endif // _di_f_array_length_ /** diff --git a/level_0/f_utf/c/utf.h b/level_0/f_utf/c/utf.h index ba1b765..67272dc 100644 --- a/level_0/f_utf/c/utf.h +++ b/level_0/f_utf/c/utf.h @@ -614,7 +614,7 @@ extern "C" { #endif // _di_f_utf_character_is_value_ /** - * Check to see if the entire byte block of the character is an ASCII or UTF-8 general space or control character. + * Check to see if the entire byte block of the character is an ASCII or UTF-8 general space character. * * @param character * The character to validate. @@ -826,7 +826,7 @@ extern "C" { #endif // _di_f_utf_is_valid_ /** - * Check to see if the entire byte block of the character is an ASCII or UTF-8 general space or control character. + * Check to see if the entire byte block of the character is an ASCII or UTF-8 general space character. * * @param character * The character to validate. diff --git a/level_1/fl_color/c/color.c b/level_1/fl_color/c/color.c index c77910b..e71d91a 100644 --- a/level_1/fl_color/c/color.c +++ b/level_1/fl_color/c/color.c @@ -191,7 +191,7 @@ extern "C" { #endif // _di_fl_color_print_code_ #ifndef _di_fl_color_load_context_ - f_return_status fl_color_load_context(fl_color_context *context, const f_bool use_light_colors) { + f_return_status fl_color_load_context(fl_color_context *context, const bool use_light_colors) { #ifndef _di_level_1_parameter_checking_ if (context == 0) return f_status_set_error(f_invalid_parameter); #endif // _di_level_1_parameter_checking_ diff --git a/level_1/fl_color/c/color.h b/level_1/fl_color/c/color.h index 36152e5..e59d20d 100644 --- a/level_1/fl_color/c/color.h +++ b/level_1/fl_color/c/color.h @@ -261,7 +261,7 @@ extern "C" { * f_reallocation_error (with error bit) on memory reallocation error. */ #ifndef _di_fl_color_load_context_ - extern f_return_status fl_color_load_context(fl_color_context *context, const f_bool use_light_colors); + extern f_return_status fl_color_load_context(fl_color_context *context, const bool use_light_colors); #endif // _di_fl_color_load_context_ #ifdef __cplusplus diff --git a/level_1/fl_console/c/console.c b/level_1/fl_console/c/console.c index 38f2018..847af52 100644 --- a/level_1/fl_console/c/console.c +++ b/level_1/fl_console/c/console.c @@ -12,7 +12,7 @@ extern "C" { f_status status = f_none; f_console_id result = 0; - f_bool found = f_false; + bool found = f_false; unsigned long location = 1; // Parameter 0 represents the program name so skip it. f_string_length sub_location = 0; @@ -26,13 +26,15 @@ extern "C" { f_string_lengths needs_additional = f_string_lengths_initialize; - // loop through and read all parameters + unsigned short width = 0; + + // loop through and read all parameters. while (location < arguments.argc) { f_console_identify(arguments.argv[location], &result); string_length = strnlen(arguments.argv[location], f_console_max_size); - // process the current parameter + // process the current parameter. if (result == f_console_short_enable || result == f_console_short_disable) { increment_by = 1; sub_location = 1; @@ -100,9 +102,41 @@ extern "C" { continue; } + width = f_macro_utf_byte_width_is(arguments.argv[location][sub_location]); + if (width > 0) { + increment_by = width; + } + if (arguments.argv[location][sub_location] != *parameters.parameter[parameter_counter].symbol_short) { continue; } + + if (width > 0) { + f_utf_character character_argument_utf = 0; + f_utf_character character_console_utf = 0; + + unsigned short max_width = string_length - sub_location; + + status = f_utf_char_to_character(arguments.argv[location] + sub_location, max_width, &character_argument_utf); + + if (status != f_none) { + f_macro_string_lengths_delete(status, needs_additional); + return status; + } + + max_width = strlen(parameters.parameter[parameter_counter].symbol_short); + + status = f_utf_char_to_character((f_string) parameters.parameter[parameter_counter].symbol_short, max_width, &character_console_utf); + + if (status != f_none) { + f_macro_string_lengths_delete(status, needs_additional); + return status; + } + + if (character_argument_utf != character_console_utf) { + continue; + } + } } else if (result == console_long) { if (parameters.parameter[parameter_counter].symbol_long == 0) { @@ -117,6 +151,20 @@ extern "C" { continue; } + if (parameters.parameter[parameter_counter].locations.used >= parameters.parameter[parameter_counter].locations.size) { + f_status allocation_status = f_none; + + f_macro_string_lengths_resize(allocation_status, parameters.parameter[parameter_counter].locations, parameters.parameter[parameter_counter].locations.size + f_console_default_allocation_step); + + if (f_status_is_error(allocation_status)) { + f_macro_string_lengths_delete(status, needs_additional); + return f_status_set_error(allocation_status); + } + } + + parameters.parameter[parameter_counter].locations.array[parameters.parameter[parameter_counter].locations.used] = location; + parameters.parameter[parameter_counter].locations.used++; + parameters.parameter[parameter_counter].result = f_console_result_found; parameters.parameter[parameter_counter].location = location; parameters.parameter[parameter_counter].location_sub = 0; @@ -166,6 +214,20 @@ extern "C" { continue; } + if (parameters.parameter[parameter_counter].locations.used >= parameters.parameter[parameter_counter].locations.size) { + f_status allocation_status = f_none; + + f_macro_string_lengths_resize(allocation_status, parameters.parameter[parameter_counter].locations, parameters.parameter[parameter_counter].locations.size + f_console_default_allocation_step); + + if (f_status_is_error(allocation_status)) { + f_macro_string_lengths_delete(status, needs_additional); + return f_status_set_error(allocation_status); + } + } + + parameters.parameter[parameter_counter].locations.array[parameters.parameter[parameter_counter].locations.used] = location; + parameters.parameter[parameter_counter].locations.used++; + parameters.parameter[parameter_counter].result = f_console_result_found; parameters.parameter[parameter_counter].location = location; parameters.parameter[parameter_counter].location_sub = 0; @@ -268,7 +330,84 @@ extern "C" { return f_none; } -#endif // _di_fl_console_parameter_prioritize__ +#endif // _di_fl_console_parameter_prioritize_ + +#ifndef _fl_console_parameter_to_number_unsigned_ + f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number) { + #ifndef _di_level_0_parameter_checking_ + if (argument == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_f + + if (argument[0] == '\0') { + return f_no_data; + } + + f_string_location location = f_string_location_initialize; + location.start = 0; + location.stop = strlen(argument) - 1; + + f_status status = f_conversion_string_to_number_unsigned(argument, number, location); + + return status; +/* + errno = 0; + + f_string end = 0; + uint64_t converted = (uint64_t) strtoull(argument, &end, 0); + + if (errno == ERANGE) { + if (converted == LLONG_MAX) { + return f_status_set_error(f_overflow); + } + + return f_status_set_error(f_invalid_number); + } + + if (*end == '\0') { + *number = converted; + return f_none; + } + + return f_status_set_error(f_invalid_number); +*/ + } +#endif // _fl_console_parameter_to_number_unsigned_ + +#ifndef _fl_console_parameter_to_number_signed_ + f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number) { + #ifndef _di_level_0_parameter_checking_ + if (argument == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_f + + if (argument[0] == '\0') { + return f_no_data; + } + + errno = 0; + + f_string end = 0; + int64_t converted = (int64_t) strtoull(argument, &end, 0); + + if (errno == ERANGE) { + if (converted == LLONG_MAX) { + return f_status_set_error(f_overflow); + } + + if (converted == LLONG_MIN) { + return f_status_set_error(f_underflow); + } + + return f_status_set_error(f_invalid_number); + } + + if (*end == '\0') { + *number = converted; + return f_none; + } + + return f_status_set_error(f_invalid_number); + } +#endif // _fl_console_parameter_to_number_signed_ #ifdef __cplusplus } // extern "C" diff --git a/level_1/fl_console/c/console.h b/level_1/fl_console/c/console.h index 93834ce..d84e076 100644 --- a/level_1/fl_console/c/console.h +++ b/level_1/fl_console/c/console.h @@ -11,13 +11,16 @@ #define _FL_console_h // libc include +#include #include // fll-0 includes #include +#include #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -57,7 +60,9 @@ extern "C" { * @return * f_none on success. * f_no_data if "additional" parameters were expected but not found. + * f_failure (with error bit) if width is not long enough to convert when processing arguments as UTF-8. * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_invalid_utf (with error bit) if character is an invalid UTF-8 character, when processing arguments. * f_reallocation_error (with error bit) on memory reallocation error. */ #ifndef _di_fl_console_parameter_process_ @@ -94,6 +99,80 @@ extern "C" { extern f_return_status fl_console_parameter_prioritize(const f_console_parameters parameters, const f_console_parameter_ids choices, f_console_parameter_id *decision); #endif // _di_fl_console_parameter_prioritize__ +/** + * Convert a console parameter additional argument to an unsigned integer. + * + * Unlike strtoull(), this only accepts complete numbers. + * If the argument has anything else, such as "123abc", this will consider the number to be "123". + * + * This accepts base-16, base-10, and base-8. + * - Base-16 is prefixed with '0x' or '0X'. + * - Base-10 is not prefixed. + * - Base-8 is prefixed with '0'. + * + * Note: The idea of an octal (base-8) being prefixed with '0' is a horrible mistake. + * This is done by strtoull(). + * In the future, custom code may be used in place of strtoull() to use '0o' for octal. + * Furthermore, '0b' for binary should be supported as well. + * + * @param argv + * The argument string expected to be a number. + * This is generally passed from the argv[]. + * @param number + * The converted number is stored here. + * This only gets modified on success. + * + * @return + * f_none on success. + * f_no_data the argument is empty. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_invalid_number (with error bit) if parameter is not a number. + * f_negative_number (with error bit) on negative value. + * f_overflow (with error bit) on overflow. + * + * @see strtoull() + */ +#ifndef _fl_console_parameter_to_number_unsigned_ + f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, uint64_t *number); +#endif // _fl_console_parameter_to_number_unsigned_ + +/** + * Convert a console parameter additional argument to a signed integer. + * + * Unlike strtoll(), this only accepts complete numbers. + * If the argument has anything else, such as "123abc", this will consider the number to be "123". + * + * This accepts base-16, base-10, and base-8. + * - Base-16 is prefixed with '0x' or '0X'. + * - Base-10 is not prefixed. + * - Base-8 is prefixed with '0'. + * + * Note: The idea of an octal (base-8) being prefixed with '0' is a horrible mistake. + * This is done by strtoull(). + * In the future, custom code may be used in place of strtoull() to use '0o'/'0O' for octal. + * Furthermore, '0b'/'0B' for binary should be supported as well. + * + * @param argv + * The argument string expected to be a number. + * This is generally passed from the argv[]. + * @param number + * The converted number is stored here. + * This only gets modified on success. + * + * @return + * f_none on success. + * f_no_data the argument is empty. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_invalid_number (with error bit) if parameter is not a number. + * f_underflow (with error bit) on underflow. + * f_overflow (with error bit) on overflow. + * + * @see strtoll() + */ +#ifndef _fl_console_parameter_to_number_signed_ + f_return_status fl_console_parameter_to_number_signed(const f_string argument, int64_t *number); +#endif // _fl_console_parameter_to_number_signed_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_console/data/build/dependencies b/level_1/fl_console/data/build/dependencies index 1ee73f6..9c37f71 100644 --- a/level_1/fl_console/data/build/dependencies +++ b/level_1/fl_console/data/build/dependencies @@ -3,4 +3,5 @@ f_status f_memory f_string f_console +f_convesion f_utf diff --git a/level_1/fl_console/data/build/settings b/level_1/fl_console/data/build/settings index d254cf8..1914c68 100644 --- a/level_1/fl_console/data/build/settings +++ b/level_1/fl_console/data/build/settings @@ -10,7 +10,7 @@ version_micro 0 build_compiler gcc build_linker ar build_libraries -lc -build_libraries_fll -lf_utf -lf_console -lf_memory +build_libraries_fll -lf_utf -lf_console -lf_conversion -lf_memory build_sources_library console.c build_sources_program build_sources_headers console.h diff --git a/level_1/fl_file/c/file.c b/level_1/fl_file/c/file.c index 7945d7e..039cbd5 100644 --- a/level_1/fl_file/c/file.c +++ b/level_1/fl_file/c/file.c @@ -18,7 +18,7 @@ extern "C" { f_status status = f_none; f_string_length size = 0; - f_bool infinite = f_false; + bool infinite = f_false; // when total_elements is 0, this means the file read will until EOF is reached if (position.total_elements == 0) { diff --git a/level_1/fl_fss/c/fss.c b/level_1/fl_fss/c/fss.c index d016e86..ec4c3f6 100644 --- a/level_1/fl_fss/c/fss.c +++ b/level_1/fl_fss/c/fss.c @@ -72,16 +72,16 @@ extern "C" { if (buffer.string[i] == f_fss_type_header_part5) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; f_string_location length = f_string_location_initialize; @@ -90,7 +90,7 @@ extern "C" { length.stop = i; // 1: A possibly valid header type was found, now convert it into its proper format and save the header type - f_string_to_hexidecimal(buffer.string, &header->type, length); + f_conversion_string_to_hexidecimal_unsigned(buffer.string, &header->type, length); // 2: At this point, we can still know the proper format for the file and still have a invalid header, handle accordingly if (buffer.string[i] == f_fss_type_header_close) { @@ -128,16 +128,16 @@ extern "C" { if (buffer.string[i] == f_fss_type_header_part5) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; - if (f_is_hexidecimal(buffer.string[i]) == f_true) { + if (f_conversion_character_is_hexidecimal(buffer.string[i]) == f_true) { i++; f_string_location length = f_string_location_initialize; @@ -145,7 +145,7 @@ extern "C" { length.start = i - 4; length.stop = i; - f_string_to_hexidecimal(buffer.string, &header->type, length); + f_conversion_string_to_hexidecimal_unsigned(buffer.string, &header->type, length); header->length = i + 1; diff --git a/level_1/fl_fss/c/fss_basic.c b/level_1/fl_fss/c/fss_basic.c index 7d79f96..92b3c03 100644 --- a/level_1/fl_fss/c/fss_basic.c +++ b/level_1/fl_fss/c/fss_basic.c @@ -34,7 +34,7 @@ extern "C" { // when handling delimits, the only time they should be applied is when a valid object would exist // however, the delimits will appear before a valid object, so remember their positions and only apply them after a would be valid object is confirmed - f_bool has_delimit = f_false; + bool has_delimit = f_false; // begin the search found->start = location->start; @@ -463,7 +463,7 @@ extern "C" { #endif // _di_level_1_parameter_checking_ f_status status = f_none; - f_bool quoted = f_false; + bool quoted = f_false; f_string_location buffer_position = f_string_location_initialize; f_string_length start_position = f_string_initialize; diff --git a/level_1/fl_fss/c/fss_basic_list.c b/level_1/fl_fss/c/fss_basic_list.c index e3efcd4..a6847df 100644 --- a/level_1/fl_fss/c/fss_basic_list.c +++ b/level_1/fl_fss/c/fss_basic_list.c @@ -206,7 +206,7 @@ extern "C" { found->array[found->used].start = location->start; f_string_length last_newline = location->start; - f_bool found_newline = f_false; + bool found_newline = f_false; // identify where the content ends while (location->start < buffer->used && location->start <= location->stop) { @@ -528,8 +528,8 @@ extern "C" { #endif // _di_level_1_parameter_checking_ f_status status = f_none; - f_bool is_comment = f_false; - f_bool has_graph = f_false; + bool is_comment = f_false; + bool has_graph = f_false; f_string_location buffer_position = f_string_location_initialize; f_string_length start_position = f_string_initialize; diff --git a/level_1/fl_fss/c/fss_extended.c b/level_1/fl_fss/c/fss_extended.c index 1aaed28..807f357 100644 --- a/level_1/fl_fss/c/fss_extended.c +++ b/level_1/fl_fss/c/fss_extended.c @@ -34,7 +34,7 @@ extern "C" { // when handling delimits, the only time they should be applied is when a valid object would exist // however, the delimits will appear before a valid object, so remember their positions and only apply them after a would be valid object is confirmed - f_bool has_delimit = f_false; + bool has_delimit = f_false; // begin the search found->start = location->start; @@ -403,10 +403,10 @@ extern "C" { return fl_fss_found_no_content; } - f_bool has_delimit = f_false; + bool has_delimit = f_false; int8_t quoted = f_string_eos; - f_bool continue_main_loop = f_false; + bool continue_main_loop = f_false; f_string_length length = 0; f_array_length already_used = found->used; @@ -815,7 +815,7 @@ extern "C" { #endif // _di_level_1_parameter_checking_ f_status status = f_none; - f_bool quoted = f_false; + bool quoted = f_false; f_string_location buffer_position = f_string_location_initialize; f_string_length start_position = f_string_initialize; diff --git a/level_1/fl_fss/c/fss_extended_list.c b/level_1/fl_fss/c/fss_extended_list.c index c6db293..31e3444 100644 --- a/level_1/fl_fss/c/fss_extended_list.c +++ b/level_1/fl_fss/c/fss_extended_list.c @@ -299,7 +299,7 @@ extern "C" { location->start++; } else if (buffer->string[location->start] == f_fss_extended_list_open || buffer->string[location->start] == f_fss_extended_list_close) { - f_bool is_open = f_false; + bool is_open = f_false; if (buffer->string[location->start] == f_fss_extended_list_open) { is_open = f_true; @@ -350,7 +350,7 @@ extern "C" { f_string_length location_newline = location->start; if (is_open) { - f_bool is_object = f_false; + bool is_object = f_false; if (slash_count % 2 == 0) { is_object = f_true; @@ -875,8 +875,8 @@ extern "C" { // @todo /* f_status status = f_none; - f_bool is_comment = f_false; - f_bool has_graph = f_false; + bool is_comment = f_false; + bool has_graph = f_false; f_string_location buffer_position = f_string_location_initialize; f_string_length start_position = f_string_initialize; diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 5ac5e3f..5dc290f 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -402,14 +402,20 @@ extern "C" { case f_divide_by_zero: *string = fl_status_string_divide_by_zero; break; - case f_cannot_be_negative: - *string = fl_status_string_cannot_be_negative; + case f_negative_number: + *string = fl_status_string_negative_number; break; - case f_cannot_be_positive: - *string = fl_status_string_cannot_be_positive; + case f_positive_number: + *string = fl_status_string_positive_number; break; - case f_cannot_be_zero: - *string = fl_status_string_cannot_be_zero; + case f_zero_number: + *string = fl_status_string_zero_number; + break; + case f_decimal_number: + *string = fl_status_string_decimal_number; + break; + case f_invalid_number: + *string = fl_status_string_invalid_number; break; #endif // _di_fl_status_digits_ diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 288dc39..1cd11da 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -406,14 +406,20 @@ extern "C" { #define fl_status_string_divide_by_zero "f_divide_by_zero" #define fl_status_string_divide_by_zero_length 17 - #define fl_status_string_cannot_be_negative "f_cannot_be_negative" - #define fl_status_string_cannot_be_negative_length 21 + #define fl_status_string_negative_number "f_negative_number" + #define fl_status_string_negative_number_length 18 - #define fl_status_string_cannot_be_positive "f_cannot_be_positive" - #define fl_status_string_cannot_be_positive_length 21 + #define fl_status_string_positive_number "f_positive_number" + #define fl_status_string_positive_number_length 18 - #define fl_status_string_cannot_be_zero "f_cannot_be_zero" - #define fl_status_string_cannot_be_zero_length 17 + #define fl_status_string_zero_number "f_zero_number" + #define fl_status_string_zero_number_length 14 + + #define fl_status_string_decimal_number "f_decimal_number" + #define fl_status_string_decimal_number_length 15 + + #define fl_status_string_invalid_number "f_invalid_number" + #define fl_status_string_invalid_number_length 15 #endif // _di_fl_status_digits_ #ifndef _di_fl_status_buffers_ diff --git a/level_2/fll_fss/c/fss_basic.c b/level_2/fll_fss/c/fss_basic.c index 3f3629b..69263b4 100644 --- a/level_2/fll_fss/c/fss_basic.c +++ b/level_2/fll_fss/c/fss_basic.c @@ -14,7 +14,7 @@ extern "C" { f_status status = f_none; f_string_length initial_used = objects->used; - f_bool found_data = f_false; + bool found_data = f_false; do { if (objects->used >= objects->size) { diff --git a/level_2/fll_fss/c/fss_basic_list.c b/level_2/fll_fss/c/fss_basic_list.c index a05884c..1575682 100644 --- a/level_2/fll_fss/c/fss_basic_list.c +++ b/level_2/fll_fss/c/fss_basic_list.c @@ -14,7 +14,7 @@ extern "C" { f_status status = f_none; f_string_length initial_used = objects->used; - f_bool found_data = f_false; + bool found_data = f_false; do { if (objects->used >= objects->size) { diff --git a/level_2/fll_fss/c/fss_extended.c b/level_2/fll_fss/c/fss_extended.c index 8f60bfb..55b32da 100644 --- a/level_2/fll_fss/c/fss_extended.c +++ b/level_2/fll_fss/c/fss_extended.c @@ -14,7 +14,7 @@ extern "C" { f_status status = f_none; f_string_length initial_used = objects->used; - f_bool found_data = f_false; + bool found_data = f_false; do { if (objects->used >= objects->size) { diff --git a/level_2/fll_fss/c/fss_extended_list.c b/level_2/fll_fss/c/fss_extended_list.c index fc57f1c..d466e57 100644 --- a/level_2/fll_fss/c/fss_extended_list.c +++ b/level_2/fll_fss/c/fss_extended_list.c @@ -14,7 +14,7 @@ extern "C" { f_status status = f_none; f_string_length initial_used = objects->used; - f_bool found_data = f_false; + bool found_data = f_false; do { if (objects->used >= objects->size) { diff --git a/level_2/fll_fss/c/fss_status.c b/level_2/fll_fss/c/fss_status.c index 386573a..639a53f 100644 --- a/level_2/fll_fss/c/fss_status.c +++ b/level_2/fll_fss/c/fss_status.c @@ -18,7 +18,7 @@ extern "C" { } // numbers are not valid status code strings. - if ((status = f_is_decimal(string[0])) == f_true) { + if ((status = f_conversion_character_is_decimal(string[0])) == f_true) { return f_status_set_error(f_invalid_data); } diff --git a/level_2/fll_program/c/program.c b/level_2/fll_program/c/program.c index ceca97b..9d1040c 100644 --- a/level_2/fll_program/c/program.c +++ b/level_2/fll_program/c/program.c @@ -113,6 +113,9 @@ extern "C" { else if (status == f_allocation_error || status == f_reallocation_error) { fl_color_print_line(f_standard_error, context->error, context->reset, "CRITICAL ERROR: unable to allocate memory."); } + else if (status == f_invalid_utf) { + fl_color_print_line(f_standard_error, context->error, context->reset, "ENCODING ERROR: Invalid UTF-8 character in parameter when calling fl_console_parameter_process()."); + } else if (status == f_invalid_parameter) { fl_color_print_line(f_standard_error, context->error, context->reset, "INTERNAL ERROR: Invalid parameter when calling fl_console_parameter_process()."); } diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index 5398a8c..e6ef62a 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -18,7 +18,7 @@ extern "C" { } // numbers are not valid status code strings. - if ((status = f_is_decimal(string[0])) == f_true) { + if ((status = f_conversion_character_is_decimal(string[0])) == f_true) { return f_status_set_error(f_invalid_data); } @@ -659,18 +659,28 @@ extern "C" { return f_none; } - if (fl_string_compare(string, fl_status_string_cannot_be_negative, length, fl_status_string_cannot_be_negative_length) == f_equal_to) { - *code = f_cannot_be_negative; + if (fl_string_compare(string, fl_status_string_negative_number, length, fl_status_string_negative_number_length) == f_equal_to) { + *code = f_negative_number; return f_none; } - if (fl_string_compare(string, fl_status_string_cannot_be_positive, length, fl_status_string_cannot_be_positive_length) == f_equal_to) { - *code = f_cannot_be_positive; + if (fl_string_compare(string, fl_status_string_positive_number, length, fl_status_string_positive_number_length) == f_equal_to) { + *code = f_positive_number; return f_none; } - if (fl_string_compare(string, fl_status_string_cannot_be_zero, length, fl_status_string_cannot_be_zero_length) == f_equal_to) { - *code = f_cannot_be_zero; + if (fl_string_compare(string, fl_status_string_zero_number, length, fl_status_string_zero_number_length) == f_equal_to) { + *code = f_zero_number; + return f_none; + } + + if (fl_string_compare(string, fl_status_string_decimal_number, length, fl_status_string_decimal_number_length) == f_equal_to) { + *code = f_decimal_number; + return f_none; + } + + if (fl_string_compare(string, fl_status_string_invalid_number, length, fl_status_string_invalid_number_length) == f_equal_to) { + *code = f_invalid_number; return f_none; } #endif // _di_fll_status_digits_ diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c index 3b8b33d..4d2f88c 100644 --- a/level_3/byte_dump/c/byte_dump.c +++ b/level_3/byte_dump/c/byte_dump.c @@ -299,6 +299,7 @@ extern "C" { f_status status = f_none; for (f_string_length i = 0; i < byte_dump_total_parameters; i++) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); } // for diff --git a/level_3/byte_dump/c/byte_dump.h b/level_3/byte_dump/c/byte_dump.h index c44ac40..9d1024e 100644 --- a/level_3/byte_dump/c/byte_dump.h +++ b/level_3/byte_dump/c/byte_dump.h @@ -195,7 +195,7 @@ extern "C" { f_console_parameter parameters[byte_dump_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; uint64_t first; uint64_t last; diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index 1d17340..8238de4 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -24,8 +24,8 @@ extern "C" { uint8_t previous_bytes = 0; uint8_t previous_invalid = 0; - f_bool character_reset = 0; - f_bool found_invalid_utf = f_false; + bool character_reset = 0; + bool found_invalid_utf = f_false; // Store the current character data until it can be printed. f_utf_string_dynamic characters = f_utf_string_dynamic_initialize; @@ -223,10 +223,10 @@ extern "C" { #endif // _di_byte_dump_file_ #ifndef _di_byte_dump_print_character_fragment_ - f_bool byte_dump_print_character_fragment(const byte_dump_data data, const f_utf_string_dynamic characters, const uint8_t invalid[], const int8_t width_utf, const int8_t byte_current, uint8_t *previous_bytes, uint8_t *previous_invalid, uint8_t *column, uint64_t *row) { + bool byte_dump_print_character_fragment(const byte_dump_data data, const f_utf_string_dynamic characters, const uint8_t invalid[], const int8_t width_utf, const int8_t byte_current, uint8_t *previous_bytes, uint8_t *previous_invalid, uint8_t *column, uint64_t *row) { uint8_t byte = 0; - f_bool reset = f_false; + bool reset = f_false; f_utf_string_length character_current = characters.used - 1; @@ -343,7 +343,7 @@ extern "C" { uint8_t j = 0; uint8_t output = 0; uint8_t width_utf = 0; - f_bool printed = f_false; + bool printed = f_false; fl_color_print(f_standard_output, data.context.notable, data.context.reset, " %s ", byte_dump_character_wall); diff --git a/level_3/byte_dump/c/private-byte_dump.h b/level_3/byte_dump/c/private-byte_dump.h index 0be072c..237b06d 100644 --- a/level_3/byte_dump/c/private-byte_dump.h +++ b/level_3/byte_dump/c/private-byte_dump.h @@ -67,7 +67,7 @@ extern "C" { * @see byte_dump_print_text() */ #ifndef _di_byte_dump_print_character_fragment_ - extern f_bool byte_dump_print_character_fragment(const byte_dump_data data, const f_utf_string_dynamic characters, const uint8_t invalid[], const int8_t width_utf, const int8_t byte_current, uint8_t *previous_bytes, uint8_t *previous_invalid, uint8_t *column, uint64_t *row); + extern bool byte_dump_print_character_fragment(const byte_dump_data data, const f_utf_string_dynamic characters, const uint8_t invalid[], const int8_t width_utf, const int8_t byte_current, uint8_t *previous_bytes, uint8_t *previous_invalid, uint8_t *column, uint64_t *row); #endif // _di_byte_dump_print_character_fragment_ /** diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c index 568bd0d..937138c 100644 --- a/level_3/firewall/c/firewall.c +++ b/level_3/firewall/c/firewall.c @@ -82,7 +82,7 @@ extern "C" { } else { // now determine which command was placed first - f_bool found_command = f_false; + bool found_command = f_false; unsigned int command = 0; if (data->parameters[firewall_parameter_command_start].result == f_console_result_found) { @@ -145,9 +145,9 @@ extern "C" { if (command == firewall_parameter_command_show) { // Warning: these are hardcoded print commands (I am not certain how I am going to implement external 'show' rules as the default-firewall setting file is the wrong place to put this) - f_bool show_nat = f_true; - f_bool show_mangle = f_true; - f_bool show_ports = f_true; + bool show_nat = f_true; + bool show_mangle = f_true; + bool show_ports = f_true; f_string_dynamics parameters = f_string_dynamics_initialize; int results = 0; @@ -657,6 +657,7 @@ extern "C" { f_string_length i = 0; while (i < firewall_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/firewall/c/firewall.h b/level_3/firewall/c/firewall.h index 57e0f80..d92915d 100644 --- a/level_3/firewall/c/firewall.h +++ b/level_3/firewall/c/firewall.h @@ -279,7 +279,7 @@ extern "C" { f_string_dynamics chains; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; f_string_dynamics devices; fl_color_context context; diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c index fe4a23c..78f2fa0 100644 --- a/level_3/firewall/c/private-firewall.c +++ b/level_3/firewall/c/private-firewall.c @@ -15,14 +15,14 @@ f_return_status firewall_perform_commands(const firewall_local_data local, const int results = 0; f_string_length length = 0; - f_bool invalid = f_false; - f_bool is_ip_list = f_false; + bool invalid = f_false; + bool is_ip_list = f_false; f_string_dynamic ip_list = f_string_dynamic_initialize; // iptables command arguments - f_bool device_all = f_false; - f_bool ip_list_direction = f_false; // false = source, true = destination - f_bool use_protocol = f_false; + bool device_all = f_false; + bool ip_list_direction = f_false; // false = source, true = destination + bool use_protocol = f_false; uint8_t tool = firewall_program_ip46tables; uint8_t chain = firewall_chain_none_id; @@ -861,8 +861,8 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains *reserved f_status status2 = f_none; uint8_t tool = firewall_program_iptables; - f_bool new_chain = f_false; - f_bool create_chain = f_false; + bool new_chain = f_false; + bool create_chain = f_false; int results = 0; f_array_length i = 0; @@ -1339,7 +1339,7 @@ f_return_status firewall_default_lock(const firewall_data data) { return status; } -f_return_status firewall_buffer_rules(const f_string filename, const f_bool optional, firewall_local_data *local, firewall_data *data) { +f_return_status firewall_buffer_rules(const f_string filename, const bool optional, firewall_local_data *local, firewall_data *data) { f_file file = f_file_initialize; f_status status = f_none; diff --git a/level_3/firewall/c/private-firewall.h b/level_3/firewall/c/private-firewall.h index 1ba3f9d..785b0d3 100644 --- a/level_3/firewall/c/private-firewall.h +++ b/level_3/firewall/c/private-firewall.h @@ -13,10 +13,10 @@ extern "C" { #endif typedef struct { - f_bool is_global; - f_bool is_main; - f_bool is_stop; - f_bool is_lock; + bool is_global; + bool is_main; + bool is_stop; + bool is_lock; f_file_position file_position; @@ -49,9 +49,9 @@ typedef struct { } typedef struct { - f_bool has_main; - f_bool has_stop; - f_bool has_lock; + bool has_main; + bool has_stop; + bool has_lock; f_array_length main_at; f_array_length stop_at; @@ -126,7 +126,7 @@ f_return_status firewall_default_lock(const firewall_data data) f_gcc_attribute_ /** * Buffer firewall rules. */ -f_return_status firewall_buffer_rules(const f_string filename, const f_bool optional, firewall_local_data *local, firewall_data *data) f_gcc_attribute_visibility_internal; +f_return_status firewall_buffer_rules(const f_string filename, const bool optional, firewall_local_data *local, firewall_data *data) f_gcc_attribute_visibility_internal; /** * Process buffered rules. diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.c b/level_3/fss_basic_list_read/c/fss_basic_list_read.c index b8d551e..0c14259 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.c @@ -17,15 +17,90 @@ extern "C" { printf("%c", f_string_eol); - fll_program_print_help_option(data.context, fss_basic_list_read_short_name, fss_basic_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find and print content from this object name."); - fll_program_print_help_option(data.context, fss_basic_list_read_short_count, fss_basic_list_read_long_count, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find a specific occurrence of the object."); - fll_program_print_help_option(data.context, fss_basic_list_read_short_total, fss_basic_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects in this file."); - fll_program_print_help_option(data.context, fss_basic_list_read_short_object, fss_basic_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); - fll_program_print_help_option(data.context, fss_basic_list_read_short_size, fss_basic_list_read_long_size, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print total lines in the given content."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_at, fss_basic_list_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric index."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_depth, fss_basic_list_read_long_depth, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric depth."); fll_program_print_help_option(data.context, fss_basic_list_read_short_line, fss_basic_list_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print only the content at the given line."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_name, fss_basic_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object with this name."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_object, fss_basic_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_select, fss_basic_list_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select sub-content at this index."); + fll_program_print_help_option(data.context, fss_basic_list_read_short_total, fss_basic_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects."); fll_program_print_help_usage(data.context, fss_basic_list_read_name, "filename(s)"); + printf(" This program will print the content associated with the given object and content data based on the FSS-0002 Basic List standard.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" When using the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth); + printf(" option, an order of operations is enforced on the parameters.%c", f_string_eol); + + printf(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_at); + printf(": An object index at the specified depth.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth); + printf(": A new depth within the specified depth, indexed from the root.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_name); + printf(": An object name at the specified depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth); + printf(" should be in numeric order, but values in between may be skipped.%c", f_string_eol); + printf(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%c", f_string_eol); + printf(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_at); + printf(" cannot be used with the parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_name); + printf(" at the same depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_select); + printf(" selects a content index at a given depth.%c", f_string_eol); + printf(" (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" Specify both "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_total); + printf(" and the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_line); + printf(" parameters to get the total lines.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" This program may support parameters, such as "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth); + printf(" or "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_select); + printf(", even if not supported by the standard.%c", f_string_eol); + printf(" This is done to help ensure consistency for scripting.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth); + printf(", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_select); + printf(", if the standard doesn't support multiple content groups, then only a select of 0 would be valid."); + + printf("%c%c", f_string_eol, f_string_eol); + return f_none; } #endif // _di_fss_basic_list_read_print_help_ @@ -40,15 +115,16 @@ extern "C" { f_console_parameter_ids choices = { ids, 3 }; status = fll_program_process_parameters(arguments, parameters, choices, &data->remaining, &data->context); - } - if (f_status_is_error(status)) { - fss_basic_list_read_delete_data(data); - return f_status_set_error(status); + if (f_status_is_error(status)) { + fss_basic_list_read_delete_data(data); + return f_status_set_error(status); + } + + status = f_none; } f_status status2 = f_none; - status = f_none; // execute parameter results if (data->parameters[fss_basic_list_read_parameter_help].result == f_console_result_found) { @@ -58,12 +134,59 @@ extern "C" { fll_program_print_version(fss_basic_list_read_version); } else if (data->remaining.used > 0 || data->process_pipe) { + if (data->parameters[fss_basic_list_read_parameter_object].result == f_console_result_found) { + if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_found) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_line); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + + if (data->parameters[fss_basic_list_read_parameter_select].result == f_console_result_additional) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_select); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + } + f_string_length counter = 0; f_string_length target = 0; f_string_length original_size = data->file_position.total_elements; - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional) { - target = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_list_read_parameter_count].additional.array[0]]); + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + target = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_list_read_parameter_at].additional.array[0]]); + } + + status = fss_basic_list_read_main_preprocess_depth(arguments, *data, &depths); + if (f_status_is_error(status)) { + macro_fss_basic_list_read_depths_delete(status2, depths); + fss_basic_list_read_delete_data(data); + return status; + } + + // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. + if (depths.used > 0 && depths.array[0].depth > 0) { + if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { + fprintf(f_standard_output, "0%s", f_string_eol); + return f_none; + } + + return f_none; + } + + // This standard does not support nesting, so it can be determined that --name is in use with --total and --object, which is not allowed. + if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { + if (data->parameters[fss_basic_list_read_parameter_object].result == f_console_result_found && data->parameters[fss_basic_list_read_parameter_name].result == f_console_result_found) { + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '--%s' parameter, the ' '--%s' parameter, and the '--%s' parameter together.", fss_basic_list_read_long_object, fss_basic_list_read_long_line); + return f_status_set_error(f_invalid_parameter); + } } if (data->process_pipe) { @@ -74,24 +197,7 @@ extern "C" { status = fl_file_read_fifo(file, &data->buffer); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", "-"); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", "-"); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", "-"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_basic_list_read_print_file_error(data->context, "fl_file_read_fifo", "-", f_status_set_fine(status)); fss_basic_list_read_delete_data(data); return status; } @@ -116,24 +222,7 @@ extern "C" { data->file_position.total_elements = original_size; if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_basic_list_read_print_file_error(data->context, "f_file_open", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_basic_list_read_delete_data(data); return f_status_set_error(status); } @@ -157,30 +246,7 @@ extern "C" { f_file_close(&file); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } - else if (status == f_overflow) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_not_open) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_seek_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_read_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_allocation_error || status == f_reallocation_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", f_status_set_error(status)); - } - + fss_basic_list_read_print_file_error(data->context, "fl_file_read", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_basic_list_read_delete_data(data); return f_status_set_error(status); } @@ -198,7 +264,7 @@ extern "C" { } // for } else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files"); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files."); status = f_status_set_error(f_invalid_parameter); } @@ -213,6 +279,7 @@ extern "C" { f_string_length i = 0; while (i < fss_basic_list_read_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.h b/level_3/fss_basic_list_read/c/fss_basic_list_read.h index 00e0178..51370ea 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.h @@ -54,19 +54,21 @@ extern "C" { #endif // _di_fss_basic_list_read_name_ #ifndef _di_fss_basic_list_read_defines_ + #define fss_basic_list_read_short_at "a" + #define fss_basic_list_read_short_depth "d" + #define fss_basic_list_read_short_line "l" #define fss_basic_list_read_short_name "n" - #define fss_basic_list_read_short_count "c" - #define fss_basic_list_read_short_total "t" #define fss_basic_list_read_short_object "o" - #define fss_basic_list_read_short_size "s" - #define fss_basic_list_read_short_line "l" + #define fss_basic_list_read_short_select "s" + #define fss_basic_list_read_short_total "t" + #define fss_basic_list_read_long_at "at" + #define fss_basic_list_read_long_depth "depth" + #define fss_basic_list_read_long_line "line" #define fss_basic_list_read_long_name "name" - #define fss_basic_list_read_long_count "count" - #define fss_basic_list_read_long_total "total" #define fss_basic_list_read_long_object "object" - #define fss_basic_list_read_long_size "size" - #define fss_basic_list_read_long_line "line" + #define fss_basic_list_read_long_select "select" + #define fss_basic_list_read_long_total "total" enum { fss_basic_list_read_parameter_help, @@ -75,12 +77,13 @@ extern "C" { fss_basic_list_read_parameter_no_color, fss_basic_list_read_parameter_version, + fss_basic_list_read_parameter_at, + fss_basic_list_read_parameter_depth, + fss_basic_list_read_parameter_line, fss_basic_list_read_parameter_name, - fss_basic_list_read_parameter_count, - fss_basic_list_read_parameter_total, fss_basic_list_read_parameter_object, - fss_basic_list_read_parameter_size, - fss_basic_list_read_parameter_line, + fss_basic_list_read_parameter_select, + fss_basic_list_read_parameter_total, }; #define f_console_parameter_initialize_fss_basic_list_read \ @@ -90,15 +93,16 @@ extern "C" { f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, f_false, f_console_type_inverse), \ + f_console_parameter_initialize(fss_basic_list_read_short_at, fss_basic_list_read_long_at, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_list_read_short_depth, fss_basic_list_read_long_depth, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_list_read_short_line, fss_basic_list_read_long_line, 0, f_true, f_console_type_normal), \ f_console_parameter_initialize(fss_basic_list_read_short_name, fss_basic_list_read_long_name, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_list_read_short_count, fss_basic_list_read_long_count, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_list_read_short_total, fss_basic_list_read_long_total, 0, f_false, f_console_type_normal), \ f_console_parameter_initialize(fss_basic_list_read_short_object, fss_basic_list_read_long_object, 0, f_false, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_list_read_short_size, fss_basic_list_read_long_size, 0, f_false, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_list_read_short_line, fss_basic_list_read_long_line, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_list_read_short_select, fss_basic_list_read_long_select, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_list_read_short_total, fss_basic_list_read_long_total, 0, f_false, f_console_type_normal), \ } - #define fss_basic_list_read_total_parameters 11 + #define fss_basic_list_read_total_parameters 13 #endif // _di_fss_basic_list_read_defines_ #ifndef _di_fss_basic_list_read_data_ @@ -110,7 +114,7 @@ extern "C" { f_fss_contents contents; f_file_position file_position; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_basic_list_read_data; diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c index 4ac5ddd..1f41ac9 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.c @@ -5,6 +5,217 @@ extern "C" { #endif +#ifndef _di_fss_basic_list_read_print_file_error_ + void fss_basic_list_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_file_not_open) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: The 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, "' is no longer open."); + } + else if (status == f_file_seek_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A seek error occurred while accessing the 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, "'."); + } + else if (status == f_file_read_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A read error occurred while accessing the 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, "'."); + } + else if (status == f_file_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to find the 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, "'."); + } + else if (status == f_file_open_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to open the 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, "'."); + } + else if (status == f_file_descriptor_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: File descriptor error while trying to open the 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, "'."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_allocation_error || status == f_reallocation_error) { + fl_color_print_line(f_standard_error, context.error, context.reset, "CRITICAL ERROR: unable to allocate memory."); + } + else { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: An unhandled error ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%u", status); + fl_color_print(f_standard_error, context.error, context.reset, ") has occured while calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + } +#endif // _di_fss_basic_list_read_print_file_error_ + +#ifndef _di_fss_basic_list_read_main_preprocess_depth_ + f_return_status fss_basic_list_read_main_preprocess_depth(const f_console_arguments arguments, const fss_basic_list_read_data data, fss_basic_list_read_depths *depths) { + f_status status = f_none; + + // pre-process the depth and depth-sensitive parameters. + if (data.parameters[fss_basic_list_read_parameter_depth].result == f_console_result_additional) { + macro_fss_basic_list_read_depths_new(status, (*depths), data.parameters[fss_basic_list_read_parameter_depth].locations.used); + if (f_status_is_error(status)) { + f_status status2 = f_none; + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + + macro_fss_basic_list_read_depths_delete(status2, (*depths)); + return f_status_set_error(f_invalid_parameter); + } + + f_array_length depth_position = data.parameters[fss_basic_list_read_parameter_depth].additional.array[0]; + f_array_length at_index = 0; + f_array_length name_index = 0; + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->array[0].parameter = 0; + depths->array[0].position = 0; + depths->used = 1; + + f_string_length depth_previous = depths->array[0].depth; + f_string_length depth_current = depths->array[0].depth; + + if (data.parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_basic_list_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_basic_list_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_basic_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_list_read_parameter_at].additional.array[at_index] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[1]) { + break; + } + } + + depths->array[0].parameter = fss_basic_list_read_parameter_at; + } + } // for + } + + if (data.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_basic_list_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_basic_list_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_basic_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_list_read_parameter_name].additional.array[name_index] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[1]) { + break; + } + } + + if (depths->array[0].parameter == fss_basic_list_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_basic_list_read_long_at, fss_basic_list_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].parameter = fss_basic_list_read_parameter_name; + } + } // for + } + + for (f_array_length i = 1; i < data.parameters[fss_basic_list_read_parameter_depth].locations.used; i++) { + depth_position = data.parameters[fss_basic_list_read_parameter_depth].additional.array[i]; + depth_current = (f_string_length) atoll(arguments.argv[depth_position]); + + if (depth_current > depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be specified before the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (depth_current == depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be the same as the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (data.parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_basic_list_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_basic_list_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_basic_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_list_read_parameter_at].additional.array[at_index] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + depths->array[i].parameter = fss_basic_list_read_parameter_at; + depths->array[i].position = data.parameters[fss_basic_list_read_parameter_at].additional.array[i]; + } + } // for + } + + if (data.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_basic_list_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_basic_list_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_basic_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_list_read_parameter_name].additional.array[name_index] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + if (depths->array[i].parameter == fss_basic_list_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_basic_list_read_long_at, fss_basic_list_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[i].parameter = fss_basic_list_read_parameter_name; + depths->array[i].position = data.parameters[fss_basic_list_read_parameter_name].additional.array[i]; + } + } // for + } + + depths->array[i].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->used++; + } // for + } + // when no depth parameter is specified, provide a implicit depth of 0 when depth-sensitive parameters are in use. + else { + if (data.parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { + if (data.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '%s' and '%s' parameters must not be specified at the same time.", fss_basic_list_read_long_name, fss_basic_list_read_long_object); + return f_status_set_error(f_invalid_parameter); + } + + macro_fss_basic_list_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_basic_list_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_basic_list_read_parameter_at; + depths->array[0].position = 0; + depths->used = 1; + } + else if (data.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) { + macro_fss_basic_list_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_basic_list_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_basic_list_read_parameter_name; + depths->array[0].position = 0; + depths->used = 1; + } + } + + return f_none; + } +#endif // _di_fss_basic_list_read_main_preprocess_depth_ + #ifndef _di_fss_basic_list_read_main_process_file_ f_return_status fss_basic_list_read_main_process_file(const f_console_arguments arguments, fss_basic_list_read_data *data, const f_string filename, const f_string_length target) { f_status status = f_none; @@ -55,7 +266,7 @@ extern "C" { // now that all of the files have been read, process the objects and contents if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_list_read_parameter_name].result == f_console_result_none) { - fprintf(f_standard_output, "%u\n", (unsigned int) data->objects.used); + fprintf(f_standard_output, "%llu\n", data->objects.used); } else { current = 0; @@ -63,9 +274,9 @@ extern "C" { if (data->parameters[fss_basic_list_read_parameter_name].result == f_console_result_none) { if (data->parameters[fss_basic_list_read_parameter_object].result == f_console_result_none) { for (; current < data->objects.used; current++) { - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional && found == target)) { - if (data->parameters[fss_basic_list_read_parameter_size].result == f_console_result_found) { + /*if (data->parameters[fss_basic_list_read_parameter_size].result == f_console_result_found) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].start; f_string_length size = 0; @@ -83,7 +294,7 @@ extern "C" { fprintf(f_standard_output, "0\n"); } } - else if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { + else*/ if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].start; f_string_length position = 0; @@ -127,7 +338,7 @@ extern "C" { } } - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -139,12 +350,12 @@ extern "C" { } else { for (; current < data->objects.used; current++) { - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -172,7 +383,7 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->objects.array[current].start, arguments.argv[data->parameters[fss_basic_list_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_basic_list_read_parameter_size].result == f_console_result_found) { + /*if (data->parameters[fss_basic_list_read_parameter_size].result == f_console_result_found) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].start; f_string_length size = 0; @@ -190,7 +401,7 @@ extern "C" { fprintf(f_standard_output, "0\n"); } } - else if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { + else*/ if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].start; f_string_length position = 0; @@ -227,7 +438,7 @@ extern "C" { } } else { - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional && found == target)) { if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) { total++; } @@ -240,7 +451,7 @@ extern "C" { } } - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -252,7 +463,7 @@ extern "C" { } } // for - if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_none) { + if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_none) { fprintf(f_standard_output, f_string_length_printf "\n", total); } } @@ -265,12 +476,12 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->contents.array[current].array[0].start, arguments.argv[data->parameters[fss_basic_list_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_basic_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } diff --git a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h index 85709c7..bb37a47 100644 --- a/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/private-fss_basic_list_read.h @@ -11,13 +11,97 @@ #ifdef __cplusplus extern "C" { #endif +/** + * A structure of parameters applied at some depth. + * + * depth: the depth number in which this is to be processed at. + * parameter: the index representing the parameter enum of either the "at" parameter or the "name" parameter. + * position: the parameter position index within the argv representing the value associated with the designated parameter. + */ +#ifndef _di_fss_basic_list_read_depth_ + typedef struct { + f_string_length depth; -#ifdef __cplusplus -} // extern "C" -#endif + f_array_length parameter; + f_array_length position; + } fss_basic_list_read_depth; + + #define fss_basic_list_read_depth_initialize \ + { \ + 0, \ + f_array_length_initialize, \ + f_array_length_initialize, \ + } +#endif // _di_fss_basic_list_read_depth_ + +/** + * An array of depth parameters. + * + * array: the array of depths. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_fss_basic_list_read_depths_ + typedef struct { + fss_basic_list_read_depth *array; + + f_array_length size; + f_array_length used; + } fss_basic_list_read_depths; + + #define fss_basic_list_read_depths_initialize { 0, 0, 0 } + + #define macro_fss_basic_list_read_depths_clear(depths) f_macro_memory_structure_clear(depths) + + #define macro_fss_basic_list_read_depths_new(status, depths, length) f_macro_memory_structure_new(status, depths, fss_basic_list_read_depths, length) + + #define macro_fss_basic_list_read_depths_delete(status, depths) f_macro_memory_structure_delete(status, depths, fss_basic_list_read_depths) + #define macro_fss_basic_list_read_depths_destroy(status, depths) f_macro_memory_structure_destroy(status, depths, fss_basic_list_read_depths) + + #define macro_fss_basic_list_read_depths_resize(status, depths, new_length) f_macro_memory_structure_resize(status, depths, fss_basic_list_read_depths, new_length) + #define macro_fss_basic_list_read_depths_adjust(status, depths, new_length) f_macro_memory_structure_adjust(status, depths, fss_basic_list_read_depths, new_length) +#endif // _di_fss_basic_list_read_depths_ + +/** + * Print file error messages. + * + * @param context + * The color context information to use when printing. + * @param function_name + * The name of the function responsible for the error. + * @param file_name + * The name of the file with the error. + * @param status + * The status code representing the error. + */ +#ifndef _di_fss_basic_list_read_print_file_error_ + extern void fss_basic_list_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_print_file_error_ + +/** + * Pre-process the parameters, parsing out and handling the depth and depth related parameters. + * + * @param arguments + * The console arguments to pre-process. + * @param data + * The Program specific data. + * @param depths + * This stores the pre-processed depth parameters. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_list_read_main_preprocess_depth_ + extern f_return_status fss_basic_list_read_main_preprocess_depth(const f_console_arguments arguments, const fss_basic_list_read_data data, fss_basic_list_read_depths *depths) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_list_read_main_preprocess_depth_ #ifndef _di_fss_basic_list_read_main_process_file_ extern f_return_status fss_basic_list_read_main_process_file(const f_console_arguments arguments, fss_basic_list_read_data *data, const f_string filename, const f_string_length target) f_gcc_attribute_visibility_internal; #endif // _di_fss_basic_list_read_main_process_file_ +#ifdef __cplusplus +} // extern "C" +#endif + #endif // _PRIVATE_fss_basic_list_read_h diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.c b/level_3/fss_basic_list_write/c/fss_basic_list_write.c index 99e790d..5f37256 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.c @@ -54,7 +54,7 @@ extern "C" { } else { f_array_length counter = 0; - f_bool object = (data->parameters[fss_basic_list_write_parameter_object].result == f_console_result_found); + bool object = (data->parameters[fss_basic_list_write_parameter_object].result == f_console_result_found); f_string_dynamic buffer = f_string_dynamic_initialize; f_string_location location = f_string_location_initialize; @@ -207,6 +207,7 @@ extern "C" { f_string_length i = 0; while (i < fss_basic_list_write_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.h b/level_3/fss_basic_list_write/c/fss_basic_list_write.h index aa48b46..d8237a3 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.h +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.h @@ -90,7 +90,7 @@ extern "C" { f_console_parameter parameters[fss_basic_list_write_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_basic_list_write_data; diff --git a/level_3/fss_basic_read/c/fss_basic_read.c b/level_3/fss_basic_read/c/fss_basic_read.c index a552a31..4d3937f 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.c +++ b/level_3/fss_basic_read/c/fss_basic_read.c @@ -17,13 +17,90 @@ extern "C" { printf("%c", f_string_eol); - fll_program_print_help_option(data.context, fss_basic_read_short_name, fss_basic_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find and print content from this object name."); - fll_program_print_help_option(data.context, fss_basic_read_short_count, fss_basic_read_long_count, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find a specific occurrence of the object."); - fll_program_print_help_option(data.context, fss_basic_read_short_total, fss_basic_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects in this file."); + fll_program_print_help_option(data.context, fss_basic_read_short_at, fss_basic_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric index."); + fll_program_print_help_option(data.context, fss_basic_read_short_depth, fss_basic_read_long_depth, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric depth."); + fll_program_print_help_option(data.context, fss_basic_read_short_line, fss_basic_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print only the content at the given line."); + fll_program_print_help_option(data.context, fss_basic_read_short_name, fss_basic_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object with this name."); fll_program_print_help_option(data.context, fss_basic_read_short_object, fss_basic_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); + fll_program_print_help_option(data.context, fss_basic_read_short_select, fss_basic_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select sub-content at this index."); + fll_program_print_help_option(data.context, fss_basic_read_short_total, fss_basic_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects."); fll_program_print_help_usage(data.context, fss_basic_read_name, "filename(s)"); + printf(" This program will print the content associated with the given object and content data based on the FSS-0000 Basic standard.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" When using the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_depth); + printf(" option, an order of operations is enforced on the parameters.%c", f_string_eol); + + printf(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_at); + printf(": An object index at the specified depth.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_depth); + printf(": A new depth within the specified depth, indexed from the root.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_name); + printf(": An object name at the specified depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_depth); + printf(" should be in numeric order, but values in between may be skipped.%c", f_string_eol); + printf(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%c", f_string_eol); + printf(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_at); + printf(" cannot be used with the parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_name); + printf(" at the same depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_select); + printf(" selects a content index at a given depth.%c", f_string_eol); + printf(" (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" Specify both "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_total); + printf(" and the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_line); + printf(" parameters to get the total lines.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" This program may support parameters, such as "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_depth); + printf(" or "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_select); + printf(", even if not supported by the standard.%c", f_string_eol); + printf(" This is done to help ensure consistency for scripting.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_depth); + printf(", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_read_long_select); + printf(", if the standard doesn't support multiple content groups, then only a select of 0 would be valid."); + + printf("%c%c", f_string_eol, f_string_eol); + return f_none; } #endif // _di_fss_basic_read_print_help_ @@ -38,17 +115,16 @@ extern "C" { f_console_parameter_ids choices = { ids, 3 }; status = fll_program_process_parameters(arguments, parameters, choices, &data->remaining, &data->context); - } - if (f_status_is_error(status)) { - fss_basic_read_delete_data(data); - return f_status_set_error(status); - } + if (f_status_is_error(status)) { + fss_basic_read_delete_data(data); + return f_status_set_error(status); + } - f_status status2 = f_none; - status = f_none; + status = f_none; + } - // execute parameter results + // execute parameter results. if (data->parameters[fss_basic_read_parameter_help].result == f_console_result_found) { fss_basic_read_print_help(*data); } @@ -56,12 +132,71 @@ extern "C" { fll_program_print_version(fss_basic_read_version); } else if (data->remaining.used > 0 || data->process_pipe) { + if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_found) { + if (data->parameters[fss_basic_read_parameter_line].result == f_console_result_found) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_line); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + + if (data->parameters[fss_basic_read_parameter_select].result == f_console_result_additional) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_select); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + } + + fss_basic_read_depths depths = fss_basic_read_depths_initialize; + f_status status2 = f_none; + f_string_length counter = 0; - f_string_length target = 0; f_string_length original_size = data->file_position.total_elements; - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional) { - target = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_read_parameter_count].additional.array[0]]); + status = fss_basic_read_main_preprocess_depth(arguments, *data, &depths); + if (f_status_is_error(status)) { + macro_fss_basic_read_depths_delete(status2, depths); + fss_basic_read_delete_data(data); + return status; + } + + // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. + if (depths.used > 0 && depths.array[0].depth > 0) { + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found) { + fprintf(f_standard_output, "0%c", f_string_eol); + return f_none; + } + + return f_none; + } + + if (data->parameters[fss_basic_read_parameter_select].result == f_console_result_found) { + 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", fss_basic_read_long_select); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter requires a positive number."); + return f_status_set_error(f_invalid_parameter); + } + + // This standard does not support nesting, so it can be determined that --name is in use with --total and --object, which is not allowed. + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found) { + if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_found && data->parameters[fss_basic_read_parameter_name].result == f_console_result_found) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_parameter_total); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter, the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter, and the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_read_long_line); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter together."); + + return f_status_set_error(f_invalid_parameter); + } } if (data->process_pipe) { @@ -72,41 +207,21 @@ extern "C" { status = fl_file_read_fifo(file, &data->buffer); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } - else if (status == f_overflow) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", "-"); - } - else if (status == f_file_not_open) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", "-"); - } - else if (status == f_file_seek_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", "-"); - } - else if (status == f_file_read_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", "-"); - } - else if (status == f_allocation_error || status == f_reallocation_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", f_status_set_error(status)); - } - + fss_basic_read_print_file_error(data->context, "fl_file_read_fifo", "-", f_status_set_fine(status)); + macro_fss_basic_read_depths_delete(status2, depths); fss_basic_read_delete_data(data); - return f_status_set_error(status); + return status; } - status = fss_basic_read_main_process_file(arguments, data, "-", target); + status = fss_basic_read_main_process_file(arguments, data, "-", depths); if (f_status_is_error(status)) { + macro_fss_basic_read_depths_delete(status2, depths); + fss_basic_read_delete_data(data); return status; } - // clear buffers before continuing + // clear buffers before continuing. f_macro_fss_contents_delete(status2, data->contents); f_macro_fss_objects_delete(status2, data->objects); f_macro_string_dynamic_delete(status2, data->buffer); @@ -121,26 +236,10 @@ extern "C" { data->file_position.total_elements = original_size; if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_basic_read_print_file_error(data->context, "f_file_open", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); + macro_fss_basic_read_depths_delete(status2, depths); fss_basic_read_delete_data(data); - return f_status_set_error(status); + return status; } if (data->file_position.total_elements == 0) { @@ -148,7 +247,7 @@ extern "C" { data->file_position.total_elements = ftell(file.address); - // skip past empty files + // skip past empty files. if (data->file_position.total_elements == 0) { f_file_close(&file); continue; @@ -162,49 +261,31 @@ extern "C" { f_file_close(&file); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } - else if (status == f_overflow) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_not_open) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_seek_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_read_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_allocation_error || status == f_reallocation_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", f_status_set_error(status)); - } - + fss_basic_read_print_file_error(data->context, "fl_file_read", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); + macro_fss_basic_read_depths_delete(status2, depths); fss_basic_read_delete_data(data); - return f_status_set_error(status); + return status; } - status = fss_basic_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[counter]], target); + status = fss_basic_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[counter]], depths); if (f_status_is_error(status)) { + macro_fss_basic_read_depths_delete(status2, depths); + fss_basic_read_delete_data(data); return status; } - // clear buffers before repeating the loop + // clear buffers before repeating the loop. f_macro_fss_contents_delete(status2, data->contents); f_macro_fss_objects_delete(status2, data->objects); f_macro_string_dynamic_delete(status2, data->buffer); } // for } + + macro_fss_basic_read_depths_delete(status2, depths); } else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files"); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files."); status = f_status_set_error(f_invalid_parameter); } @@ -219,6 +300,7 @@ extern "C" { f_string_length i = 0; while (i < fss_basic_read_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_basic_read/c/fss_basic_read.h b/level_3/fss_basic_read/c/fss_basic_read.h index d17e369..dbd1a22 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.h +++ b/level_3/fss_basic_read/c/fss_basic_read.h @@ -54,15 +54,21 @@ extern "C" { #endif // _di_fss_basic_read_name_ #ifndef _di_fss_basic_read_defines_ + #define fss_basic_read_short_at "a" + #define fss_basic_read_short_depth "d" + #define fss_basic_read_short_line "l" #define fss_basic_read_short_name "n" - #define fss_basic_read_short_count "c" - #define fss_basic_read_short_total "t" #define fss_basic_read_short_object "o" + #define fss_basic_read_short_select "s" + #define fss_basic_read_short_total "t" + #define fss_basic_read_long_at "at" + #define fss_basic_read_long_depth "depth" + #define fss_basic_read_long_line "line" #define fss_basic_read_long_name "name" - #define fss_basic_read_long_count "count" - #define fss_basic_read_long_total "total" #define fss_basic_read_long_object "object" + #define fss_basic_read_long_select "select" + #define fss_basic_read_long_total "total" enum { fss_basic_read_parameter_help, @@ -71,10 +77,13 @@ extern "C" { fss_basic_read_parameter_no_color, fss_basic_read_parameter_version, + fss_basic_read_parameter_at, + fss_basic_read_parameter_depth, + fss_basic_read_parameter_line, fss_basic_read_parameter_name, - fss_basic_read_parameter_count, - fss_basic_read_parameter_total, fss_basic_read_parameter_object, + fss_basic_read_parameter_select, + fss_basic_read_parameter_total, }; #define f_console_parameter_initialize_fss_basic_read \ @@ -84,13 +93,16 @@ extern "C" { f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, f_false, f_console_type_inverse), \ + f_console_parameter_initialize(fss_basic_read_short_at, fss_basic_read_long_at, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_read_short_depth, fss_basic_read_long_depth, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_read_short_line, fss_basic_read_long_line, 0, f_true, f_console_type_normal), \ f_console_parameter_initialize(fss_basic_read_short_name, fss_basic_read_long_name, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_read_short_count, fss_basic_read_long_count, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_basic_read_short_total, fss_basic_read_long_total, 0, f_false, f_console_type_normal), \ f_console_parameter_initialize(fss_basic_read_short_object, fss_basic_read_long_object, 0, f_false, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_read_short_select, fss_basic_read_long_select, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_basic_read_short_total, fss_basic_read_long_total, 0, f_false, f_console_type_normal), \ } - #define fss_basic_read_total_parameters 9 + #define fss_basic_read_total_parameters 13 #endif // _di_fss_basic_read_defines_ #ifndef _di_fss_basic_read_data_ @@ -102,7 +114,7 @@ extern "C" { f_fss_contents contents; f_file_position file_position; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_basic_read_data; diff --git a/level_3/fss_basic_read/c/private-fss_basic_read.c b/level_3/fss_basic_read/c/private-fss_basic_read.c index fc9ee03..f00a77b 100644 --- a/level_3/fss_basic_read/c/private-fss_basic_read.c +++ b/level_3/fss_basic_read/c/private-fss_basic_read.c @@ -5,19 +5,277 @@ extern "C" { #endif +#ifndef _di_fss_basic_read_print_file_error_ + void fss_basic_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_file_not_open) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: The 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, "' is no longer open."); + } + else if (status == f_file_seek_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A seek error occurred while accessing the 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, "'."); + } + else if (status == f_file_read_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A read error occurred while accessing the 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, "'."); + } + else if (status == f_file_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to find the 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, "'."); + } + else if (status == f_file_open_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to open the 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, "'."); + } + else if (status == f_file_descriptor_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: File descriptor error while trying to open the 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, "'."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_allocation_error || status == f_reallocation_error) { + fl_color_print_line(f_standard_error, context.error, context.reset, "CRITICAL ERROR: unable to allocate memory."); + } + else { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: An unhandled error ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%u", status); + fl_color_print(f_standard_error, context.error, context.reset, ") has occured while calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + } +#endif // _di_fss_basic_read_print_file_error_ + +#ifndef _di_fss_basic_read_print_number_argument_error_ + void fss_basic_read_print_number_argument_error(const fl_color_context context, const f_string function_name, const f_string parameter_name, const f_string argument, const f_status status) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + else if (status == f_invalid_number) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: the argument '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", argument); + fl_color_print(f_standard_error, context.error, context.reset, "' is not a valid number for the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "--%s", parameter_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + else if (status == f_underflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: the argument '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", argument); + fl_color_print(f_standard_error, context.error, context.reset, "' is too small for the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "--%s", parameter_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: the argument '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", argument); + fl_color_print(f_standard_error, context.error, context.reset, "' is too large for the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "--%s", parameter_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + else if (status == f_negative_number) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: the argument '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", argument); + fl_color_print(f_standard_error, context.error, context.reset, "' is negative, which is not allowed for the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "--%s", parameter_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + else { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: An unhandled error ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%u", status); + fl_color_print(f_standard_error, context.error, context.reset, ") has occured while calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print(f_standard_error, context.error, context.reset, "' for the parameter '"); + fl_color_print(f_standard_error, context.notable, context.reset, "--%s", parameter_name); + fl_color_print(f_standard_error, context.error, context.reset, "' with the value '"); + fl_color_print(f_standard_error, context.notable, context.reset, "%s", argument); + fl_color_print_line(f_standard_error, context.error, context.reset, "'."); + } + } +#endif // _di_fss_basic_read_print_number_argument_error_ + +#ifndef _di_fss_basic_read_main_preprocess_depth_ + f_return_status fss_basic_read_main_preprocess_depth(const f_console_arguments arguments, const fss_basic_read_data data, fss_basic_read_depths *depths) { + f_status status = f_none; + + // pre-process the depth and depth-sensitive parameters. + if (data.parameters[fss_basic_read_parameter_depth].result == f_console_result_additional) { + macro_fss_basic_read_depths_new(status, (*depths), data.parameters[fss_basic_read_parameter_depth].locations.used); + if (f_status_is_error(status)) { + f_status status2 = f_none; + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + + macro_fss_basic_read_depths_delete(status2, (*depths)); + return f_status_set_error(f_invalid_parameter); + } + + f_array_length depth_position = data.parameters[fss_basic_read_parameter_depth].additional.array[0]; + f_array_length at_index = 0; + f_array_length name_index = 0; + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->array[0].parameter = 0; + depths->array[0].position = 0; + depths->used = 1; + + f_string_length depth_previous = depths->array[0].depth; + f_string_length depth_current = depths->array[0].depth; + + if (data.parameters[fss_basic_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_basic_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_basic_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_basic_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_read_parameter_at].additional.array[at_index] > data.parameters[fss_basic_read_parameter_depth].additional.array[1]) { + break; + } + } + + depths->array[0].parameter = fss_basic_read_parameter_at; + } + } // for + } + + if (data.parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_basic_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_basic_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_basic_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_read_parameter_name].additional.array[name_index] > data.parameters[fss_basic_read_parameter_depth].additional.array[1]) { + break; + } + } + + if (depths->array[0].parameter == fss_basic_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_basic_read_long_at, fss_basic_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].parameter = fss_basic_read_parameter_name; + } + } // for + } + + for (f_array_length i = 1; i < data.parameters[fss_basic_read_parameter_depth].locations.used; i++) { + depth_position = data.parameters[fss_basic_read_parameter_depth].additional.array[i]; + depth_current = (f_string_length) atoll(arguments.argv[depth_position]); + + if (depth_current > depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be specified before the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (depth_current == depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be the same as the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (data.parameters[fss_basic_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_basic_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_basic_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_basic_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_read_parameter_at].additional.array[at_index] > data.parameters[fss_basic_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + depths->array[i].parameter = fss_basic_read_parameter_at; + depths->array[i].position = data.parameters[fss_basic_read_parameter_at].additional.array[i]; + } + } // for + } + + if (data.parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_basic_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_basic_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_basic_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_basic_read_parameter_name].additional.array[name_index] > data.parameters[fss_basic_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + if (depths->array[i].parameter == fss_basic_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_basic_read_long_at, fss_basic_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[i].parameter = fss_basic_read_parameter_name; + depths->array[i].position = data.parameters[fss_basic_read_parameter_name].additional.array[i]; + } + } // for + } + + depths->array[i].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->used++; + } // for + } + // when no depth parameter is specified, provide a implicit depth of 0 when depth-sensitive parameters are in use. + else { + if (data.parameters[fss_basic_read_parameter_at].result == f_console_result_additional) { + if (data.parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '%s' and '%s' parameters must not be specified at the same time.", fss_basic_read_long_name, fss_basic_read_long_object); + return f_status_set_error(f_invalid_parameter); + } + + macro_fss_basic_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_basic_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_basic_read_parameter_at; + depths->array[0].position = 0; + depths->used = 1; + } + else if (data.parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { + macro_fss_basic_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_basic_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_basic_read_parameter_name; + depths->array[0].position = 0; + depths->used = 1; + } + } + + return f_none; + } +#endif // _di_fss_basic_read_main_preprocess_depth_ + #ifndef _di_fss_basic_read_main_process_file_ - f_return_status fss_basic_read_main_process_file(const f_console_arguments arguments, fss_basic_read_data *data, const f_string filename, const f_string_length target) { + f_return_status fss_basic_read_main_process_file(const f_console_arguments arguments, fss_basic_read_data *data, const f_string filename, const fss_basic_read_depths depths) { f_status status = f_none; f_status status2 = f_none; - f_string_length current = 0; - f_string_length found = 0; - { f_string_location input = f_string_location_initialize; input.start = 0; - input.stop = data->buffer.used - 1; + input.stop = data->buffer.used - 1; status = fll_fss_basic_read(&data->buffer, &input, &data->objects, &data->contents); @@ -40,11 +298,10 @@ extern "C" { fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'", f_status_set_error(status), filename); } - fss_basic_read_delete_data(data); return f_status_set_error(status); } else if (status == f_no_data_on_stop || status == f_no_data_on_eos) { - // clear buffers, then attempt the next file + // clear buffers, then attempt the next file. f_macro_fss_contents_delete(status2, data->contents); f_macro_fss_objects_delete(status2, data->objects); f_macro_string_dynamic_delete(status2, data->buffer); @@ -53,89 +310,97 @@ extern "C" { } } - // now that the file has been read, process the objects and contents - if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_read_parameter_name].result == f_console_result_none) { - fprintf(f_standard_output, "%u\n", (unsigned int) data->objects.used); + // depth is always 0 in this standard, so when specifying --total with --object, just print the total of all. + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found) { + if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_none) { + fprintf(f_standard_output, "%llu%c", data->objects.used, f_string_eol); + return f_none; + } } - else { - current = 0; - if (data->parameters[fss_basic_read_parameter_name].result == f_console_result_none) { - if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_none) { - for (; current < data->objects.used; current++) { - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional && found == target)) { - if (data->contents.array[current].used > 0) { - f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[current].array[0]); - fprintf(f_standard_output, "\n"); - } - else { - // for all objects with no data, print a newline - fprintf(f_standard_output, "\n"); - } - } + f_string_length select = 0; + if (data->parameters[fss_basic_read_parameter_select].result == f_console_result_additional) { + status = fl_console_parameter_to_number_unsigned(arguments.argv[data->parameters[fss_basic_read_parameter_select].additional.array[0]], &select); - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional) { - if (found == target) { - break; - } - else { - found++; - } - } - } // for - } - else { - for (; current < data->objects.used; current++) { - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional && found == target)) { - f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); - fprintf(f_standard_output, "\n"); - } + if (f_status_is_error(status)) { + fss_basic_read_print_number_argument_error(data->context, "fl_console_parameter_to_number_unsigned", fss_basic_read_long_select, arguments.argv[data->parameters[fss_basic_read_parameter_select].additional.array[0]], f_status_set_fine(status)); + return status; + } - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional) { - if (found == target) { - break; - } - else { - found++; - } - } - } // for - } + // this standard does not support multiple content groups, so a select value of anything other than 0 should return nothing. + if (select > 0) { + return f_none; } - else { - current = 0; + } - f_string_length total = 0; - f_string_length name_length = 0; - f_string_length argv_length = 0; + // now that the file has been read, process the objects and contents. + if (depths.used > 0 && depths.array[0].parameter == fss_basic_read_parameter_name) { + /* + // @todo: this if-block is not updated. + // @todo: printing conditions need to handle --line as well as --relative. + // @todo: when --total is specified, process it here (and --relative will matter). + f_string_length total = 0; + f_string_length name_length = 0; + f_string_length argv_length = 0; + f_string_length found = 0; - if (data->parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { - argv_length = strlen(arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]]); + if (data->parameters[fss_basic_read_parameter_name].result == f_console_result_additional) { + argv_length = strlen(arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]]); - if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_none) { - for (; current < data->objects.used; current++) { - name_length = data->objects.array[current].stop - data->objects.array[current].start + 1; + if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_none) { + for (f_string_length i = 0; i < data->objects.used; i++) { + name_length = data->objects.array[i].stop - data->objects.array[i].start + 1; - if (name_length == argv_length) { - if (fl_string_compare(data->buffer.string + data->objects.array[current].start, arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { + if (name_length == argv_length) { + if (fl_string_compare(data->buffer.string + data->objects.array[i].start, arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional && found == target)) { - if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found) { - total++; + if (data->parameters[fss_basic_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_at].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found) { + total++; + } + else { + if (data->contents.array[i].used > 0) { + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[i].array[0]); + fprintf(f_standard_output, "%c", f_string_eol); } else { - if (data->contents.array[current].used > 0) { - f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[current].array[0]); - fprintf(f_standard_output, "\n"); - } - else { - // for all objects with no data, print a newline - fprintf(f_standard_output, "\n"); - } + // for all objects with no data, print a newline. + fprintf(f_standard_output, "%c", f_string_eol); } } + } + + if (data->parameters[fss_basic_read_parameter_at].result == f_console_result_additional) { + if (found == target) { + break; + } + else { + found++; + } + } + } + } + } // for - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_read_parameter_at].result == f_console_result_none) { + fprintf(f_standard_output, f_string_length_printf "%s%c", total, f_string_eol); + } + } + else { + // when and because the object parameter is specified, the name parameter refers to the content instead of the object. + // therefore, make the search on the content and display the object. + for (f_string_length i = 0; i < data->contents.used; i++) { + if (data->contents.array[i].used > 0) { + name_length = data->contents.array[i].array[0].stop - data->contents.array[i].array[0].start + 1; + + if (name_length == argv_length) { + if (fl_string_compare(data->buffer.string + data->contents.array[i].array[0].start, arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { + if (data->parameters[fss_basic_read_parameter_at].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_at].result == f_console_result_additional && found == target)) { + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[i]); + fprintf(f_standard_output, "%c", f_string_eol); + } + + if (data->parameters[fss_basic_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -145,43 +410,104 @@ extern "C" { } } } + } + } // for + } + } +*/ + return f_none; + } + + if (data->parameters[fss_basic_read_parameter_object].result == f_console_result_none) { + if (depths.used > 0 && depths.array[0].parameter == fss_basic_read_parameter_at) { + f_string_length target = (f_string_length) atoll(arguments.argv[depths.array[0].position]); + + if (target >= data->objects.used) { + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_additional) { + fprintf(f_standard_output, "0%c", f_string_eol); + } + + return f_none; + } + + if (data->parameters[fss_basic_read_parameter_line].result == f_console_result_additional) { + if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_additional) { + f_string_length total = 0; + + for (f_string_length i = data->contents.array[target].array[0].start; i < data->contents.array[target].array[0].stop; i++) { + if (data->buffer.string[i] == f_string_eol) { + total++; + } } // for - if (data->parameters[fss_basic_read_parameter_total].result == f_console_result_found && data->parameters[fss_basic_read_parameter_count].result == f_console_result_none) { - fprintf(f_standard_output, f_string_length_printf "\n", total); - } + fprintf(f_standard_output, "%llu%c", total, f_string_eol); } else { - // when and because the object parameter is specified, the name parameter refers to the content instead of the object - // therefore, make the search on the content and display the object - for (; current < data->contents.used; current++) { - if (data->contents.array[current].used > 0) { - name_length = data->contents.array[current].array[0].stop - data->contents.array[current].array[0].start + 1; - - if (name_length == argv_length) { - if (fl_string_compare(data->buffer.string + data->contents.array[current].array[0].start, arguments.argv[data->parameters[fss_basic_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_none || (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional && found == target)) { - f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); - fprintf(f_standard_output, "\n"); - } + f_string_length line = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_read_parameter_line].additional.array[0]]); + f_string_length total = 0; + f_string_location line_position = f_string_location_initialize; - if (data->parameters[fss_basic_read_parameter_count].result == f_console_result_additional) { - if (found == target) { - break; - } - else { - found++; - } - } + line_position.start = data->contents.array[target].array[0].start; + for (f_string_length i = line_position.start; i <= data->contents.array[target].array[0].stop; i++) { + if (data->buffer.string[i] == f_string_eol) { + total++; + + if (total == line) { + if (i != line_position.start) { + line_position.stop = i - 1; + + f_print_string_dynamic_partial(f_standard_output, data->buffer, line_position); } + + fprintf(f_standard_output, "%c", f_string_eol); + break; } } } // for } + + return f_none; } + + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[target].array[0]); + + // newline is printed even when there is no content for this object. + fprintf(f_standard_output, "%c", f_string_eol); + + return f_none; } + + for (f_string_length i = 0; i < data->objects.used; i++) { + if (data->contents.array[i].used > 0) { + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[i].array[0]); + } + + // newline is printed even when there is no content for this object. + fprintf(f_standard_output, "%c", f_string_eol); + } // for + + return f_none; + } + + if (depths.used > 0 && depths.array[0].parameter == fss_basic_read_parameter_at) { + f_string_length target = (f_string_length) atoll(arguments.argv[depths.array[0].position]); + + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[target]); + + // newline is printed even when there is no content for this object. + fprintf(f_standard_output, "%c", f_string_eol); + + return f_none; } + // @todo: when --total is specified, process it here (and --relative will matter) for standards that support nesting (also handle other nesting state changes here). + for (f_string_length i = 0; i < data->objects.used; i++) { + f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[i]); + + // newline is printed for all objects. + fprintf(f_standard_output, "%c", f_string_eol); + } // for + return f_none; } #endif // _di_fss_basic_read_main_process_file_ diff --git a/level_3/fss_basic_read/c/private-fss_basic_read.h b/level_3/fss_basic_read/c/private-fss_basic_read.h index 8958e15..7329c9f 100644 --- a/level_3/fss_basic_read/c/private-fss_basic_read.h +++ b/level_3/fss_basic_read/c/private-fss_basic_read.h @@ -12,12 +12,115 @@ extern "C" { #endif -#ifdef __cplusplus -} // extern "C" -#endif +/** + * A structure of parameters applied at some depth. + * + * depth: the depth number in which this is to be processed at. + * parameter: the index representing the parameter enum of either the "at" parameter or the "name" parameter. + * position: the parameter position index within the argv representing the value associated with the designated parameter. + */ +#ifndef _di_fss_basic_read_depth_ + typedef struct { + f_string_length depth; + + f_array_length parameter; + f_array_length position; + } fss_basic_read_depth; + + #define fss_basic_read_depth_initialize \ + { \ + 0, \ + f_array_length_initialize, \ + f_array_length_initialize, \ + } +#endif // _di_fss_basic_read_depth_ + +/** + * An array of depth parameters. + * + * array: the array of depths. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_fss_basic_read_depths_ + typedef struct { + fss_basic_read_depth *array; + + f_array_length size; + f_array_length used; + } fss_basic_read_depths; + + #define fss_basic_read_depths_initialize { 0, 0, 0 } + + #define macro_fss_basic_read_depths_clear(depths) f_macro_memory_structure_clear(depths) + + #define macro_fss_basic_read_depths_new(status, depths, length) f_macro_memory_structure_new(status, depths, fss_basic_read_depths, length) + + #define macro_fss_basic_read_depths_delete(status, depths) f_macro_memory_structure_delete(status, depths, fss_basic_read_depths) + #define macro_fss_basic_read_depths_destroy(status, depths) f_macro_memory_structure_destroy(status, depths, fss_basic_read_depths) + + #define macro_fss_basic_read_depths_resize(status, depths, new_length) f_macro_memory_structure_resize(status, depths, fss_basic_read_depths, new_length) + #define macro_fss_basic_read_depths_adjust(status, depths, new_length) f_macro_memory_structure_adjust(status, depths, fss_basic_read_depths, new_length) +#endif // _di_fss_basic_read_depths_ + +/** + * Print file error messages. + * + * @param context + * The color context information to use when printing. + * @param function_name + * The name of the function responsible for the error. + * @param file_name + * The name of the file with the error. + * @param status + * The status code representing the error. + */ +#ifndef _di_fss_basic_read_print_file_error_ + extern void fss_basic_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_read_print_file_error_ + +/** + * Print number parameter argument error messages. + * + * @param context + * The color context information to use when printing. + * @param function_name + * The name of the function responsible for the error. + * @param parameter_name + * The name of the parameter responsible for the error. + * @param argument + * The value of the argument that is invalid. + * @param status + * The status code representing the error. + */ +#ifndef _di_fss_basic_read_print_number_argument_error_ + extern void fss_basic_read_print_number_argument_error(const fl_color_context context, const f_string function_name, const f_string parameter_name, const f_string argument, const f_status status) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_read_print_number_argument_error_ + +/** + * Pre-process the parameters, parsing out and handling the depth and depth related parameters. + * + * @param arguments + * The console arguments to pre-process. + * @param data + * The Program specific data. + * @param depths + * This stores the pre-processed depth parameters. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_read_main_preprocess_depth_ + extern f_return_status fss_basic_read_main_preprocess_depth(const f_console_arguments arguments, const fss_basic_read_data data, fss_basic_read_depths *depths) f_gcc_attribute_visibility_internal; +#endif // _di_fss_basic_read_main_preprocess_depth_ #ifndef _di_fss_basic_read_main_process_file_ - extern f_return_status fss_basic_read_main_process_file(const f_console_arguments arguments, fss_basic_read_data *data, const f_string filename, const f_string_length target) f_gcc_attribute_visibility_internal; + extern f_return_status fss_basic_read_main_process_file(const f_console_arguments arguments, fss_basic_read_data *data, const f_string filename, const fss_basic_read_depths depths) f_gcc_attribute_visibility_internal; #endif // _di_fss_basic_read_main_process_file_ +#ifdef __cplusplus +} // extern "C" +#endif + #endif // _PRIVATE_fss_basic_read_h diff --git a/level_3/fss_basic_write/c/fss_basic_write.c b/level_3/fss_basic_write/c/fss_basic_write.c index 20d368f..b4d31a5 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.c +++ b/level_3/fss_basic_write/c/fss_basic_write.c @@ -54,7 +54,7 @@ extern "C" { } else { f_array_length counter = 0; - f_bool object = (data->parameters[fss_basic_write_parameter_object].result == f_console_result_found); + bool object = (data->parameters[fss_basic_write_parameter_object].result == f_console_result_found); f_string_dynamic buffer = f_string_dynamic_initialize; f_string_location location = f_string_location_initialize; @@ -207,6 +207,7 @@ extern "C" { f_string_length i = 0; while (i < fss_basic_write_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_basic_write/c/fss_basic_write.h b/level_3/fss_basic_write/c/fss_basic_write.h index 103ec2f..ddc537f 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.h +++ b/level_3/fss_basic_write/c/fss_basic_write.h @@ -89,7 +89,7 @@ extern "C" { f_console_parameter parameters[fss_basic_write_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_basic_write_data; diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.c b/level_3/fss_extended_list_read/c/fss_extended_list_read.c index 62f29a3..add03a0 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.c +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.c @@ -17,15 +17,90 @@ extern "C" { printf("%c", f_string_eol); - fll_program_print_help_option(data.context, fss_extended_list_read_short_name, fss_extended_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find and print content from this object name."); - fll_program_print_help_option(data.context, fss_extended_list_read_short_count, fss_extended_list_read_long_count, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find a specific occurrence of the object."); - fll_program_print_help_option(data.context, fss_extended_list_read_short_total, fss_extended_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects in this file."); - fll_program_print_help_option(data.context, fss_extended_list_read_short_object, fss_extended_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); - fll_program_print_help_option(data.context, fss_extended_list_read_short_size, fss_extended_list_read_long_size, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print total lines in the given content."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_at, fss_extended_list_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric index."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_depth, fss_extended_list_read_long_depth, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric depth."); fll_program_print_help_option(data.context, fss_extended_list_read_short_line, fss_extended_list_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print only the content at the given line."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_name, fss_extended_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object with this name."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_object, fss_extended_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_select, fss_extended_list_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select sub-content at this index."); + fll_program_print_help_option(data.context, fss_extended_list_read_short_total, fss_extended_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects."); fll_program_print_help_usage(data.context, fss_extended_list_read_name, "filename(s)"); + printf(" This program will print the content associated with the given object and content data based on the FSS-0003 Extended List standard.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" When using the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_depth); + printf(" option, an order of operations is enforced on the parameters.%c", f_string_eol); + + printf(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_at); + printf(": An object index at the specified depth.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_depth); + printf(": A new depth within the specified depth, indexed from the root.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_name); + printf(": An object name at the specified depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_depth); + printf(" should be in numeric order, but values in between may be skipped.%c", f_string_eol); + printf(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%c", f_string_eol); + printf(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_at); + printf(" cannot be used with the parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_name); + printf(" at the same depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_select); + printf(" selects a content index at a given depth.%c", f_string_eol); + printf(" (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" Specify both "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_total); + printf(" and the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_line); + printf(" parameters to get the total lines.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" This program may support parameters, such as "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_depth); + printf(" or "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_select); + printf(", even if not supported by the standard.%c", f_string_eol); + printf(" This is done to help ensure consistency for scripting.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_depth); + printf(", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_list_read_long_select); + printf(", if the standard doesn't support multiple content groups, then only a select of 0 would be valid."); + + printf("%c%c", f_string_eol, f_string_eol); + return f_none; } #endif // _di_fss_extended_list_read_print_help_ @@ -40,15 +115,16 @@ extern "C" { f_console_parameter_ids choices = { ids, 3 }; status = fll_program_process_parameters(arguments, parameters, choices, &data->remaining, &data->context); - } - if (f_status_is_error(status)) { - fss_extended_list_read_delete_data(data); - return f_status_set_error(status); + if (f_status_is_error(status)) { + fss_extended_list_read_delete_data(data); + return f_status_set_error(status); + } + + status = f_none; } f_status status2 = f_none; - status = f_none; // execute parameter results if (data->parameters[fss_extended_list_read_parameter_help].result == f_console_result_found) { @@ -58,12 +134,41 @@ extern "C" { fll_program_print_version(fss_extended_list_read_version); } else if (data->remaining.used > 0 || data->process_pipe) { + if (data->parameters[fss_extended_list_read_parameter_object].result == f_console_result_found) { + if (data->parameters[fss_extended_list_read_parameter_line].result == f_console_result_found) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_list_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_list_read_long_line); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + + if (data->parameters[fss_extended_list_read_parameter_select].result == f_console_result_additional) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_list_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_list_read_long_select); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + } + f_string_length counter = 0; f_string_length target = 0; f_string_length original_size = data->file_position.total_elements; - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional) { - target = (f_string_length) atoll(arguments.argv[data->parameters[fss_extended_list_read_parameter_count].additional.array[0]]); + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { + target = (f_string_length) atoll(arguments.argv[data->parameters[fss_extended_list_read_parameter_at].additional.array[0]]); + } + + status = fss_extended_list_read_main_preprocess_depth(arguments, *data, &depths); + if (f_status_is_error(status)) { + macro_fss_extended_list_read_depths_delete(status2, depths); + fss_extended_list_read_delete_data(data); + return status; } if (data->process_pipe) { @@ -74,24 +179,7 @@ extern "C" { status = fl_file_read_fifo(file, &data->buffer); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", "-"); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", "-"); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", "-"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_extended_list_read_print_file_error(data->context, "fl_file_read_fifo", "-", f_status_set_fine(status)); fss_extended_list_read_delete_data(data); return status; } @@ -116,24 +204,7 @@ extern "C" { data->file_position.total_elements = original_size; if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_extended_list_read_print_file_error(data->context, "f_file_open", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_extended_list_read_delete_data(data); return f_status_set_error(status); } @@ -157,30 +228,7 @@ extern "C" { f_file_close(&file); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } - else if (status == f_overflow) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_not_open) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_seek_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_read_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_allocation_error || status == f_reallocation_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", f_status_set_error(status)); - } - + fss_extended_list_read_print_file_error(data->context, "fl_file_read", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_extended_list_read_delete_data(data); return f_status_set_error(status); } @@ -198,7 +246,7 @@ extern "C" { } // for } else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files"); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files."); status = f_status_set_error(f_invalid_parameter); } @@ -213,6 +261,7 @@ extern "C" { f_string_length i = 0; while (i < fss_extended_list_read_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.h b/level_3/fss_extended_list_read/c/fss_extended_list_read.h index b1cca66..d45c25c 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.h +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.h @@ -54,19 +54,21 @@ extern "C" { #endif // _di_fss_extended_list_read_name_ #ifndef _di_fss_extended_list_read_defines_ + #define fss_extended_list_read_short_at "a" + #define fss_extended_list_read_short_depth "d" + #define fss_extended_list_read_short_line "l" #define fss_extended_list_read_short_name "n" - #define fss_extended_list_read_short_count "c" - #define fss_extended_list_read_short_total "t" #define fss_extended_list_read_short_object "o" - #define fss_extended_list_read_short_size "s" - #define fss_extended_list_read_short_line "l" + #define fss_extended_list_read_short_select "s" + #define fss_extended_list_read_short_total "t" + #define fss_extended_list_read_long_at "at" + #define fss_extended_list_read_long_depth "depth" + #define fss_extended_list_read_long_line "line" #define fss_extended_list_read_long_name "name" - #define fss_extended_list_read_long_count "count" - #define fss_extended_list_read_long_total "total" #define fss_extended_list_read_long_object "object" - #define fss_extended_list_read_long_size "size" - #define fss_extended_list_read_long_line "line" + #define fss_extended_list_read_long_select "select" + #define fss_extended_list_read_long_total "total" enum { fss_extended_list_read_parameter_help, @@ -75,12 +77,13 @@ extern "C" { fss_extended_list_read_parameter_no_color, fss_extended_list_read_parameter_version, + fss_extended_list_read_parameter_at, + fss_extended_list_read_parameter_depth, + fss_extended_list_read_parameter_line, fss_extended_list_read_parameter_name, - fss_extended_list_read_parameter_count, - fss_extended_list_read_parameter_total, fss_extended_list_read_parameter_object, - fss_extended_list_read_parameter_size, - fss_extended_list_read_parameter_line, + fss_extended_list_read_parameter_select, + fss_extended_list_read_parameter_total, }; #define f_console_parameter_initialize_fss_extended_list_read \ @@ -90,15 +93,16 @@ extern "C" { f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, f_false, f_console_type_inverse), \ + f_console_parameter_initialize(fss_extended_list_read_short_at, fss_extended_list_read_long_at, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_list_read_short_depth, fss_extended_list_read_long_depth, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_list_read_short_line, fss_extended_list_read_long_line, 0, f_true, f_console_type_normal), \ f_console_parameter_initialize(fss_extended_list_read_short_name, fss_extended_list_read_long_name, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_list_read_short_count, fss_extended_list_read_long_count, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_list_read_short_total, fss_extended_list_read_long_total, 0, f_false, f_console_type_normal), \ f_console_parameter_initialize(fss_extended_list_read_short_object, fss_extended_list_read_long_object, 0, f_false, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_list_read_short_size, fss_extended_list_read_long_size, 0, f_false, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_list_read_short_line, fss_extended_list_read_long_line, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_list_read_short_select, fss_extended_list_read_long_select, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_list_read_short_total, fss_extended_list_read_long_total, 0, f_false, f_console_type_normal), \ } - #define fss_extended_list_read_total_parameters 11 + #define fss_extended_list_read_total_parameters 13 #endif // _di_fss_extended_list_read_defines_ #ifndef _di_fss_extended_list_read_data_ @@ -110,7 +114,7 @@ extern "C" { f_fss_content_nests contents; f_file_position file_position; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_extended_list_read_data; diff --git a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c index b0df160..5b35bd6 100644 --- a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c +++ b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.c @@ -5,6 +5,217 @@ extern "C" { #endif +#ifndef _di_fss_extended_list_read_print_file_error_ + void fss_extended_list_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_file_not_open) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: The 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, "' is no longer open."); + } + else if (status == f_file_seek_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A seek error occurred while accessing the 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, "'."); + } + else if (status == f_file_read_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A read error occurred while accessing the 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, "'."); + } + else if (status == f_file_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to find the 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, "'."); + } + else if (status == f_file_open_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to open the 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, "'."); + } + else if (status == f_file_descriptor_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: File descriptor error while trying to open the 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, "'."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_allocation_error || status == f_reallocation_error) { + fl_color_print_line(f_standard_error, context.error, context.reset, "CRITICAL ERROR: unable to allocate memory."); + } + else { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: An unhandled error ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%u", status); + fl_color_print(f_standard_error, context.error, context.reset, ") has occured while calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + } +#endif // _di_fss_extended_list_read_print_file_error_ + +#ifndef _di_fss_extended_list_read_main_preprocess_depth_ + f_return_status fss_extended_list_read_main_preprocess_depth(const f_console_arguments arguments, const fss_extended_list_read_data data, fss_extended_list_read_depths *depths) { + f_status status = f_none; + + // pre-process the depth and depth-sensitive parameters. + if (data.parameters[fss_extended_list_read_parameter_depth].result == f_console_result_additional) { + macro_fss_extended_list_read_depths_new(status, (*depths), data.parameters[fss_extended_list_read_parameter_depth].locations.used); + if (f_status_is_error(status)) { + f_status status2 = f_none; + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + + macro_fss_extended_list_read_depths_delete(status2, (*depths)); + return f_status_set_error(f_invalid_parameter); + } + + f_array_length depth_position = data.parameters[fss_extended_list_read_parameter_depth].additional.array[0]; + f_array_length at_index = 0; + f_array_length name_index = 0; + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->array[0].parameter = 0; + depths->array[0].position = 0; + depths->used = 1; + + f_string_length depth_previous = depths->array[0].depth; + f_string_length depth_current = depths->array[0].depth; + + if (data.parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_extended_list_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_extended_list_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_extended_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_list_read_parameter_at].additional.array[at_index] > data.parameters[fss_extended_list_read_parameter_depth].additional.array[1]) { + break; + } + } + + depths->array[0].parameter = fss_extended_list_read_parameter_at; + } + } // for + } + + if (data.parameters[fss_extended_list_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_extended_list_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_extended_list_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_extended_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_list_read_parameter_name].additional.array[name_index] > data.parameters[fss_extended_list_read_parameter_depth].additional.array[1]) { + break; + } + } + + if (depths->array[0].parameter == fss_extended_list_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_extended_list_read_long_at, fss_extended_list_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].parameter = fss_extended_list_read_parameter_name; + } + } // for + } + + for (f_array_length i = 1; i < data.parameters[fss_extended_list_read_parameter_depth].locations.used; i++) { + depth_position = data.parameters[fss_extended_list_read_parameter_depth].additional.array[i]; + depth_current = (f_string_length) atoll(arguments.argv[depth_position]); + + if (depth_current > depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be specified before the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (depth_current == depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be the same as the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (data.parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_extended_list_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_extended_list_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_extended_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_list_read_parameter_at].additional.array[at_index] > data.parameters[fss_extended_list_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + depths->array[i].parameter = fss_extended_list_read_parameter_at; + depths->array[i].position = data.parameters[fss_extended_list_read_parameter_at].additional.array[i]; + } + } // for + } + + if (data.parameters[fss_extended_list_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_extended_list_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_extended_list_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_extended_list_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_list_read_parameter_name].additional.array[name_index] > data.parameters[fss_extended_list_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + if (depths->array[i].parameter == fss_extended_list_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_extended_list_read_long_at, fss_extended_list_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[i].parameter = fss_extended_list_read_parameter_name; + depths->array[i].position = data.parameters[fss_extended_list_read_parameter_name].additional.array[i]; + } + } // for + } + + depths->array[i].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->used++; + } // for + } + // when no depth parameter is specified, provide a implicit depth of 0 when depth-sensitive parameters are in use. + else { + if (data.parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { + if (data.parameters[fss_extended_list_read_parameter_name].result == f_console_result_additional) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '%s' and '%s' parameters must not be specified at the same time.", fss_extended_list_read_long_name, fss_extended_list_read_long_object); + return f_status_set_error(f_invalid_parameter); + } + + macro_fss_extended_list_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_extended_list_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_extended_list_read_parameter_at; + depths->array[0].position = 0; + depths->used = 1; + } + else if (data.parameters[fss_extended_list_read_parameter_name].result == f_console_result_additional) { + macro_fss_extended_list_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_extended_list_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_extended_list_read_parameter_name; + depths->array[0].position = 0; + depths->used = 1; + } + } + + return f_none; + } +#endif // _di_fss_extended_list_read_main_preprocess_depth_ + #ifndef _di_fss_extended_list_read_main_process_file_ f_return_status fss_extended_list_read_main_process_file(const f_console_arguments arguments, fss_extended_list_read_data *data, const f_string filename, const f_string_length target) { f_status status = f_none; @@ -55,7 +266,7 @@ extern "C" { // now that all of the files have been read, process the objects and contents if (data->parameters[fss_extended_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_extended_list_read_parameter_name].result == f_console_result_none) { - fprintf(f_standard_output, "%u\n", (unsigned int) data->objects.used); + fprintf(f_standard_output, "%llu\n", data->objects.used); } else { current = 0; @@ -63,9 +274,9 @@ extern "C" { if (data->parameters[fss_extended_list_read_parameter_name].result == f_console_result_none) { if (data->parameters[fss_extended_list_read_parameter_object].result == f_console_result_none) { for (; current < data->objects.used; current++) { - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional && found == target)) { - if (data->parameters[fss_extended_list_read_parameter_size].result == f_console_result_found) { + /*if (data->parameters[fss_extended_list_read_parameter_size].result == f_console_result_found) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].range.start; f_string_length size = 0; @@ -83,7 +294,7 @@ extern "C" { fprintf(f_standard_output, "0\n"); } } - else if (data->parameters[fss_extended_list_read_parameter_line].result == f_console_result_additional) { + else*/ if (data->parameters[fss_extended_list_read_parameter_line].result == f_console_result_additional) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].range.start; f_string_length position = 0; @@ -127,7 +338,7 @@ extern "C" { } } - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -139,12 +350,12 @@ extern "C" { } else { for (; current < data->objects.used; current++) { - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -172,7 +383,7 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->objects.array[current].start, arguments.argv[data->parameters[fss_extended_list_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_extended_list_read_parameter_size].result == f_console_result_found) { + /*if (data->parameters[fss_extended_list_read_parameter_size].result == f_console_result_found) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].range.start; f_string_length size = 0; @@ -190,7 +401,7 @@ extern "C" { fprintf(f_standard_output, "0\n"); } } - else if (data->parameters[fss_extended_list_read_parameter_line].result == f_console_result_additional) { + else*/ if (data->parameters[fss_extended_list_read_parameter_line].result == f_console_result_additional) { if (data->contents.array[current].used > 0) { f_string_length counter = data->contents.array[current].array[0].range.start; f_string_length position = 0; @@ -227,7 +438,7 @@ extern "C" { } } else { - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional && found == target)) { if (data->parameters[fss_extended_list_read_parameter_total].result == f_console_result_found) { total++; } @@ -240,7 +451,7 @@ extern "C" { } } - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -252,7 +463,7 @@ extern "C" { } } // for - if (data->parameters[fss_extended_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_none) { + if (data->parameters[fss_extended_list_read_parameter_total].result == f_console_result_found && data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_none) { fprintf(f_standard_output, f_string_length_printf "\n", total); } } @@ -265,12 +476,12 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->contents.array[current].array[0].range.start, arguments.argv[data->parameters[fss_extended_list_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_extended_list_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_list_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } diff --git a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h index ec5f589..36f911f 100644 --- a/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h +++ b/level_3/fss_extended_list_read/c/private-fss_extended_list_read.h @@ -11,13 +11,97 @@ #ifdef __cplusplus extern "C" { #endif +/** + * A structure of parameters applied at some depth. + * + * depth: the depth number in which this is to be processed at. + * parameter: the index representing the parameter enum of either the "at" parameter or the "name" parameter. + * position: the parameter position index within the argv representing the value associated with the designated parameter. + */ +#ifndef _di_fss_extended_list_read_depth_ + typedef struct { + f_string_length depth; -#ifdef __cplusplus -} // extern "C" -#endif + f_array_length parameter; + f_array_length position; + } fss_extended_list_read_depth; + + #define fss_extended_list_read_depth_initialize \ + { \ + 0, \ + f_array_length_initialize, \ + f_array_length_initialize, \ + } +#endif // _di_fss_extended_list_read_depth_ + +/** + * An array of depth parameters. + * + * array: the array of depths. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_fss_extended_list_read_depths_ + typedef struct { + fss_extended_list_read_depth *array; + + f_array_length size; + f_array_length used; + } fss_extended_list_read_depths; + + #define fss_extended_list_read_depths_initialize { 0, 0, 0 } + + #define macro_fss_extended_list_read_depths_clear(depths) f_macro_memory_structure_clear(depths) + + #define macro_fss_extended_list_read_depths_new(status, depths, length) f_macro_memory_structure_new(status, depths, fss_extended_list_read_depths, length) + + #define macro_fss_extended_list_read_depths_delete(status, depths) f_macro_memory_structure_delete(status, depths, fss_extended_list_read_depths) + #define macro_fss_extended_list_read_depths_destroy(status, depths) f_macro_memory_structure_destroy(status, depths, fss_extended_list_read_depths) + + #define macro_fss_extended_list_read_depths_resize(status, depths, new_length) f_macro_memory_structure_resize(status, depths, fss_extended_list_read_depths, new_length) + #define macro_fss_extended_list_read_depths_adjust(status, depths, new_length) f_macro_memory_structure_adjust(status, depths, fss_extended_list_read_depths, new_length) +#endif // _di_fss_extended_list_read_depths_ + +/** + * Print file error messages. + * + * @param context + * The color context information to use when printing. + * @param function_name + * The name of the function responsible for the error. + * @param file_name + * The name of the file with the error. + * @param status + * The status code representing the error. + */ +#ifndef _di_fss_extended_list_read_print_file_error_ + extern void fss_extended_list_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) f_gcc_attribute_visibility_internal; +#endif // _di_fss_extended_list_read_print_file_error_ + +/** + * Pre-process the parameters, parsing out and handling the depth and depth related parameters. + * + * @param arguments + * The console arguments to pre-process. + * @param data + * The Program specific data. + * @param depths + * This stores the pre-processed depth parameters. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_list_read_main_preprocess_depth_ + extern f_return_status fss_extended_list_read_main_preprocess_depth(const f_console_arguments arguments, const fss_extended_list_read_data data, fss_extended_list_read_depths *depths) f_gcc_attribute_visibility_internal; +#endif // _di_fss_extended_list_read_main_preprocess_depth_ #ifndef _di_fss_extended_list_read_main_process_file_ extern f_return_status fss_extended_list_read_main_process_file(const f_console_arguments arguments, fss_extended_list_read_data *data, const f_string filename, const f_string_length target) f_gcc_attribute_visibility_internal; #endif // _di_fss_extended_list_read_main_process_file_ +#ifdef __cplusplus +} // extern "C" +#endif + #endif // _PRIVATE_fss_extended_list_read_h diff --git a/level_3/fss_extended_read/c/fss_extended_read.c b/level_3/fss_extended_read/c/fss_extended_read.c index 451acad..b3eee88 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.c +++ b/level_3/fss_extended_read/c/fss_extended_read.c @@ -17,14 +17,90 @@ extern "C" { printf("%c", f_string_eol); - fll_program_print_help_option(data.context, fss_extended_read_short_name, fss_extended_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find and print content from this object name."); - fll_program_print_help_option(data.context, fss_extended_read_short_count, fss_extended_read_long_count, f_console_symbol_short_enable, f_console_symbol_long_enable, " Find a specific occurrence of the object."); - fll_program_print_help_option(data.context, fss_extended_read_short_total, fss_extended_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects in this file."); + fll_program_print_help_option(data.context, fss_extended_read_short_at, fss_extended_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric index."); + fll_program_print_help_option(data.context, fss_extended_read_short_depth, fss_extended_read_long_depth, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object at this numeric depth."); + fll_program_print_help_option(data.context, fss_extended_read_short_line, fss_extended_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print only the content at the given line."); + fll_program_print_help_option(data.context, fss_extended_read_short_name, fss_extended_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select object with this name."); fll_program_print_help_option(data.context, fss_extended_read_short_object, fss_extended_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the object instead of the content."); - fll_program_print_help_option(data.context, fss_extended_read_short_select, fss_extended_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select a specific content to print, default is 0."); + fll_program_print_help_option(data.context, fss_extended_read_short_select, fss_extended_read_long_select, f_console_symbol_short_enable, f_console_symbol_long_enable, " Select sub-content at this index."); + fll_program_print_help_option(data.context, fss_extended_read_short_total, fss_extended_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the total number of objects."); fll_program_print_help_usage(data.context, fss_extended_read_name, "filename(s)"); + printf(" This program will print the content associated with the given object and content data based on the FSS-0001 Extended standard.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" When using the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_depth); + printf(" option, an order of operations is enforced on the parameters.%c", f_string_eol); + + printf(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_at); + printf(": An object index at the specified depth.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_depth); + printf(": A new depth within the specified depth, indexed from the root.%c", f_string_eol); + + printf(" "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_name); + printf(": An object name at the specified depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_depth); + printf(" should be in numeric order, but values in between may be skipped.%c", f_string_eol); + printf(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%c", f_string_eol); + printf(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_at); + printf(" cannot be used with the parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_name); + printf(" at the same depth.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" The parameter "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_select); + printf(" selects a content index at a given depth.%c", f_string_eol); + printf(" (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" Specify both "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_total); + printf(" and the "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_line); + printf(" parameters to get the total lines.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" This program may support parameters, such as "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_depth); + printf(" or "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_select); + printf(", even if not supported by the standard.%c", f_string_eol); + printf(" This is done to help ensure consistency for scripting.%c", f_string_eol); + + printf("%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_depth); + printf(", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol); + + printf(" For parameters like "); + fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_extended_read_long_select); + printf(", if the standard doesn't support multiple content groups, then only a select of 0 would be valid."); + + printf("%c%c", f_string_eol, f_string_eol); + return f_none; } #endif // _di_fss_extended_read_print_help_ @@ -39,15 +115,16 @@ extern "C" { f_console_parameter_ids choices = { ids, 3 }; status = fll_program_process_parameters(arguments, parameters, choices, &data->remaining, &data->context); - } - if (f_status_is_error(status)) { - fss_extended_read_delete_data(data); - return f_status_set_error(status); + if (f_status_is_error(status)) { + fss_extended_read_delete_data(data); + return f_status_set_error(status); + } + + status = f_none; } f_status status2 = f_none; - status = f_none; // execute parameter results if (data->parameters[fss_extended_read_parameter_help].result == f_console_result_found) { @@ -57,13 +134,66 @@ extern "C" { fll_program_print_version(fss_extended_read_version); } else if (data->remaining.used > 0 || data->process_pipe) { + + if (data->parameters[fss_extended_read_parameter_object].result == f_console_result_found) { + if (data->parameters[fss_extended_read_parameter_line].result == f_console_result_found) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_read_long_line); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + + if (data->parameters[fss_extended_read_parameter_select].result == f_console_result_additional) { + fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_read_long_object); + fl_color_print(f_standard_error, data->context.error, data->context.reset, "' parameter with the '"); + fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_extended_read_long_select); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter."); + + return f_status_set_error(f_invalid_parameter); + } + } + f_string_length counter = 0; f_string_length target = 0; f_string_length select = 0; f_string_length original_size = data->file_position.total_elements; - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional) { - target = (f_string_length) atoll(arguments.argv[data->parameters[fss_extended_read_parameter_count].additional.array[0]]); + status = fss_extended_read_main_preprocess_depth(arguments, *data, &depths); + if (f_status_is_error(status)) { + macro_fss_extended_read_depths_delete(status2, depths); + fss_extended_read_delete_data(data); + return status; + } + + // This standard does not support nesting, so any depth greater than 0 can be predicted without processing the file. + if (depths.used > 0 && depths.array[0].depth > 0) { + if (data->parameters[fss_extended_read_parameter_total].result == f_console_result_found) { + fprintf(f_standard_output, "0%s", f_string_eol); + return f_none; + } + + return f_none; + } + + // This standard does not support nesting, so it can be determined that --name is in use with --total and --object, which is not allowed. + if (data->parameters[fss_extended_read_parameter_object].result == f_console_result_found) { + if (data->parameters[fss_extended_read_parameter_total].result == f_console_result_found && data->parameters[fss_extended_read_parameter_name].result == f_console_result_found) { + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '--%s' parameter, the ' '--%s' parameter, and the '--%s' parameter together.", fss_extended_read_long_object, fss_extended_read_long_line); + return f_status_set_error(f_invalid_parameter); + } + + if (data->parameters[fss_extended_read_parameter_select].result == f_console_result_additional) { + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '--%s' parameter with the '--%s' parameter.", fss_extended_read_long_object, fss_extended_read_long_select); + return f_status_set_error(f_invalid_parameter); + } + } + + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { + target = (f_string_length) atoll(arguments.argv[data->parameters[fss_extended_read_parameter_at].additional.array[0]]); } if (data->parameters[fss_extended_read_parameter_select].result == f_console_result_additional) { @@ -78,24 +208,7 @@ extern "C" { status = fl_file_read_fifo(file, &data->buffer); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", "-"); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", "-"); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", "-"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_extended_read_print_file_error(data->context, "fl_file_read_fifo", "-", f_status_set_fine(status)); fss_extended_read_delete_data(data); return f_status_set_error(status); } @@ -121,24 +234,7 @@ extern "C" { data->file_position.total_elements = original_size; if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } - else if (status == f_file_not_found) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_open_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_descriptor_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", f_status_set_error(status)); - } - + fss_extended_read_print_file_error(data->context, "f_file_open", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_extended_read_delete_data(data); return f_status_set_error(status); } @@ -162,30 +258,7 @@ extern "C" { f_file_close(&file); if (f_status_is_error(status)) { - status = f_status_set_fine(status); - - if (status == f_invalid_parameter) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } - else if (status == f_overflow) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_not_open) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_seek_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_file_read_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", arguments.argv[data->remaining.array[counter]]); - } - else if (status == f_allocation_error || status == f_reallocation_error) { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } - else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", f_status_set_error(status)); - } - + fss_extended_read_print_file_error(data->context, "fl_file_read", arguments.argv[data->remaining.array[counter]], f_status_set_fine(status)); fss_extended_read_delete_data(data); return f_status_set_error(status); } @@ -203,7 +276,7 @@ extern "C" { } // for } else { - fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files"); + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files."); status = f_status_set_error(f_invalid_parameter); } @@ -218,11 +291,12 @@ extern "C" { f_string_length i = 0; while (i < fss_extended_read_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while - f_macro_fss_content_nests_delete(status, data->contents); + f_macro_fss_contents_delete(status, data->contents); f_macro_fss_objects_delete(status, data->objects); f_macro_string_dynamic_delete(status, data->buffer); f_macro_string_lengths_delete(status, data->remaining); diff --git a/level_3/fss_extended_read/c/fss_extended_read.h b/level_3/fss_extended_read/c/fss_extended_read.h index 64f6311..87e1010 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.h +++ b/level_3/fss_extended_read/c/fss_extended_read.h @@ -54,17 +54,21 @@ extern "C" { #endif // _di_fss_extended_read_name_ #ifndef _di_fss_extended_read_defines_ + #define fss_extended_read_short_at "a" + #define fss_extended_read_short_depth "d" + #define fss_extended_read_short_line "l" #define fss_extended_read_short_name "n" - #define fss_extended_read_short_count "c" - #define fss_extended_read_short_total "t" #define fss_extended_read_short_object "o" #define fss_extended_read_short_select "s" + #define fss_extended_read_short_total "t" + #define fss_extended_read_long_at "at" + #define fss_extended_read_long_depth "depth" + #define fss_extended_read_long_line "line" #define fss_extended_read_long_name "name" - #define fss_extended_read_long_count "count" - #define fss_extended_read_long_total "total" #define fss_extended_read_long_object "object" #define fss_extended_read_long_select "select" + #define fss_extended_read_long_total "total" enum { fss_extended_read_parameter_help, @@ -73,11 +77,13 @@ extern "C" { fss_extended_read_parameter_no_color, fss_extended_read_parameter_version, + fss_extended_read_parameter_at, + fss_extended_read_parameter_depth, + fss_extended_read_parameter_line, fss_extended_read_parameter_name, - fss_extended_read_parameter_count, - fss_extended_read_parameter_total, fss_extended_read_parameter_object, fss_extended_read_parameter_select, + fss_extended_read_parameter_total, }; #define f_console_parameter_initialize_fss_extended_read \ @@ -87,14 +93,16 @@ extern "C" { f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, f_false, f_console_type_inverse), \ f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, f_false, f_console_type_inverse), \ + f_console_parameter_initialize(fss_extended_read_short_at, fss_extended_read_long_at, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_read_short_depth, fss_extended_read_long_depth, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_read_short_line, fss_extended_read_long_line, 0, f_true, f_console_type_normal), \ f_console_parameter_initialize(fss_extended_read_short_name, fss_extended_read_long_name, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_read_short_count, fss_extended_read_long_count, 0, f_true, f_console_type_normal), \ - f_console_parameter_initialize(fss_extended_read_short_total, fss_extended_read_long_total, 0, f_false, f_console_type_normal), \ f_console_parameter_initialize(fss_extended_read_short_object, fss_extended_read_long_object, 0, f_false, f_console_type_normal), \ f_console_parameter_initialize(fss_extended_read_short_select, fss_extended_read_long_select, 0, f_true, f_console_type_normal), \ + f_console_parameter_initialize(fss_extended_read_short_total, fss_extended_read_long_total, 0, f_false, f_console_type_normal), \ } - #define fss_extended_read_total_parameters 10 + #define fss_extended_read_total_parameters 12 #endif // _di_fss_extended_read_defines_ #ifndef _di_fss_extended_read_data_ @@ -106,7 +114,7 @@ extern "C" { f_fss_contents contents; f_file_position file_position; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_extended_read_data; diff --git a/level_3/fss_extended_read/c/private-fss_extended_read.c b/level_3/fss_extended_read/c/private-fss_extended_read.c index 8d5d91b..b1243d1 100644 --- a/level_3/fss_extended_read/c/private-fss_extended_read.c +++ b/level_3/fss_extended_read/c/private-fss_extended_read.c @@ -5,6 +5,217 @@ extern "C" { #endif +#ifndef _di_fss_extended_read_print_file_error_ + void fss_extended_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) { + + if (status == f_invalid_parameter) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_file_not_open) { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: The 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, "' is no longer open."); + } + else if (status == f_file_seek_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A seek error occurred while accessing the 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, "'."); + } + else if (status == f_file_read_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: A read error occurred while accessing the 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, "'."); + } + else if (status == f_file_not_found) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to find the 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, "'."); + } + else if (status == f_file_open_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Unable to open the 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, "'."); + } + else if (status == f_file_descriptor_error) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: File descriptor error while trying to open the 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, "'."); + } + else if (status == f_overflow) { + fl_color_print(f_standard_error, context.error, context.reset, "ERROR: Integer overflow while trying to buffer the 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, "'."); + } + else if (status == f_allocation_error || status == f_reallocation_error) { + fl_color_print_line(f_standard_error, context.error, context.reset, "CRITICAL ERROR: unable to allocate memory."); + } + else { + fl_color_print(f_standard_error, context.error, context.reset, "INTERNAL ERROR: An unhandled error ("); + fl_color_print(f_standard_error, context.notable, context.reset, "%u", status); + fl_color_print(f_standard_error, context.error, context.reset, ") has occured while calling "); + fl_color_print(f_standard_error, context.notable, context.reset, "%s()", function_name); + fl_color_print_line(f_standard_error, context.error, context.reset, "."); + } + } +#endif // _di_fss_extended_read_print_file_error_ + +#ifndef _di_fss_extended_read_main_preprocess_depth_ + f_return_status fss_extended_read_main_preprocess_depth(const f_console_arguments arguments, const fss_extended_read_data data, fss_extended_read_depths *depths) { + f_status status = f_none; + + // pre-process the depth and depth-sensitive parameters. + if (data.parameters[fss_extended_read_parameter_depth].result == f_console_result_additional) { + macro_fss_extended_read_depths_new(status, (*depths), data.parameters[fss_extended_read_parameter_depth].locations.used); + if (f_status_is_error(status)) { + f_status status2 = f_none; + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + + macro_fss_extended_read_depths_delete(status2, (*depths)); + return f_status_set_error(f_invalid_parameter); + } + + f_array_length depth_position = data.parameters[fss_extended_read_parameter_depth].additional.array[0]; + f_array_length at_index = 0; + f_array_length name_index = 0; + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->array[0].parameter = 0; + depths->array[0].position = 0; + depths->used = 1; + + f_string_length depth_previous = depths->array[0].depth; + f_string_length depth_current = depths->array[0].depth; + + if (data.parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_extended_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_extended_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_extended_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_read_parameter_at].additional.array[at_index] > data.parameters[fss_extended_read_parameter_depth].additional.array[1]) { + break; + } + } + + depths->array[0].parameter = fss_extended_read_parameter_at; + } + } // for + } + + if (data.parameters[fss_extended_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_extended_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_extended_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_extended_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_read_parameter_name].additional.array[name_index] > data.parameters[fss_extended_read_parameter_depth].additional.array[1]) { + break; + } + } + + if (depths->array[0].parameter == fss_extended_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_extended_read_long_at, fss_extended_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].parameter = fss_extended_read_parameter_name; + } + } // for + } + + for (f_array_length i = 1; i < data.parameters[fss_extended_read_parameter_depth].locations.used; i++) { + depth_position = data.parameters[fss_extended_read_parameter_depth].additional.array[i]; + depth_current = (f_string_length) atoll(arguments.argv[depth_position]); + + if (depth_current > depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be specified before the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (depth_current == depth_previous) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The depth '%llu' cannot be the same as the depth '%llu'.", depth_previous, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + if (data.parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { + for (; at_index < data.parameters[fss_extended_read_parameter_at].additional.used; at_index++) { + if (data.parameters[fss_extended_read_parameter_at].additional.array[at_index] > depth_position) { + if (data.parameters[fss_extended_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_read_parameter_at].additional.array[at_index] > data.parameters[fss_extended_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + depths->array[i].parameter = fss_extended_read_parameter_at; + depths->array[i].position = data.parameters[fss_extended_read_parameter_at].additional.array[i]; + } + } // for + } + + if (data.parameters[fss_extended_read_parameter_name].result == f_console_result_additional) { + for (; name_index < data.parameters[fss_extended_read_parameter_name].additional.used; name_index++) { + if (data.parameters[fss_extended_read_parameter_name].additional.array[name_index] > depth_position) { + if (data.parameters[fss_extended_read_parameter_depth].additional.used > 1) { + if (data.parameters[fss_extended_read_parameter_name].additional.array[name_index] > data.parameters[fss_extended_read_parameter_depth].additional.array[i+1]) { + break; + } + } + + if (depths->array[i].parameter == fss_extended_read_parameter_at) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '--%s' and '--%s' parameters cannot be specified at the same time (specified for depth '%llu').", fss_extended_read_long_at, fss_extended_read_long_name, depth_current); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[i].parameter = fss_extended_read_parameter_name; + depths->array[i].position = data.parameters[fss_extended_read_parameter_name].additional.array[i]; + } + } // for + } + + depths->array[i].depth = (f_string_length) atoll(arguments.argv[depth_position]); + depths->used++; + } // for + } + // when no depth parameter is specified, provide a implicit depth of 0 when depth-sensitive parameters are in use. + else { + if (data.parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { + if (data.parameters[fss_extended_read_parameter_name].result == f_console_result_additional) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "ERROR: The '%s' and '%s' parameters must not be specified at the same time.", fss_extended_read_long_name, fss_extended_read_long_object); + return f_status_set_error(f_invalid_parameter); + } + + macro_fss_extended_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_extended_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_extended_read_parameter_at; + depths->array[0].position = 0; + depths->used = 1; + } + else if (data.parameters[fss_extended_read_parameter_name].result == f_console_result_additional) { + macro_fss_extended_read_depths_new(status, (*depths), 1); + if (f_status_is_error(status)) { + fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "CRITICAL ERROR: unable to allocate memory."); + return f_status_set_error(f_invalid_parameter); + } + + depths->array[0].depth = (f_string_length) atoll(arguments.argv[data.parameters[fss_extended_read_parameter_depth].additional.array[0]]); + depths->array[0].parameter = fss_extended_read_parameter_name; + depths->array[0].position = 0; + depths->used = 1; + } + } + + return f_none; + } +#endif // _di_fss_extended_read_main_preprocess_depth_ + #ifndef _di_fss_extended_read_main_process_file_ f_return_status fss_extended_read_main_process_file(const f_console_arguments arguments, fss_extended_read_data *data, const f_string filename, const f_string_length target, const f_string_length select) { f_status status = f_none; @@ -55,7 +266,7 @@ extern "C" { // now that all of the files have been read, process the objects and contents if (data->parameters[fss_extended_read_parameter_total].result == f_console_result_found && data->parameters[fss_extended_read_parameter_name].result == f_console_result_none) { - fprintf(f_standard_output, "%u\n", (unsigned int) data->objects.used); + fprintf(f_standard_output, "%llu\n", data->objects.used); } else { current = 0; @@ -63,7 +274,7 @@ extern "C" { if (data->parameters[fss_extended_read_parameter_name].result == f_console_result_none) { if (data->parameters[fss_extended_read_parameter_object].result == f_console_result_none) { for (; current < data->objects.used; current++) { - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional && found == target)) { if (data->contents.array[current].used > select) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[current].array[select]); fprintf(f_standard_output, "\n"); @@ -74,7 +285,7 @@ extern "C" { } } - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -86,12 +297,12 @@ extern "C" { } else { for (; current < data->objects.used; current++) { - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } @@ -118,7 +329,7 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->objects.array[current].start, arguments.argv[data->parameters[fss_extended_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional && found == target)) { if (data->parameters[fss_extended_read_parameter_total].result == f_console_result_found) { total++; } @@ -134,7 +345,7 @@ extern "C" { } } - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { if (data->parameters[fss_extended_read_parameter_total].result == f_console_result_found) { total = data->contents.array[current].used; } @@ -163,12 +374,12 @@ extern "C" { if (name_length == argv_length) { if (fl_string_compare(data->buffer.string + data->contents.array[current].array[select].start, arguments.argv[data->parameters[fss_extended_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) { - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional && found == target)) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_none || (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional && found == target)) { f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[current]); fprintf(f_standard_output, "\n"); } - if (data->parameters[fss_extended_read_parameter_count].result == f_console_result_additional) { + if (data->parameters[fss_extended_read_parameter_at].result == f_console_result_additional) { if (found == target) { break; } diff --git a/level_3/fss_extended_read/c/private-fss_extended_read.h b/level_3/fss_extended_read/c/private-fss_extended_read.h index fb6f99c..4eb77e9 100644 --- a/level_3/fss_extended_read/c/private-fss_extended_read.h +++ b/level_3/fss_extended_read/c/private-fss_extended_read.h @@ -11,6 +11,90 @@ #ifdef __cplusplus extern "C" { #endif +/** + * A structure of parameters applied at some depth. + * + * depth: the depth number in which this is to be processed at. + * parameter: the index representing the parameter enum of either the "at" parameter or the "name" parameter. + * position: the parameter position index within the argv representing the value associated with the designated parameter. + */ +#ifndef _di_fss_extended_read_depth_ + typedef struct { + f_string_length depth; + + f_array_length parameter; + f_array_length position; + } fss_extended_read_depth; + + #define fss_extended_read_depth_initialize \ + { \ + 0, \ + f_array_length_initialize, \ + f_array_length_initialize, \ + } +#endif // _di_fss_extended_read_depth_ + +/** + * An array of depth parameters. + * + * array: the array of depths. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_fss_extended_read_depths_ + typedef struct { + fss_extended_read_depth *array; + + f_array_length size; + f_array_length used; + } fss_extended_read_depths; + + #define fss_extended_read_depths_initialize { 0, 0, 0 } + + #define macro_fss_extended_read_depths_clear(depths) f_macro_memory_structure_clear(depths) + + #define macro_fss_extended_read_depths_new(status, depths, length) f_macro_memory_structure_new(status, depths, fss_extended_read_depths, length) + + #define macro_fss_extended_read_depths_delete(status, depths) f_macro_memory_structure_delete(status, depths, fss_extended_read_depths) + #define macro_fss_extended_read_depths_destroy(status, depths) f_macro_memory_structure_destroy(status, depths, fss_extended_read_depths) + + #define macro_fss_extended_read_depths_resize(status, depths, new_length) f_macro_memory_structure_resize(status, depths, fss_extended_read_depths, new_length) + #define macro_fss_extended_read_depths_adjust(status, depths, new_length) f_macro_memory_structure_adjust(status, depths, fss_extended_read_depths, new_length) +#endif // _di_fss_extended_read_depths_ + +/** + * Print file error messages. + * + * @param context + * The color context information to use when printing. + * @param function_name + * The name of the function responsible for the error. + * @param file_name + * The name of the file with the error. + * @param status + * The status code representing the error. + */ +#ifndef _di_fss_extended_read_print_file_error_ + extern void fss_extended_read_print_file_error(const fl_color_context context, const f_string function_name, const f_string file_name, const f_status status) f_gcc_attribute_visibility_internal; +#endif // _di_fss_extended_read_print_file_error_ + +/** + * Pre-process the parameters, parsing out and handling the depth and depth related parameters. + * + * @param arguments + * The console arguments to pre-process. + * @param data + * The Program specific data. + * @param depths + * This stores the pre-processed depth parameters. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_read_main_preprocess_depth_ + extern f_return_status fss_extended_read_main_preprocess_depth(const f_console_arguments arguments, const fss_extended_read_data data, fss_extended_read_depths *depths) f_gcc_attribute_visibility_internal; +#endif // _di_fss_extended_read_main_preprocess_depth_ #ifndef _di_fss_extended_read_main_process_file_ extern f_return_status fss_extended_read_main_process_file(const f_console_arguments arguments, fss_extended_read_data *data, const f_string filename, const f_string_length target, const f_string_length select) f_gcc_attribute_visibility_internal; diff --git a/level_3/fss_extended_write/c/fss_extended_write.c b/level_3/fss_extended_write/c/fss_extended_write.c index b343982..3b19fcd 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.c +++ b/level_3/fss_extended_write/c/fss_extended_write.c @@ -58,6 +58,9 @@ extern "C" { else if (status == f_allocation_error || status == f_reallocation_error) { fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory."); } + else if (status == f_invalid_utf) { + fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ENCODING ERROR: Invalid UTF-8 character in parameter when calling fl_console_parameter_process()."); + } else if (status == f_invalid_parameter) { fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_console_parameter_process()."); } @@ -78,7 +81,7 @@ extern "C" { } else { f_array_length counter = 0; - f_bool object = (data->parameters[fss_extended_write_parameter_object].result == f_console_result_found); + bool object = (data->parameters[fss_extended_write_parameter_object].result == f_console_result_found); f_string_dynamic buffer = f_string_dynamic_initialize; f_string_location location = f_string_location_initialize; @@ -269,6 +272,7 @@ extern "C" { f_string_length i = 0; while (i < fss_extended_write_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_extended_write/c/fss_extended_write.h b/level_3/fss_extended_write/c/fss_extended_write.h index 10f8ac8..eb79264 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.h +++ b/level_3/fss_extended_write/c/fss_extended_write.h @@ -94,7 +94,7 @@ extern "C" { f_console_parameter parameters[fss_extended_write_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_extended_write_data; diff --git a/level_3/fss_status_code/c/fss_status_code.c b/level_3/fss_status_code/c/fss_status_code.c index 8b7f1de..5019924 100644 --- a/level_3/fss_status_code/c/fss_status_code.c +++ b/level_3/fss_status_code/c/fss_status_code.c @@ -62,7 +62,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -101,7 +101,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -140,7 +140,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -178,7 +178,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // numbers are not valid status code strings. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_true) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_true) { status = f_false; continue; } @@ -214,7 +214,7 @@ extern "C" { if (data->remaining.used > 0) { for (; counter < data->remaining.used; counter++) { // only numbers are valid status code. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -259,6 +259,7 @@ extern "C" { f_string_length i = 0; while (i < fss_status_code_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/fss_status_code/c/fss_status_code.h b/level_3/fss_status_code/c/fss_status_code.h index f53394f..c2deff6 100644 --- a/level_3/fss_status_code/c/fss_status_code.h +++ b/level_3/fss_status_code/c/fss_status_code.h @@ -94,7 +94,7 @@ extern "C" { f_console_parameter parameters[fss_status_code_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } fss_status_code_data; diff --git a/level_3/init/c/init.h b/level_3/init/c/init.h index 5ecb362..7f1240f 100644 --- a/level_3/init/c/init.h +++ b/level_3/init/c/init.h @@ -222,7 +222,7 @@ extern "C" { f_console_parameter parameters[init_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } init_data; diff --git a/level_3/init/c/private-init.h b/level_3/init/c/private-init.h index 1d55d5e..f500e62 100644 --- a/level_3/init/c/private-init.h +++ b/level_3/init/c/private-init.h @@ -36,8 +36,8 @@ extern "C" { f_string_dynamic name; f_string_dynamic directory; f_string_dynamic file; - f_bool require; - f_bool asynchronous; + bool require; + bool asynchronous; } init_rule; #define init_rule_initialize \ diff --git a/level_3/status_code/c/status_code.c b/level_3/status_code/c/status_code.c index 241d3e1..410e589 100644 --- a/level_3/status_code/c/status_code.c +++ b/level_3/status_code/c/status_code.c @@ -62,7 +62,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -101,7 +101,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -140,7 +140,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // only numbers are valid status codes. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -178,7 +178,7 @@ extern "C" { for (; counter < data->remaining.used; counter++) { // numbers are not valid status code strings. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_true) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_true) { status = f_false; continue; } @@ -213,7 +213,7 @@ extern "C" { if (data->remaining.used > 0) { for (; counter < data->remaining.used; counter++) { // only numbers are valid status code. - if (f_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { + if (f_conversion_character_is_decimal(arguments.argv[data->remaining.array[counter]][0]) == f_false) { status = f_false; continue; } @@ -258,6 +258,7 @@ extern "C" { f_string_length i = 0; while (i < status_code_total_parameters) { + f_macro_string_lengths_delete(status, data->parameters[i].locations); f_macro_string_lengths_delete(status, data->parameters[i].additional); i++; } // while diff --git a/level_3/status_code/c/status_code.h b/level_3/status_code/c/status_code.h index 87917c4..d5b3b94 100644 --- a/level_3/status_code/c/status_code.h +++ b/level_3/status_code/c/status_code.h @@ -91,7 +91,7 @@ extern "C" { f_console_parameter parameters[status_code_total_parameters]; f_string_lengths remaining; - f_bool process_pipe; + bool process_pipe; fl_color_context context; } status_code_data; -- 1.8.3.1