]> Kevux Git Server - fll/commitdiff
Progress: rewriting fss_* programs and all dependencies
authorKevin Day <thekevinday@gmail.com>
Sat, 9 Nov 2019 01:25:07 +0000 (19:25 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 9 Nov 2019 01:28:02 +0000 (19:28 -0600)
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.

68 files changed:
level_0/f_console/c/console.c
level_0/f_console/c/console.h
level_0/f_conversion/c/conversion.c
level_0/f_conversion/c/conversion.h
level_0/f_conversion/data/build/dependencies
level_0/f_conversion/data/build/settings
level_0/f_fss/c/fss.h
level_0/f_status/c/status.h
level_0/f_string/c/string.h
level_0/f_type/c/type.h
level_0/f_utf/c/utf.h
level_1/fl_color/c/color.c
level_1/fl_color/c/color.h
level_1/fl_console/c/console.c
level_1/fl_console/c/console.h
level_1/fl_console/data/build/dependencies
level_1/fl_console/data/build/settings
level_1/fl_file/c/file.c
level_1/fl_fss/c/fss.c
level_1/fl_fss/c/fss_basic.c
level_1/fl_fss/c/fss_basic_list.c
level_1/fl_fss/c/fss_extended.c
level_1/fl_fss/c/fss_extended_list.c
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_fss/c/fss_basic.c
level_2/fll_fss/c/fss_basic_list.c
level_2/fll_fss/c/fss_extended.c
level_2/fll_fss/c/fss_extended_list.c
level_2/fll_fss/c/fss_status.c
level_2/fll_program/c/program.c
level_2/fll_status/c/status.c
level_3/byte_dump/c/byte_dump.c
level_3/byte_dump/c/byte_dump.h
level_3/byte_dump/c/private-byte_dump.c
level_3/byte_dump/c/private-byte_dump.h
level_3/firewall/c/firewall.c
level_3/firewall/c/firewall.h
level_3/firewall/c/private-firewall.c
level_3/firewall/c/private-firewall.h
level_3/fss_basic_list_read/c/fss_basic_list_read.c
level_3/fss_basic_list_read/c/fss_basic_list_read.h
level_3/fss_basic_list_read/c/private-fss_basic_list_read.c
level_3/fss_basic_list_read/c/private-fss_basic_list_read.h
level_3/fss_basic_list_write/c/fss_basic_list_write.c
level_3/fss_basic_list_write/c/fss_basic_list_write.h
level_3/fss_basic_read/c/fss_basic_read.c
level_3/fss_basic_read/c/fss_basic_read.h
level_3/fss_basic_read/c/private-fss_basic_read.c
level_3/fss_basic_read/c/private-fss_basic_read.h
level_3/fss_basic_write/c/fss_basic_write.c
level_3/fss_basic_write/c/fss_basic_write.h
level_3/fss_extended_list_read/c/fss_extended_list_read.c
level_3/fss_extended_list_read/c/fss_extended_list_read.h
level_3/fss_extended_list_read/c/private-fss_extended_list_read.c
level_3/fss_extended_list_read/c/private-fss_extended_list_read.h
level_3/fss_extended_read/c/fss_extended_read.c
level_3/fss_extended_read/c/fss_extended_read.h
level_3/fss_extended_read/c/private-fss_extended_read.c
level_3/fss_extended_read/c/private-fss_extended_read.h
level_3/fss_extended_write/c/fss_extended_write.c
level_3/fss_extended_write/c/fss_extended_write.h
level_3/fss_status_code/c/fss_status_code.c
level_3/fss_status_code/c/fss_status_code.h
level_3/init/c/init.h
level_3/init/c/private-init.h
level_3/status_code/c/status_code.c
level_3/status_code/c/status_code.h

index 6196f15b78a4810399a16acd1147e528a8cea428..dbfcd297eb9e1d1e308c1eed032c8b52682c0411 100644 (file)
@@ -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);
 
index cbaf57c41f7da6006705c486dfbae5a4f17fef00..dce50d7caca14e167fdc301c243ffe45f50cc824 100644 (file)
@@ -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_
 
index 4f57bd84107aa4028f2b948aa6ef1fe92247108c..dca1b3541b7e2fa8b181fcc0270b3500801744f2 100644 (file)
@@ -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"
index 9e47bc409d4e080364da0ae9dd28627e0d5e38a0..cd94168b39f6928ce111d88e2706d39db8a00b1f 100644 (file)
 #define _F_conversion_h
 
 // libc includes
+#include <ctype.h>
 #include <stdlib.h>
 
 // fll-0 includes
 #include <level_0/status.h>
 #include <level_0/string.h>
 #include <level_0/type.h>
+#include <level_0/utf.h>
 
 #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"
index d8175f560a573638a52fec738c6bd984a86a5620..13b45c70749e2d3516b47e95d38129f780366064 100644 (file)
@@ -2,3 +2,4 @@ f_type
 f_status
 f_memory
 f_string
+f_utf
index 2ec77414bc2c6cf990d09597a6c189162e6ad816..643c0716df1366d6b64764043a9c3e0a582a2898 100644 (file)
@@ -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
index 6f20e2c61c16d206754e85160b6c9d56c55c4a49..fb2c755c76b9426efb8125932c2be9a80e9644ff 100644 (file)
@@ -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;
index 4ae60c1ed1a8b36d7cb9ba4f0f695f9dc6e346c1..ec3e090fa176929d7be31aa7423d85d28f495e64 100644 (file)
@@ -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_
index 9c7bf52ce2e48f9c6c942f04859bd42901a18452..116965e0f74a80ecba3face3aa39e1f38a280416 100644 (file)
@@ -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)
 
index f8bdf08ef13fc0fe41cf4fce3d15abb2eb93fc96..3a22311cd63998a6d7668321e54b1784419ac7a1 100644 (file)
@@ -11,6 +11,7 @@
 #define _F_types_h
 
 // libc includes
+#include <stdbool.h>
 #include <stdint.h>
 
 #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_
 
 /**
index ba1b7650a1374200c8a38ebcb9eaae8a1104d14f..67272dc4ae6065b62909f337086dfe897aaf860d 100644 (file)
@@ -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.
index c77910bf3fdc52ad68e83f38db7998d41873b77b..e71d91aeb746cf3ac14e939a5c4296eaf486dbd5 100644 (file)
@@ -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_
index 36152e51045c7f53588a1b93cf7029da990e2854..e59d20dd7bed9072d50ef9a7b1bd205e3573fee0 100644 (file)
@@ -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
index 38f2018868ca69e6468b84389c9b28ba6e409490..847af523442bf1045b81c043d7357e06f04de4d3 100644 (file)
@@ -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"
index 93834ce958a6e34aba6323219b4a7dc6c768c51a..d84e076786d0af8cb4666b8d0438229ba6c7b1eb 100644 (file)
 #define _FL_console_h
 
 // libc include
+#include <limits.h>
 #include <string.h>
 
 // fll-0 includes
 #include <level_0/console.h>
+#include <level_0/conversion.h>
 #include <level_0/status.h>
 #include <level_0/string.h>
 #include <level_0/type.h>
+#include <level_0/utf.h>
 
 #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
index 1ee73f6ab38e704d3fbd43107f502ddc8ecc881a..9c37f71c692b21d836d861a0e926e695864566c2 100644 (file)
@@ -3,4 +3,5 @@ f_status
 f_memory
 f_string
 f_console
+f_convesion
 f_utf
index d254cf80fd717ab91b9a916073812dad8762818a..1914c68455c4a6918d882782bf197f64332375b8 100644 (file)
@@ -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
index 7945d7ef992416dc8f7300e52ec8a2003bdc5212..039cbd5cbad89ff746429c0145b07858e68178b5 100644 (file)
@@ -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) {
index d016e86158b9ef33587ebb13752c0a622c3ef430..ec4c3f6132386c43dcfaa671ff26e1b543994bb9 100644 (file)
@@ -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;
 
index 7d79f96f779f1c4bf60e8bf8c1adeaf2f319bc06..92b3c03f6b7be5434ad84438cfcbd2fa3d087c83 100644 (file)
@@ -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;
index e3efcd420d3125dee37b0aada5dbe1d0d522b2dd..a6847dfb992934835efb88b9ede6b37bd850d710 100644 (file)
@@ -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;
index 1aaed2821774bfb170e08f5e6304bc8a8210203f..807f357e9268d7325563107b89a527b290694336 100644 (file)
@@ -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;
index c6db2936e43927932a5f3cbb817d47b30f5d13ee..31e34444ccde510f3bcf266144e9275ce11d88a9 100644 (file)
@@ -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;
index 5ac5e3f0b3b3728743f6ea75d027c127e94312cd..5dc290f5ef9dcf802612c9a6e306516deca30973 100644 (file)
@@ -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_
 
index 288dc39290abdb743f9d37d82d65e79bfdb1a1c8..1cd11daa22b385e97cb5592c959527b8a5356ba6 100644 (file)
@@ -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_
index 3f3629bf809bce64d4955100cb6525b2a1dde723..69263b4c6efe9e10ad9c7ce87c156b074f2fd363 100644 (file)
@@ -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) {
index a05884cb2d08eb474bedf97b8bfa8adedd88e9ad..1575682daf1e133fed8cc382590e313776e07769 100644 (file)
@@ -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) {
index 8f60bfbe581a6fc730f029283d858e63875fb971..55b32da98a46394253d1ee55fd32150e6b04ba9c 100644 (file)
@@ -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) {
index fc57f1cdebc03196c1fdb1b06847b464cd6ee53b..d466e570c426e40f248cfbe80ee22e6e1ab2bb0d 100644 (file)
@@ -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) {
index 386573ad47392e36cf8b52602de391651a7e57c3..639a53feb40387d2bd0f9428d7400f6b154c5776 100644 (file)
@@ -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);
     }
 
index ceca97b3957d66e198b79c4725c145ac7048c413..9d1040c5f1caa273a0b9f79d30b5165759ff72b2 100644 (file)
@@ -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().");
       }
index 5398a8c34b001be2e4fe3790d3d03dee90edde0e..e6ef62af82e93278c78b26ca92132990178aa5bd 100644 (file)
@@ -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_
index 3b8b33d8ad5bdd019a3bc55a9f65a8ef10317eae..4d2f88c21d8798c9344060d978c2c64f322126eb 100644 (file)
@@ -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
 
index c44ac40cd1400bbb99868ec371da8122221f75ce..9d1024e91f7579a7a5907224126f1873c0f4924f 100644 (file)
@@ -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;
index 1d173409aa99608c34145d3f743422707b3b41a3..8238de4504f2cf00558584d067fae606986550ff 100644 (file)
@@ -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);
 
index 0be072ceb8edc35cd1a0c299579f76c98815285d..237b06d4bac41756e884b24b8e15fc97ef7468d5 100644 (file)
@@ -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_
 
 /**
index 568bd0d74b59fa9f9689fc41d87f31c7ebdbad36..937138ca66eb166aca61aa225a5266dd9a8d64b9 100644 (file)
@@ -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
index 57e0f80d9a482aaed4752a7a1f4cd1b771c5c26f..d92915d2a8a505a811a9232f98cbaf9480dda91b 100644 (file)
@@ -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;
index fe4a23ce713d0480ba8a7463388723172af5c5f6..78f2fa087e512aa7d4548be260773b0bf38d205d 100644 (file)
@@ -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;
 
index 1ba3f9da77840811f8698aafaafeba677738b6b2..785b0d3ec01f77155b3cdf992ecdfc30dd29c7fe 100644 (file)
@@ -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.
index b8d551e264b3897c1ca7f260025b48764fcf5577..0c14259114edeb226ffd4489c0a000684b9762ee 100644 (file)
@@ -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
index 00e017876d9cbde6b7e35b852ad6e5d177f6a45a..51370eabefa8652ad358309a29964a3338c4a2d0 100644 (file)
@@ -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;
index 4ac5ddd1d042e313af347c5122bc9e4ad4c333f2..1f41ac9ef9604a89fdcae8280b191342730ed511 100644 (file)
@@ -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;
                       }
index 85709c7317ee968f3b0af49538d71891f32c3908..bb37a47f0ab91e6b594cbe21a647ec1a78d2e853 100644 (file)
 #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
index 99e790dfd854a41b69bb22bb6ca64ce7f59b3375..5f372564c9b5f984a8aaf9bd6f18cc3cb00a649a 100644 (file)
@@ -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
index aa48b46bb34c9a93cc435d4404d4f8b970b7b9b3..d8237a37064d54880f36753dd988d8c6870e4459 100644 (file)
@@ -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;
index a552a3102eae38844128328645152b68434750cd..4d3937fc0b0e365c39878c36d545d76627f4ddb7 100644 (file)
@@ -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
index d17e369404a2c920d744c1ba29b63c718a024c5f..dbd1a2245c4bd067b39c4de51ab1c2b712eb1ebf 100644 (file)
@@ -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;
index fc9ee03569ac7c112c429906c06543de8045f293..f00a77b9df1beb994edbf1191112a66ab9bd88fc 100644 (file)
 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_
index 8958e15915f08898de6b9cd2fc8e94777eacfcbe..7329c9f04cc410f00a0fa93bba839c2fcb6fcb49 100644 (file)
 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
index 20d368f9e1e7f7bb24ac30221296c6972572ff53..b4d31a548fa622fbbfe5eab7eeb32831d06c9f55 100644 (file)
@@ -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
index 103ec2ff93b1e5791e40c7686fdd48617d504819..ddc537f7fc530e4ebed8fec53db25ae991274115 100644 (file)
@@ -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;
index 62f29a3b4df9457ffd49b6b63c672b51fe9af5c3..add03a0f16b5ee4d7cd3884fab686a0e3bc4082a 100644 (file)
@@ -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
index b1cca66d33e778158db731877dbd27812aa45476..d45c25c3f4c5d994e43ce17719c88048ee28907d 100644 (file)
@@ -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;
index b0df1608d989d527854529e31f6fa3cac1c36372..5b35bd67e3b7cdedca2c61e14b69a75c50ec1899 100644 (file)
@@ -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;
                       }
index ec5f58986feb1a2c058cfaf5cbf4312c1e3f56b7..36f911f86be8af4da96371b2aae900a45390cdc5 100644 (file)
 #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
index 451acad027b5b81121962d7a5cd34c497ca91c19..b3eee889013263a14e5f4947302912107829e21c 100644 (file)
@@ -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);
index 64f6311d221ccb46249803497ed64385df1a378f..87e1010999ff9382d002d1872d15f90934a38b19 100644 (file)
@@ -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;
index 8d5d91b569fcebfd833e151565bf49e159a15e8e..b1243d1fa9d3ca0dbf4e56f0e30808246f0e37ec 100644 (file)
@@ -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;
                       }
index fb6f99c65cb3e774e7387bfc428a37ccb6297c6e..4eb77e99896652964f9889d0add4b7c2687970bd 100644 (file)
 #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;
index b3439824141c55930befb7289d7f93ef5f42a2df..3b19fcd598e5af15f08864ecfa876cd74164323b 100644 (file)
@@ -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
index 10f8ac86185fcaa0eea5c90d89e85a222e1d9d68..eb79264db0e67ea839efeca0606fa35104566099 100644 (file)
@@ -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;
index 8b7f1de40924f0dae1ac8ddd3dc11154b79286f2..5019924e98c3b701daf58c7da4b732944e7c9399 100644 (file)
@@ -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
index f53394fa690d8ddc0425cf668e420b07ae15eb39..c2deff6b6de7c2b2ba9b07d669b6515b5b01e8fd 100644 (file)
@@ -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;
index 5ecb3621add7b99e47695cf55edff2529b63fdcc..7f1240f4aa8dff7f3f60a23f1bdd4b093f0b7d48 100644 (file)
@@ -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;
index 1d55d5ea8cc73589ffbf991ad9d54ede26dd1c20..f500e625da13d38734e63991ee2f36333dc87b89 100644 (file)
@@ -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 \
index 241d3e1ca4cf6d7099e13e4dcc89e4937ef4ae47..410e589957a4d585cfb78e2031a5ae702bb169bd 100644 (file)
@@ -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
index 87917c443f1a753dfd3a4398b27222289cb5336a..d5b3b94809d5625c849f5529f789273bbb570d4c 100644 (file)
@@ -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;