]> Kevux Git Server - fll/commitdiff
Update: finish implementing fss_basic_list_read
authorKevin Day <thekevinday@gmail.com>
Sat, 16 Nov 2019 04:20:56 +0000 (22:20 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 16 Nov 2019 04:20:56 +0000 (22:20 -0600)
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

index 0c14259114edeb226ffd4489c0a000684b9762ee..dcb9898aeb5718546bc8b60f5dde0e9788048c9c 100644 (file)
@@ -19,15 +19,20 @@ extern "C" {
 
     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_empty, fss_basic_list_read_long_empty, f_console_symbol_short_enable, f_console_symbol_long_enable, "   Include empty content when processing.");
     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_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 lines.");
 
     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);
+    fl_color_print(f_standard_output, data.context.important, data.context.reset, " Notes:");
+
+    printf("%c", f_string_eol, f_string_eol);
+
+    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);
 
@@ -53,21 +58,13 @@ extern "C" {
 
     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(" must 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);
@@ -75,10 +72,10 @@ extern "C" {
     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);
+    fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_object);
     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);
+    fl_color_print(f_standard_output, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_total);
+    printf(" parameters to get the total objects.%c", f_string_eol);
 
     printf("%c", f_string_eol);
 
@@ -124,9 +121,7 @@ extern "C" {
       status = f_none;
     }
 
-    f_status status2 = f_none;
-
-    // execute parameter results
+    // Execute parameter results.
     if (data->parameters[fss_basic_list_read_parameter_help].result == f_console_result_found) {
       fss_basic_list_read_print_help(*data);
     }
@@ -134,8 +129,48 @@ 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_at].result == f_console_result_found) {
+        fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+        fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_at);
+        fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' requires a positive number.");
+
+        return f_status_set_error(f_invalid_parameter);
+      }
+
+      if (data->parameters[fss_basic_list_read_parameter_depth].result == f_console_result_found) {
+        fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+        fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_depth);
+        fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' requires a positive number.");
+
+        return f_status_set_error(f_invalid_parameter);
+      }
+
+      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: The parameter '");
+        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, "' requires a positive number.");
+
+        return f_status_set_error(f_invalid_parameter);
+      }
+
+      if (data->parameters[fss_basic_list_read_parameter_name].result == f_console_result_found) {
+        fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+        fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_name);
+        fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' requires a string.");
+
+        return f_status_set_error(f_invalid_parameter);
+      }
+
+      if (data->parameters[fss_basic_list_read_parameter_select].result == f_console_result_found) {
+        fl_color_print(f_standard_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+        fl_color_print(f_standard_error, data->context.notable, data->context.reset, "--%s", fss_basic_list_read_long_select);
+        fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' requires a positive number.");
+
+        return f_status_set_error(f_invalid_parameter);
+      }
+
       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) {
+        if (data->parameters[fss_basic_list_read_parameter_line].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 '");
@@ -156,14 +191,24 @@ extern "C" {
         }
       }
 
-      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_line].result == f_console_result_additional) {
+        if (data->parameters[fss_basic_list_read_parameter_total].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_line);
+          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_total);
+          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "' parameter.");
 
-      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]]);
+          return f_status_set_error(f_invalid_parameter);
+        }
       }
 
+      fss_basic_list_read_depths depths = fss_basic_list_read_depths_initialize;
+      f_status status2 = f_none;
+
+      f_string_length counter = 0;
+      f_string_length original_size = data->file_position.total_elements;
+
       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);
@@ -174,19 +219,18 @@ extern "C" {
       // 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);
+          fprintf(f_standard_output, "0%c", 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->parameters[fss_basic_list_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_list_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);
       }
 
       if (data->process_pipe) {
@@ -198,70 +242,81 @@ extern "C" {
 
         if (f_status_is_error(status)) {
           fss_basic_list_read_print_file_error(data->context, "fl_file_read_fifo", "-", f_status_set_fine(status));
+          macro_fss_basic_list_read_depths_delete(status2, depths);
           fss_basic_list_read_delete_data(data);
           return status;
         }
 
-        status = fss_basic_list_read_main_process_file(arguments, data, "-", target);
+        status = fss_basic_list_read_main_process_file(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;
         }
 
-        // 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);
       }
 
-      for (; counter < data->remaining.used; counter++) {
-        f_file file = f_file_initialize;
+      if (data->remaining.used > 0) {
+        for (; counter < data->remaining.used; counter++) {
+          f_file file = f_file_initialize;
 
-        status = f_file_open(&file, arguments.argv[data->remaining.array[counter]]);
+          status = f_file_open(&file, arguments.argv[data->remaining.array[counter]]);
 
-        data->file_position.total_elements = original_size;
+          data->file_position.total_elements = original_size;
 
-        if (f_status_is_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);
-        }
+          if (f_status_is_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));
+            macro_fss_basic_list_read_depths_delete(status2, depths);
+            fss_basic_list_read_delete_data(data);
+            return status;
+          }
 
-        if (data->file_position.total_elements == 0) {
-          fseek(file.address, 0, SEEK_END);
+          if (data->file_position.total_elements == 0) {
+            fseek(file.address, 0, SEEK_END);
 
-          data->file_position.total_elements = ftell(file.address);
+            data->file_position.total_elements = ftell(file.address);
 
-          // skip past empty files
-          if (data->file_position.total_elements == 0) {
-            f_file_close(&file);
-            continue;
+            // Sskip past empty files.
+            if (data->file_position.total_elements == 0) {
+              f_file_close(&file);
+              continue;
+            }
+
+            fseek(file.address, 0, SEEK_SET);
           }
 
-          fseek(file.address, 0, SEEK_SET);
-        }
+          status = fl_file_read(file, data->file_position, &data->buffer);
 
-        status = fl_file_read(file, data->file_position, &data->buffer);
+          f_file_close(&file);
 
-        f_file_close(&file);
+          if (f_status_is_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));
+            macro_fss_basic_list_read_depths_delete(status2, depths);
+            fss_basic_list_read_delete_data(data);
+            return status;
+          }
 
-        if (f_status_is_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);
-        }
+          status = fss_basic_list_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[counter]], depths);
 
-        status = fss_basic_list_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[counter]], target);
+          if (f_status_is_error(status)) {
+            macro_fss_basic_list_read_depths_delete(status2, depths);
+            fss_basic_list_read_delete_data(data);
+            return status;
+          }
 
-        if (f_status_is_error(status)) {
-          return status;
-        }
+          // 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
+      }
 
-        // 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_list_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.");
index 0ff11b06cda00deac9de85b7d3cb47224686f90d..655705264c03c884eb7ca4237096461e7a3c54f0 100644 (file)
@@ -58,6 +58,7 @@ extern "C" {
 #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_empty  "e"
   #define fss_basic_list_read_short_line   "l"
   #define fss_basic_list_read_short_name   "n"
   #define fss_basic_list_read_short_object "o"
@@ -66,6 +67,7 @@ extern "C" {
 
   #define fss_basic_list_read_long_at     "at"
   #define fss_basic_list_read_long_depth  "depth"
+  #define fss_basic_list_read_long_empty  "empty"
   #define fss_basic_list_read_long_line   "line"
   #define fss_basic_list_read_long_name   "name"
   #define fss_basic_list_read_long_object "object"
@@ -81,6 +83,7 @@ extern "C" {
 
     fss_basic_list_read_parameter_at,
     fss_basic_list_read_parameter_depth,
+    fss_basic_list_read_parameter_empty,
     fss_basic_list_read_parameter_line,
     fss_basic_list_read_parameter_name,
     fss_basic_list_read_parameter_object,
@@ -97,6 +100,7 @@ extern "C" {
       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_empty, fss_basic_list_read_long_empty, 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_name, fss_basic_list_read_long_name, 0, f_true, 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), \
index 763f4c3dffded21ce60194576d5aedbaf4e0ef0f..0ae20df03b20e101697c346f51d9163ed0bcbf97 100644 (file)
@@ -66,169 +66,199 @@ extern "C" {
   }
 #endif // _di_fss_basic_list_read_print_file_error_
 
+#ifndef _di_fss_basic_list_read_print_number_argument_error_
+  void fss_basic_list_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 if (status == f_positive_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, "' contains a '");
+      fl_color_print(f_standard_error, context.notable, context.reset, "+");
+      fl_color_print(f_standard_error, context.error, context.reset, "', 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 if (status == f_no_data) {
+      fl_color_print(f_standard_error, context.error, context.reset, "ERROR: 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, "' must not be an empty string.");
+    }
+    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_list_read_print_number_argument_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);
+    {
+      f_array_length depth_size = 1;
+
+      if (data.parameters[fss_basic_list_read_parameter_depth].result == f_console_result_additional) {
+        depth_size = data.parameters[fss_basic_list_read_parameter_depth].additional.used;
+      }
+
+      macro_fss_basic_list_read_depths_new(status, (*depths), depth_size);
       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);
+        return status;
       }
 
-      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->used = depth_size;
+    }
+
+    f_array_length position_depth = 0;
+    f_array_length position_at = 0;
+    f_array_length position_name = 0;
+
+    for (f_array_length i = 0; i < depths->used; i++) {
+      depths->array[i].depth = 0;
+      depths->array[i].index_at = 0;
+      depths->array[i].index_name = 0;
+      depths->array[i].value_at = 0;
+      depths->array[i].value_name = f_string_eos;
+
+      if (data.parameters[fss_basic_list_read_parameter_depth].additional.used == 0) {
+        position_depth = 0;
+      }
+      else {
+        position_depth = data.parameters[fss_basic_list_read_parameter_depth].additional.array[i];
 
-      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;
+        status = fl_console_parameter_to_number_unsigned(arguments.argv[position_depth], &depths->array[i].depth);
 
-      f_string_length depth_previous = depths->array[0].depth;
-      f_string_length depth_current = depths->array[0].depth;
+        if (f_status_is_error(status)) {
+          fss_basic_list_read_print_number_argument_error(data.context, "fl_console_parameter_to_number_unsigned", fss_basic_list_read_long_depth, arguments.argv[position_depth], f_status_set_fine(status));
+          return status;
+        }
+      }
 
       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;
-              }
-            }
+        for (; position_at < data.parameters[fss_basic_list_read_parameter_at].additional.used; position_at++) {
+          if (data.parameters[fss_basic_list_read_parameter_at].additional.array[position_at] < position_depth) {
+            continue;
+          }
 
-            depths->array[0].parameter = fss_basic_list_read_parameter_at;
+          if (i + 1 < depths->used && data.parameters[fss_basic_list_read_parameter_at].additional.array[position_at] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[i + 1]) {
+            break;
           }
-        } // 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;
-              }
-            }
+          depths->array[i].index_at = data.parameters[fss_basic_list_read_parameter_at].additional.array[position_at];
 
-            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);
-            }
+          status = fl_console_parameter_to_number_unsigned(arguments.argv[depths->array[i].index_at], &depths->array[i].value_at);
 
-            depths->array[0].parameter = fss_basic_list_read_parameter_name;
+          if (f_status_is_error(status)) {
+            fss_basic_list_read_print_number_argument_error(data.context, "fl_console_parameter_to_number_unsigned", fss_basic_list_read_long_at, arguments.argv[depths->array[i].index_at], f_status_set_fine(status));
+            return status;
           }
         } // 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;
-                }
-              }
+      if (data.parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) {
+        for (; position_name < data.parameters[fss_basic_list_read_parameter_name].additional.used; position_name++) {
+          if (data.parameters[fss_basic_list_read_parameter_name].additional.array[position_name] < position_depth) {
+            continue;
+          }
 
-              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 (i + 1 < depths->used && data.parameters[fss_basic_list_read_parameter_name].additional.array[position_name] > data.parameters[fss_basic_list_read_parameter_depth].additional.array[i + 1]) {
+            break;
+          }
 
-        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;
-                }
-              }
+          depths->array[i].index_name = data.parameters[fss_basic_list_read_parameter_name].additional.array[position_name];
+          depths->array[i].value_name = arguments.argv[depths->array[i].index_name];
 
-              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);
-              }
+          if (depths->array[i].value_name[0] == '\0') {
+            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_list_read_long_name);
+            fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "' must not be an empty string.");
 
-              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
-        }
+            return f_status_set_error(f_invalid_parameter);
+          }
+        } // for
+      }
+    } // 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);
-        }
+    for (f_array_length i = 0; i < depths->used; i++) {
+      for (f_array_length j = i + 1; j < depths->used; j++) {
+        if (depths->array[i].depth == depths->array[j].depth) {
+          fl_color_print(f_standard_error, data.context.error, data.context.reset, "ERROR: The value '");
+          fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%llu", depths->array[i].depth);
+          fl_color_print(f_standard_error, data.context.error, data.context.reset, "' may only be specified once for the parameter '");
+          fl_color_print(f_standard_error, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth);
+          fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "'.");
 
-        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);
         }
+        else if (depths->array[i].depth > depths->array[j].depth) {
+          fl_color_print(f_standard_error, data.context.error, data.context.reset, "ERROR: The parameter '");
+          fl_color_print(f_standard_error, data.context.notable, data.context.reset, "--%s", fss_basic_list_read_long_depth);
+          fl_color_print(f_standard_error, data.context.error, data.context.reset, "' may not have the value '");
+          fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%llu", depths->array[i].depth);
+          fl_color_print(f_standard_error, data.context.error, data.context.reset, "' before the value '");
+          fl_color_print(f_standard_error, data.context.notable, data.context.reset, "%llu", depths->array[j].depth);
+          fl_color_print_line(f_standard_error, data.context.error, data.context.reset, "'.");
 
-        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;
-      }
-    }
+      } // for
+    } // for
 
     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_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 fss_basic_list_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_list_read(&data->buffer, &input, &data->objects, &data->contents);
 
@@ -236,26 +266,39 @@ extern "C" {
         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 fll_fss_basic_list_read() for the file '%s'", filename);
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling ");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "fll_fss_basic_list_read()");
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, " for the file '");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", filename);
+          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'.");
         }
         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_incomplete_utf_on_stop) {
-          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ENCODING ERROR: error occured on invalid UTF-8 character at stop position (at %d).", input.start);
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, "ENCODING ERROR: error occured on invalid UTF-8 character at stop position (at ");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%d", input.start);
+          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, ").");
         }
         else if (status == f_incomplete_utf_on_eos) {
-          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "ENCODING ERROR: error occured on invalid UTF-8 character at end of string (at %d).", input.start);
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, "ENCODING ERROR: error occured on invalid UTF-8 character at end of string (at ");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%d", input.start);
+          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, ").");
         }
         else {
-          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'", status, filename);
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%u", status);
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, ") has occured while calling ");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "fll_fss_basic_list_read()");
+          fl_color_print(f_standard_error, data->context.error, data->context.reset, " for the file '");
+          fl_color_print(f_standard_error, data->context.notable, data->context.reset, "%s", filename);
+          fl_color_print_line(f_standard_error, data->context.error, data->context.reset, "'.");
         }
 
-        fss_basic_list_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);
@@ -264,240 +307,285 @@ 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, "%llu\n", data->objects.used);
+    f_string_length select = 0;
+
+    if (data->parameters[fss_basic_list_read_parameter_select].result == f_console_result_additional) {
+      status = fl_console_parameter_to_number_unsigned(arguments.argv[data->parameters[fss_basic_list_read_parameter_select].additional.array[data->parameters[fss_basic_list_read_parameter_select].additional.used - 1]], &select);
+
+      if (f_status_is_error(status)) {
+        fss_basic_list_read_print_number_argument_error(data->context, "fl_console_parameter_to_number_unsigned", fss_basic_list_read_long_select, arguments.argv[data->parameters[fss_basic_list_read_parameter_select].additional.array[0]], f_status_set_fine(status));
+        return status;
+      }
+
+      // This standard does not support multiple content groups.
+      if (select > 0) {
+        return f_none;
+      }
     }
-    else {
-      current = 0;
 
-      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_at].result == f_console_result_none || (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional && found == target)) {
+    f_string_length line = 0;
 
-              /*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;
+    if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) {
+      status = fl_console_parameter_to_number_unsigned(arguments.argv[data->parameters[fss_basic_list_read_parameter_line].additional.array[data->parameters[fss_basic_list_read_parameter_line].additional.used - 1]], &line);
 
-                  for (; counter <= data->contents.array[current].array[0].stop; counter++) {
-                    if (data->buffer.string[counter] == f_string_eol) size++;
-                  } // for
+      if (f_status_is_error(status)) {
+        fss_basic_list_read_print_number_argument_error(data->context, "fl_console_parameter_to_number_unsigned", fss_basic_list_read_long_line, arguments.argv[data->parameters[fss_basic_list_read_parameter_line].additional.array[0]], f_status_set_fine(status));
+        return status;
+      }
+    }
 
-                  // the last newline is never present
-                  size++;
+    bool names[data->objects.used];
 
-                  fprintf(f_standard_output, "%u\n", (unsigned int) size);
-                }
-                else {
-                  fprintf(f_standard_output, "0\n");
-                }
-              }
-              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;
-                  f_string_length target = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_list_read_parameter_line].additional.array[0]]);
-                  f_string_location range = f_string_location_initialize;
-
-                  // use an invalid range to communicate range not found
-                  range.start = 1;
-                  range.stop  = 0;
-
-                  for (; counter <= data->contents.array[current].array[0].stop; counter++) {
-                    if (position == target) {
-                      range.start = counter;
-
-                      // explicit use of < instead of <= is done here so that the range.stop will always be accurate
-                      for (; counter < data->contents.array[current].array[0].stop; counter++) {
-                        if (data->buffer.string[counter] == f_string_eol) {
-                          break;
-                        }
-                      } // for
-
-                      range.stop = counter;
-                      break;
-                    }
-
-                    if (data->buffer.string[counter] == f_string_eol) {
-                      position++;
-                    }
-                  } // for
-
-                  if (range.start <= range.stop) {
-                    f_print_string_dynamic_partial(f_standard_output, data->buffer, range);
-                  }
-                }
-              }
-              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");
-                }
-              }
-            }
+    if (depths.array[0].index_name > 0) {
+      memset(names, 0, sizeof(bool) * data->objects.used);
 
-            if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) {
-              if (found == target) {
-                break;
-              }
-              else {
-                found++;
-              }
-            }
-          } // for
+      f_string_length argv_length = strlen(depths.array[0].value_name);
+      f_string_length name_length = 0;
+
+      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[i].start, depths.array[0].value_name, name_length, argv_length) == f_equal_to) {
+            names[i] = 1;
+          }
         }
-        else {
-          for (; current < data->objects.used; current++) {
-            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");
-            }
+      } // for
+    }
+    else {
+      memset(names, 1, sizeof(bool) * data->objects.used);
+    }
 
-            if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) {
-              if (found == target) {
-                break;
-              }
-              else {
-                found++;
-              }
-            }
+    bool include_empty = 0;
+
+    if (data->parameters[fss_basic_list_read_parameter_empty].result == f_console_result_found) {
+      include_empty = 1;
+    }
+
+    if (data->parameters[fss_basic_list_read_parameter_object].result == f_console_result_found) {
+      if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) {
+        if (depths.array[0].index_at > 0) {
+          if (depths.array[0].value_at < data->objects.used && names[depths.array[0].value_at]) {
+            fprintf(f_standard_output, "1%c", f_string_eol);
+          }
+          else {
+            fprintf(f_standard_output, "0%c", f_string_eol);
+          }
+        }
+        else if (depths.array[0].index_name > 0) {
+          f_string_length total = 0;
+
+          for (f_string_length i = 0; i < data->objects.used; i++) {
+            if (names[i] == 0) continue;
+
+            total++;
           } // for
+
+          fprintf(f_standard_output, "%llu%c", total, f_string_eol);
+        }
+        else {
+          fprintf(f_standard_output, "%llu%c", data->objects.used, f_string_eol);
         }
-      }
-      else {
-        current = 0;
 
-        f_string_length total = 0;
-        f_string_length name_length = 0;
-        f_string_length argv_length = 0;
+        return f_none;
+      }
 
-        if (data->parameters[fss_basic_list_read_parameter_name].result == f_console_result_additional) {
-          argv_length = strlen(arguments.argv[data->parameters[fss_basic_list_read_parameter_name].additional.array[0]]);
+      if (depths.array[0].index_at > 0) {
+        if (depths.array[0].value_at < data->objects.used && names[depths.array[0].value_at]) {
+          f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[depths.array[0].value_at]);
+          fprintf(f_standard_output, "%c", f_string_eol);
+        }
 
-          if (data->parameters[fss_basic_list_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;
+        return f_none;
+      }
 
-              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) {
+      for (f_string_length i = 0; i < data->objects.used; i++) {
+        if (names[i] == 0) continue;
 
-                  /*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;
+        f_print_string_dynamic_partial(f_standard_output, data->buffer, data->objects.array[i]);
+        fprintf(f_standard_output, "%c", f_string_eol);
+      } // for
 
-                      for (; counter <= data->contents.array[current].array[0].stop; counter++) {
-                        if (data->buffer.string[counter] == f_string_eol) size++;
-                      } // for
+      return f_none;
+    }
 
-                      // the last newline is never present
-                      size++;
+    if (depths.array[0].index_at > 0) {
+      if (names[depths.array[0].value_at]) {
+        if (depths.array[0].value_at >= data->objects.used) {
+          if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) {
+            fprintf(f_standard_output, "0%c", f_string_eol);
+          }
 
-                      fprintf(f_standard_output, "%u\n", (unsigned int) size);
-                    }
-                    else {
-                      fprintf(f_standard_output, "0\n");
-                    }
-                  }
-                  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;
-                      f_string_length target = (f_string_length) atoll(arguments.argv[data->parameters[fss_basic_list_read_parameter_line].additional.array[0]]);
-                      f_string_location range = f_string_location_initialize;
-
-                      // use an invalid range to communicate range not found
-                      range.start = 1;
-                      range.stop = 0;
-
-                      for (; counter <= data->contents.array[current].array[0].stop; counter++) {
-                        if (position == target) {
-                          range.start = counter;
-
-                          // explicit use of < instead of <= is done here so that the range.stop will always be accurate
-                          for (; counter < data->contents.array[current].array[0].stop; counter++) {
-                            if (data->buffer.string[counter] == f_string_eol) {
-                              break;
-                            }
-                          } // for
-
-                          range.stop = counter;
-                          break;
-                        }
-
-                        if (data->buffer.string[counter] == f_string_eol) {
-                          position++;
-                        }
-                      } // for
-
-                      if (range.start <= range.stop) {
-                        f_print_string_dynamic_partial(f_standard_output, data->buffer, range);
-                      }
-                    }
-                  }
-                  else {
-                    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++;
-                      }
-                      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");
-                        }
-                      }
-                    }
-                  }
+          return f_none;
+        }
+        else if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) {
+          if (data->contents.array[depths.array[0].value_at].used == 0) {
+            fprintf(f_standard_output, "0%c", f_string_eol);
+          }
+          else {
+            fprintf(f_standard_output, "1%c", f_string_eol);
+          }
 
-                  if (data->parameters[fss_basic_list_read_parameter_at].result == f_console_result_additional) {
-                    if (found == target) {
-                      break;
-                    }
-                    else {
-                      found++;
-                    }
-                  }
-                }
-              }
-            } // for
+          return f_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);
+        if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) {
+          if (data->contents.array[depths.array[0].value_at].used == 0) {
+            if (include_empty && line == 0) {
+              fprintf(f_standard_output, "%c", 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_list_read_parameter_name].additional.array[0]], name_length, argv_length) == f_equal_to) {
-                    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_at].result == f_console_result_additional) {
-                      if (found == target) {
+            f_string_length i = data->contents.array[depths.array[0].value_at].array[0].start;
+
+            if (line == 0) {
+              for (; i <= data->contents.array[depths.array[0].value_at].array[0].stop; i++) {
+                if (data->buffer.string[i] == f_string_eos) continue;
+                if (data->buffer.string[i] == f_string_eol) {
+                  fprintf(f_standard_output, "%c", f_string_eol);
+                  break;
+                }
+
+                fprintf(f_standard_output, "%c", data->buffer.string[i]);
+              } // for
+            }
+            else {
+              f_string_length line_current = 0;
+
+              for (; i <= data->contents.array[depths.array[0].value_at].array[0].stop; i++) {
+                if (data->buffer.string[i] == f_string_eos) continue;
+
+                if (data->buffer.string[i] == f_string_eol) {
+                  line_current++;
+
+                  if (line_current == line) {
+                    i++;
+
+                    for (; i <= data->contents.array[depths.array[0].value_at].array[0].stop; i++) {
+                      if (data->buffer.string[i] == f_string_eos) continue;
+                      if (data->buffer.string[i] == f_string_eol) {
+                        fprintf(f_standard_output, "%c", f_string_eol);
                         break;
                       }
-                      else {
-                        found++;
-                      }
-                    }
+
+                      fprintf(f_standard_output, "%c", data->buffer.string[i]);
+                    } // for
+
+                    break;
                   }
                 }
-              }
-            } // for
+              } // for
+            }
           }
+
+          return f_none;
+        }
+
+        if (data->contents.array[depths.array[0].value_at].used > 0) {
+          f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[depths.array[0].value_at].array[0]);
+        }
+        else if (include_empty) {
+          fprintf(f_standard_output, "%c", f_string_eol);
         }
       }
+
+      return f_none;
+    }
+
+    if (data->parameters[fss_basic_list_read_parameter_total].result == f_console_result_found) {
+      f_string_length total = 0;
+
+      for (f_string_length i = 0; i < data->objects.used; i++) {
+        if (!names[i]) {
+          continue;
+        }
+
+        if (data->contents.array[i].used == 0 && !include_empty) {
+          continue;
+        }
+
+        total++;
+      } // for
+
+      fprintf(f_standard_output, "%llu%c", total, f_string_eol);
+      return f_none;
+    }
+
+    if (data->parameters[fss_basic_list_read_parameter_line].result == f_console_result_additional) {
+      f_string_length line_current = 0;
+      f_string_length i = 0;
+      f_string_length j = 0;
+
+      for (; i < data->contents.used; i++) {
+        if (!names[i]) {
+          continue;
+        }
+
+        if (data->contents.array[i].used == 0) {
+          if (include_empty) {
+            if (line_current == line) {
+              fprintf(f_standard_output, "%c", f_string_eol);
+              break;
+            }
+
+            line_current++;
+          }
+
+          continue;
+        }
+
+        j = data->contents.array[i].array[0].start;
+
+        if (line_current != line) {
+          for (; j <= data->contents.array[i].array[0].stop; j++) {
+            if (data->buffer.string[j] == f_string_eol) {
+              line_current++;
+
+              if (line_current == line) {
+                j++;
+                break;
+              }
+            }
+          } // for
+        }
+
+        if (line_current == line) {
+          if (j > data->contents.array[i].array[0].stop) continue;
+
+          for (; j <= data->contents.array[i].array[0].stop; j++) {
+            if (data->buffer.string[j] == f_string_eos) continue;
+
+            if (data->buffer.string[j] == f_string_eol) {
+              fprintf(f_standard_output, "%c", f_string_eol);
+              break;
+            }
+
+            fprintf(f_standard_output, "%c", data->buffer.string[j]);
+          } // for
+
+          break;
+        }
+      } // for
+
+      return f_none;
     }
 
+    for (f_string_length i = 0; i < data->contents.used; i++) {
+      if (!names[i]) {
+        continue;
+      }
+
+      if (data->contents.array[i].used == 0) {
+        if (include_empty) {
+          fprintf(f_standard_output, "%c", f_string_eol);
+        }
+
+        continue;
+      }
+
+      f_print_string_dynamic_partial(f_standard_output, data->buffer, data->contents.array[i].array[0]);
+    } // for
+
     return f_none;
   }
 #endif // _di_fss_basic_list_read_main_process_file_
index 0d7c72c48c7746dc5cd835ae32b0b83b1a793f40..6ac9bd384a4e5967a6b9de629eb398d126667d73 100644 (file)
@@ -11,6 +11,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
 /**
  * A structure of parameters applied at some depth.
  *
@@ -22,8 +23,11 @@ extern "C" {
   typedef struct {
     f_string_length depth;
 
-    f_array_length parameter;
-    f_array_length position;
+    f_array_length index_at;
+    f_array_length index_name;
+
+    f_number_unsigned value_at;
+    f_string          value_name;
   } fss_basic_list_read_depth;
 
   #define fss_basic_list_read_depth_initialize \
@@ -31,6 +35,8 @@ extern "C" {
       0, \
       0, \
       0, \
+      0, \
+      f_string_initialize, \
     }
 #endif // _di_fss_basic_list_read_depth_
 
@@ -53,13 +59,13 @@ extern "C" {
 
   #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_new(status, depths, length) f_macro_memory_structure_new(status, depths, fss_basic_list_read_depth, 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_delete(status, depths) f_macro_memory_structure_delete(status, depths, fss_basic_list_read_depth)
+  #define macro_fss_basic_list_read_depths_destroy(status, depths) f_macro_memory_structure_destroy(status, depths, fss_basic_list_read_depth)
 
-  #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)
+  #define macro_fss_basic_list_read_depths_resize(status, depths, new_length) f_macro_memory_structure_resize(status, depths, fss_basic_list_read_depth, 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_depth, new_length)
 #endif // _di_fss_basic_list_read_depths_
 
 /**
@@ -79,12 +85,32 @@ extern "C" {
 #endif // _di_fss_basic_list_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_list_read_print_number_argument_error_
+  extern void fss_basic_list_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_list_read_print_number_argument_error_
+
+/**
  * Pre-process the parameters, parsing out and handling the depth and depth related parameters.
  *
+ * Will handle depth-sensitive parameter conflicts, such as --name being used with --at (which is not allowed).
+ *
  * @param arguments
  *   The console arguments to pre-process.
  * @param data
- *   The Program specific data.
+ *   The program specific data.
  * @param depths
  *   This stores the pre-processed depth parameters.
  *
@@ -96,8 +122,22 @@ extern "C" {
   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_
 
+/**
+ * Process a given file.
+ *
+ * @param arguments
+ *   The console arguments passed to the program.
+ * @param data
+ *   The program specific data.
+ * @param file_name
+ *   The name of the file being processed.
+ * @param depths
+ *   The processed depth parameters.
+ *
+ * @see 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;
+  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 file_name, const fss_basic_list_read_depths depths) f_gcc_attribute_visibility_internal;
 #endif // _di_fss_basic_list_read_main_process_file_
 
 #ifdef __cplusplus