]> Kevux Git Server - fll/commitdiff
Update: create FSS Embedded List and other minor fixes.
authorKevin Day <thekevinday@gmail.com>
Sat, 14 Nov 2020 05:33:15 +0000 (23:33 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 14 Nov 2020 05:33:15 +0000 (23:33 -0600)
The FSS-0008 Embedded List is just copied from FSS-0003 Extended List.

Fix some minor problems observed during this transition.

I will need to follow up with rewriting the FSS-0003 Extended List code.
I will probably just use FSS-0002 Basic List as a fresh starting point given that list is not recursive.

31 files changed:
build/level_1/settings
build/level_2/settings
build/monolithic/settings
level_0/f_fss/c/fss-common.h
level_1/fl_fss/c/fss_basic.h
level_1/fl_fss/c/fss_basic_list.h
level_1/fl_fss/c/fss_embedded_list.c [new file with mode: 0644]
level_1/fl_fss/c/fss_embedded_list.h [new file with mode: 0644]
level_1/fl_fss/c/fss_extended.h
level_1/fl_fss/c/fss_extended_list.h
level_1/fl_fss/data/build/settings
level_2/fll_fss/c/fss_embedded_list.c [new file with mode: 0644]
level_2/fll_fss/c/fss_embedded_list.h [new file with mode: 0644]
level_2/fll_fss/data/build/settings
level_3/fss_embedded_list_read/c/fss_embedded_list_read.c [new file with mode: 0644]
level_3/fss_embedded_list_read/c/fss_embedded_list_read.h [new file with mode: 0644]
level_3/fss_embedded_list_read/c/main.c [new file with mode: 0644]
level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c [new file with mode: 0644]
level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h [new file with mode: 0644]
level_3/fss_embedded_list_read/data/build/defines [new file with mode: 0644]
level_3/fss_embedded_list_read/data/build/dependencies [new file with mode: 0644]
level_3/fss_embedded_list_read/data/build/settings [new file with mode: 0644]
level_3/fss_embedded_list_write/c/fss_embedded_list_write.c [new file with mode: 0644]
level_3/fss_embedded_list_write/c/fss_embedded_list_write.h [new file with mode: 0644]
level_3/fss_embedded_list_write/c/main.c [new file with mode: 0644]
level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c [new file with mode: 0644]
level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h [new file with mode: 0644]
level_3/fss_embedded_list_write/data/build/defines [new file with mode: 0644]
level_3/fss_embedded_list_write/data/build/dependencies [new file with mode: 0644]
level_3/fss_embedded_list_write/data/build/settings [new file with mode: 0644]
level_3/fss_extended_list_write/c/fss_extended_list_write.h

index 35302957f0d9c7e260c37adcedd1e1ab4455ee9f..3f4a43a1e513478d2a0c9155e32ae339db6ee134 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-level -lfll_0
-build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
+build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c
 build_sources_program
-build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
+build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h
 build_sources_script
 build_sources_setting
 build_script yes
index d6c04fcb898bf32b812332248a19bebf12ea9202..55ea710dc1fe9fcf294916a16058d6b2a6256d55 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-level -lfll_1 -lfll_0
-build_sources_library error.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c
+build_sources_library error.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c
 build_sources_program
-build_sources_headers error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
+build_sources_headers error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
 build_sources_script
 build_sources_setting
 build_script yes
index 2ae883a8740e58c4020723e63e368e381652e64e..542529266b1afd8e62ec71b8f96c46bc2dbcb60c 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-monolithic
-build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c
+build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c
 build_sources_program
-build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h
+build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h
 build_sources_script
 build_sources_setting
 build_script yes
index b8129adb8b4856e977b0ee7f1c7aa967a62b4af8..bb30860b0a904db82e6eb74656d8a5e249b414f6 100644 (file)
@@ -36,6 +36,10 @@ extern "C" {
   #define f_fss_extended_list_open_end  f_string_eol[0]
   #define f_fss_extended_list_close     '}'
   #define f_fss_extended_list_close_end f_string_eol[0]
+  #define f_fss_embedded_list_open      '{'
+  #define f_fss_embedded_list_open_end  f_string_eol[0]
+  #define f_fss_embedded_list_close     '}'
+  #define f_fss_embedded_list_close_end f_string_eol[0]
   #define f_fss_type_header_open        '#'
   #define f_fss_type_header_part1       ' '
   #define f_fss_type_header_part2       'f'
@@ -73,8 +77,9 @@ extern "C" {
     f_fss_embeded_list,
     f_fss_reverse_mapping,
     f_fss_extended_reverse_mapping,
-    f_fss_simple_json,
     f_fss_simple_list,
+    f_fss_iki_text,
+    f_fss_basic_rule,
   };
 #endif // _di_f_fss_codes_
 
index ef7146d6abe202ae2f308fb447c2d7cd79278bd6..4070fd9cc06ca68c871969c145295955c0c4d091 100644 (file)
@@ -45,7 +45,7 @@ extern "C" {
  *   The start location will represent where the read stopped on return.
  *   A start location past the stop location or buffer used means that the entire range was processed.
  * @param found
- *   A set of all locations where a valid object was found.
+ *   A location where a valid object was found.
  * @param quote
  *   This will store whether or not this object is quote and what quote is in use.
  *   Set pointer address to 0 to not use.
index 16e33173346e5d82e73d72c21e98124c59253c55..962711ca3a762ced5de05363a53a7c826daba312 100644 (file)
@@ -46,7 +46,7 @@ extern "C" {
  *   The start location will represent where the read stopped on return.
  *   A start location past the stop location or buffer used means that the entire range was processed.
  * @param found
- *   A set of all locations where a valid object was found.
+ *   A location where a valid object was found.
  * @param delimits
  *   A delimits array representing where delimits exist within the buffer.
  *
diff --git a/level_1/fl_fss/c/fss_embedded_list.c b/level_1/fl_fss/c/fss_embedded_list.c
new file mode 100644 (file)
index 0000000..51b629c
--- /dev/null
@@ -0,0 +1,1300 @@
+#include "fss_embedded_list.h"
+#include "private-fss.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fl_fss_embedded_list_object_read_
+  f_return_status fl_fss_embedded_list_object_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_object_t *found, f_fss_delimits_t *delimits) {
+    #ifndef _di_level_1_parameter_checking_
+      if (!buffer) return F_status_set_error(F_parameter);
+      if (!range) return F_status_set_error(F_parameter);
+      if (!found) return F_status_set_error(F_parameter);
+      if (!delimits) return F_status_set_error(F_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    const f_array_length_t delimits_used = delimits->used;
+
+    f_status_t status = f_fss_skip_past_space(*buffer, range);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_none_eol) {
+
+      // move the start position to after the EOL.
+      range->start++;
+
+      return FL_fss_found_object_not;
+    }
+
+    if (status == F_none_eos) {
+      return F_data_not_eos;
+    }
+
+    if (status == F_none_stop) {
+      return F_data_not_stop;
+    }
+
+    // return found nothing if this line only contains whitespace and delimit placeholders.
+    if (buffer->string[range->start] == f_fss_eol) {
+
+      // move the start position to after the EOL.
+      range->start++;
+
+      return FL_fss_found_object_not;
+    }
+
+    // begin the search.
+    found->start = range->start;
+
+    // ignore all comment lines.
+    if (buffer->string[range->start] == f_fss_comment) {
+      status = f_fss_seek_to_eol(*buffer, range);
+
+      if (F_status_is_error(status)) {
+        delimits->used = delimits_used;
+        return status;
+      }
+
+      if (status == F_none_eos) {
+        return F_data_not_eos;
+      }
+
+      if (status == F_none_stop) {
+        return F_data_not_stop;
+      }
+
+      // move the start position to after the EOL.
+      range->start++;
+
+      return FL_fss_found_object_not;
+    }
+
+    f_string_length_t start = 0;
+    f_string_length_t stop = 0;
+    f_string_length_t slash_first = 0;
+    f_string_length_t slash_count = 0;
+
+    bool graph_first = F_true;
+
+    // identify where the object ends.
+    while (range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] != f_fss_eol) {
+
+      if (buffer->string[range->start] == f_fss_delimit_slash) {
+        slash_first = range->start;
+        slash_count = 1;
+
+        status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(status)) break;
+
+        while (range->start <= range->stop && range->start < buffer->used && (buffer->string[range->start] == f_fss_delimit_placeholder || buffer->string[range->start] == f_fss_delimit_slash)) {
+
+          if (buffer->string[range->start] == f_fss_delimit_slash) slash_count++;
+
+          status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(status)) break;
+        } // while
+
+        if (F_status_is_error(status)) break;
+
+        fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+        if (buffer->string[range->start] == f_fss_embedded_list_open) {
+          graph_first = F_false;
+          stop = range->start - 1;
+          range->start++;
+
+          while (range->start <= range->stop && range->start < buffer->used) {
+
+            if (buffer->string[range->start] == f_fss_eol) break;
+
+            status = f_fss_is_graph(*buffer, *range);
+            if (F_status_is_error(status)) break;
+
+            if (status == F_true) break;
+
+            status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(status)) break;
+          } // while
+
+          fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+          if (buffer->string[range->start] == f_fss_eol) {
+            start = range->start;
+
+            range->start = slash_first;
+
+            status = private_fl_fss_delimits_increase_by((slash_count / 2) + 1, delimits);
+            if (F_status_is_error(status)) break;
+
+            if (slash_count % 2 == 0) {
+              while (slash_count > 0) {
+
+                if (buffer->string[range->start] == f_fss_delimit_slash) {
+                  if (slash_count % 2 == 1) {
+                    delimits->array[delimits->used] = range->start;
+                    delimits->used++;
+                  }
+
+                  slash_count--;
+                }
+
+                status = f_utf_buffer_increment(*buffer, range, 1);
+                if (F_status_is_error(status)) break;
+              } // while
+
+              if (F_status_is_error(status)) break;
+
+              found->stop = stop;
+              range->start = start + 1;
+
+              return FL_fss_found_object;
+            }
+
+            range->start = start + 1;
+            return FL_fss_found_object_not;
+          }
+        }
+        else if (graph_first && buffer->string[range->start] == f_fss_comment) {
+          graph_first = F_false;
+
+          // comments may only have whitespace before the '#', therefore only the first slash needs to be delimited.
+          status = private_fl_fss_delimits_increase(delimits);
+          if (F_status_is_error(status)) break;
+
+          delimits->array[delimits->used++] = slash_first;
+          range->start++;
+        }
+        else {
+          graph_first = F_false;
+        }
+
+        continue;
+      }
+      else if (buffer->string[range->start] == f_fss_embedded_list_open) {
+        graph_first = F_false;
+        stop = range->start - 1;
+
+        status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(status)) break;
+
+        while (range->start <= range->stop && range->start < buffer->used) {
+
+          if (buffer->string[range->start] == f_fss_eol) break;
+
+          status = f_fss_is_space(*buffer, *range);
+          if (F_status_is_error(status)) break;
+
+          if (status == F_false) break;
+
+          status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(status)) break;
+        } // while
+
+        if (F_status_is_error(status)) break;
+
+        fl_macro_fss_object_return_on_overflow_delimited((*buffer), (*range), (*found), F_none_eos, F_none_stop);
+
+        if (buffer->string[range->start] == f_fss_eol) {
+          found->stop = stop;
+
+          // move the start position to after the EOL.
+          range->start++;
+
+          return FL_fss_found_object;
+        }
+
+        continue;
+      }
+      else if (graph_first) {
+        status = f_fss_is_space(*buffer, *range);
+        if (F_status_is_error(status)) break;
+
+        if (status == F_false) {
+          graph_first = F_false;
+        }
+      }
+
+      status = f_utf_buffer_increment(*buffer, range, 1);
+      if (F_status_is_error(status)) break;
+    } // while
+
+    if (F_status_is_error(status)) {
+      delimits->used = delimits_used;
+      return status;
+    }
+
+    // seek to the end of the line when no valid object is found.
+    while (range->start <= range->stop && range->start < buffer->used && buffer->string[range->start] != f_fss_eol) {
+
+      status = f_utf_buffer_increment(*buffer, range, 1);
+
+      if (F_status_is_error(status)) {
+        delimits->used = delimits_used;
+        return status;
+      }
+    } // while
+
+    fl_macro_fss_object_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, F_data_not_eos, F_data_not_stop);
+
+    status = f_utf_buffer_increment(*buffer, range, 1);
+
+    if (F_status_is_error(status)) {
+      delimits->used = delimits_used;
+      return status;
+    }
+
+    return FL_fss_found_object_not;
+  }
+#endif // _di_fl_fss_embedded_list_object_read_
+
+#ifndef _di_fl_fss_embedded_list_content_read_
+  f_return_status fl_fss_embedded_list_content_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *found, f_fss_delimits_t *delimits, f_fss_comments_t *comments) {
+    #ifndef _di_level_1_parameter_checking_
+      if (!buffer) return F_status_set_error(F_parameter);
+      if (!range) return F_status_set_error(F_parameter);
+      if (!found) return F_status_set_error(F_parameter);
+      if (!delimits) return F_status_set_error(F_parameter);
+      if (!comments) return F_status_set_error(F_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    const f_array_length_t found_used = found->used;
+
+    f_status_t status = f_fss_skip_past_delimit(*buffer, range);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_none_eos || status == F_none_stop) {
+      return status;
+    }
+
+    status = private_fl_fss_nest_increase(found);
+    if (F_status_is_error(status)) return status;
+
+    f_string_lengths_t positions_start = f_string_lengths_t_initialize;
+
+    f_macro_string_lengths_t_new(status, positions_start, f_fss_default_allocation_step);
+    if (F_status_is_error(status)) return status;
+
+    f_fss_objects_t objects = f_fss_objects_t_initialize;
+
+    f_macro_fss_objects_t_new(status, objects, f_fss_default_allocation_step);
+
+    if (F_status_is_error(status)) {
+      f_macro_string_lengths_t_delete_simple(positions_start);
+
+      return status;
+    }
+
+    const f_array_length_t delimits_used = delimits->used;
+    const f_array_length_t comments_used = comments->used;
+
+    f_array_length_t depth = 0;
+    f_array_length_t position = 0;
+
+    f_string_length_t position_previous = range->start;
+    f_string_length_t line_start = range->start;
+    f_string_length_t newline_last = range->start;
+    f_string_length_t comment_delimit = 0;
+
+    f_string_length_t slash_first = 0;
+    f_string_length_t slash_last = 0;
+    f_string_length_t slash_count = 0;
+
+    f_string_length_t before_list_open = position_previous;
+
+    bool is_open = F_false;
+
+    uint8_t graph_first = 0x0; // 0x0 = false, 0x1 = true, 0x2 = false, but there is a delimited comment, comment_delimit is set.
+
+    // initialize depth 1 start position.
+    // positions_start.used is used as a max depth (such that positions_start.used == max depth + 1).
+    positions_start.array[0] = range->start;
+    positions_start.used = 1;
+
+    while (range->start <= range->stop && range->start < buffer->used) {
+
+      if (buffer->string[range->start] == f_fss_eol) {
+        if (graph_first == 0x2) {
+          status = private_fl_fss_delimits_increase(delimits);
+          if (F_status_is_error(status)) break;
+
+          delimits->array[delimits->used++] = comment_delimit;
+        }
+
+        newline_last = range->start;
+        position_previous = range->start++;
+        graph_first = 0x1;
+
+        if (depth > 0) {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+        }
+        else {
+          fl_macro_fss_nest_return_on_overflow_delimited((*buffer), (*range), (*found), positions_start, objects, F_none_eos, F_none_stop);
+        }
+
+        line_start = range->start;
+        continue;
+      }
+
+      if (buffer->string[range->start] == f_fss_delimit_slash) {
+        slash_first = range->start;
+        slash_last = range->start;
+        slash_count = 1;
+
+        position_previous = range->start;
+
+        status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(status)) break;
+
+        while (range->start <= range->stop && range->start < buffer->used && (buffer->string[range->start] == f_fss_delimit_placeholder || buffer->string[range->start] == f_fss_delimit_slash)) {
+          position_previous = range->start;
+
+          if (buffer->string[range->start] == f_fss_delimit_slash) {
+            slash_last = range->start++;
+          }
+
+          status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(status)) break;
+        } // while
+
+        if (F_status_is_error(status)) break;
+
+        if (depth > 0) {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+        }
+        else {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+        }
+
+        // All slashes for an open are delimited (because it could represent a slash in the object name).
+        // for example 'object {' = valid open, name 'object', 'object \{' represents 'object {', 'object \\{' = valid open, name 'object \', 'object \\\{' represents 'object \{', etc..
+        // Only the first slash before a close is delimited, all others are maintained.
+        // for example '}' = valid close, '\}' represents '}', '\\}' represents '\}', '\\\}' represents '\\}', '\\\\}' represents '\\\}', and so on..
+        // When slash is odd and a (delimited) valid open/close is found, then save delimited positions and continue.
+        if (buffer->string[range->start] == f_fss_eol) {
+          if (graph_first == 0x2) {
+            status = private_fl_fss_delimits_increase(delimits);
+            if (F_status_is_error(status)) break;
+
+            delimits->array[delimits->used++] = comment_delimit;
+          }
+
+          newline_last = range->start;
+          position_previous = range->start++;
+          line_start = range->start;
+          graph_first = 0x1;
+        }
+        else if (buffer->string[range->start] == f_fss_embedded_list_open || buffer->string[range->start] == f_fss_embedded_list_close) {
+          before_list_open = position_previous;
+          is_open = F_false;
+          graph_first = 0x0;
+
+          if (buffer->string[range->start] == f_fss_embedded_list_open) {
+            is_open = F_true;
+          }
+
+          position_previous = range->start++;
+
+          while (range->start <= range->stop && range->start < buffer->used) {
+
+            if (buffer->string[range->start] == f_fss_eol) {
+              if (graph_first == 0x2) {
+                status = private_fl_fss_delimits_increase(delimits);
+                if (F_status_is_error(status)) break;
+
+                delimits->array[delimits->used++] = comment_delimit;
+              }
+
+              newline_last = range->start;
+              line_start = range->start + 1;
+              graph_first = 0x1;
+              break;
+            }
+
+            if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+              status = f_fss_is_space(*buffer, *range);
+              if (F_status_is_error(status)) break;
+
+              if (status == F_false) break;
+            }
+
+            position_previous = range->start;
+
+            status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(status)) break;
+          } // while
+
+          if (F_status_is_error(status)) break;
+
+          if (depth > 0) {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+          }
+          else {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+          }
+
+          // this is a valid object open/close that has been delimited, save the slash delimit positions.
+          if (buffer->string[range->start] == f_fss_eol) {
+            newline_last = range->start;
+            line_start = range->start + 1;
+            graph_first = 0x1;
+
+            if (is_open) {
+              bool is_object = F_false;
+
+              if (slash_count % 2 == 0) {
+                is_object = F_true;
+              }
+
+              range->start = slash_first;
+
+              status = private_fl_fss_delimits_increase_by((slash_count / 2) + 1, delimits);
+              if (F_status_is_error(status)) break;
+
+              // apply slash delimits, only slashes and placeholders should be present.
+              while (slash_count > 0) {
+
+                if (buffer->string[range->start] == f_fss_delimit_slash) {
+                  if (slash_count % 2 == 1) {
+                    delimits->array[delimits->used++] = range->start;
+                  }
+
+                  slash_count--;
+                }
+
+                // Delimit slashes and placeholders are required to be in the ASCII range.
+                position_previous = range->start++;
+              } // while
+
+              if (F_status_is_error(status)) break;
+
+              // when slashes are even, the object is valid and needs to be processed.
+              if (is_object) {
+                depth++;
+
+                if (depth > positions_start.size) {
+                  f_macro_string_lengths_t_resize(status, positions_start, positions_start.size + f_fss_default_allocation_step);
+                  if (F_status_is_error(status)) break;
+                }
+
+                if (positions_start.used < depth) {
+                  positions_start.used = depth;
+                }
+
+                positions_start.array[depth] = newline_last + 1;
+
+                objects.array[depth].start = line_start;
+                objects.array[depth].stop = before_list_open;
+              }
+            }
+            else {
+              status = private_fl_fss_delimits_increase(delimits);
+              if (F_status_is_error(status)) break;
+
+              delimits->array[delimits->used++] = slash_last;
+            }
+
+            range->start = newline_last;
+          }
+        }
+        else if (graph_first == 0x1 && buffer->string[range->start] == f_fss_comment) {
+          graph_first = 0x2;
+          comment_delimit = slash_first;
+        }
+        else {
+          graph_first = 0x0;
+        }
+      }
+      else if (buffer->string[range->start] == f_fss_embedded_list_open) {
+        graph_first = 0x0;
+        before_list_open = position_previous;
+        position_previous = range->start;
+
+        status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(status)) break;
+
+        while (range->start <= range->stop && range->start < buffer->used) {
+
+          if (buffer->string[range->start] == f_fss_eol) break;
+
+          if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+            status = f_fss_is_space(*buffer, *range);
+            if (F_status_is_error(status)) break;
+
+            if (status == F_false) break;
+          }
+
+          position_previous = range->start;
+
+          status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(status)) break;
+        } // while
+
+        if (F_status_is_error(status)) break;
+
+        if (depth > 0) {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+        }
+        else {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+        }
+
+        if (buffer->string[range->start] == f_fss_eol) {
+          depth++;
+
+          if (depth >= positions_start.size) {
+            f_macro_string_lengths_t_resize(status, positions_start, positions_start.size + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) break;
+
+            f_macro_fss_objects_t_resize(status, objects, objects.size + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) break;
+          }
+
+          if (positions_start.used <= depth) {
+            positions_start.used = depth + 1;
+          }
+
+          positions_start.array[depth] = range->start + 1;
+
+          objects.array[depth].start = line_start;
+          objects.array[depth].stop = before_list_open;
+
+          if (graph_first == 0x2) {
+            status = private_fl_fss_delimits_increase(delimits);
+            if (F_status_is_error(status)) break;
+
+            delimits->array[delimits->used++] = comment_delimit;
+          }
+
+          newline_last = range->start;
+          line_start = range->start + 1;
+          graph_first = 0x1;
+        }
+        else {
+
+          // No valid object close found, seek until EOL.
+          status = f_fss_seek_to_eol(*buffer, range);
+          if (F_status_is_error(status)) break;
+
+          if (graph_first == 0x2) {
+            status = private_fl_fss_delimits_increase(delimits);
+            if (F_status_is_error(status)) break;
+
+            delimits->array[delimits->used++] = comment_delimit;
+          }
+
+          newline_last = range->start;
+          line_start = range->start + 1;
+          graph_first = 0x1;
+
+          while (range->start <= range->stop && range->start < buffer->used) {
+
+            if (buffer->string[range->start] == f_fss_eol) {
+              newline_last = range->start;
+              line_start = range->start + 1;
+              break;
+            }
+
+            position_previous = range->start;
+
+            status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(status)) break;
+          } // while
+
+          if (F_status_is_error(status)) break;
+
+          if (depth > 0) {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+          }
+          else {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+          }
+        }
+      }
+      else if (buffer->string[range->start] == f_fss_embedded_list_close) {
+        graph_first = 0x0;
+
+        while (range->start <= range->stop && range->start < buffer->used) {
+
+          position_previous = range->start;
+
+          status = f_utf_buffer_increment(*buffer, range, 1);
+          if (F_status_is_error(status)) break;
+
+          if (buffer->string[range->start] == f_fss_eol) {
+            break;
+          }
+
+          if (buffer->string[range->start] != f_fss_delimit_placeholder) {
+            status = f_fss_is_space(*buffer, *range);
+            if (F_status_is_error(status)) break;
+
+            if (status == F_false) {
+              break;
+            }
+          }
+        } // while
+
+        if (F_status_is_error(status)) break;
+
+        if (depth > 0) {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop);
+        }
+        else {
+          fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop);
+        }
+
+        if (buffer->string[range->start] == f_fss_eol) {
+          status = private_fl_fss_nest_increase(found);
+          if (F_status_is_error(status)) break;
+
+          if (found->depth[depth].used == found->depth[depth].size) {
+            f_macro_fss_items_t_resize(status, found->depth[depth], found->depth[depth].size + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) break;
+          }
+
+          position = found->depth[depth].used;
+
+          if (found->depth[depth].array[position].content.size != 1) {
+            f_macro_fss_content_t_resize(status, found->depth[depth].array[position].content, 1);
+            if (F_status_is_error(status)) break;
+          }
+
+          if (depth) {
+            found->depth[depth].array[position].parent = found->depth[depth - 1].used;
+
+            // only assign object positions for nested objects.
+            found->depth[depth].array[position].object.start = objects.array[depth].start;
+            found->depth[depth].array[position].object.stop = objects.array[depth].stop;
+          }
+
+          found->depth[depth].array[position].content.array[0].start = positions_start.array[depth];
+          found->depth[depth].array[position].content.array[0].stop = newline_last;
+          found->depth[depth].array[position].content.used = 1;
+
+          if (position >= found->depth[depth].used) {
+            found->depth[depth].used++;
+          }
+
+          if (found->used < depth + 1) {
+            found->used = depth + 1;
+          }
+
+          if (graph_first == 0x2) {
+            status = private_fl_fss_delimits_increase(delimits);
+            if (F_status_is_error(status)) break;
+
+            delimits->array[delimits->used++] = comment_delimit;
+          }
+
+          newline_last = range->start;
+          line_start = range->start + 1;
+          graph_first = 0x1;
+
+          if (!depth) {
+            status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(status)) break;
+
+            fl_macro_fss_nest_return_on_overflow_delimited((*buffer), (*range), (*found), positions_start, objects, F_none_eos, F_none_stop)
+
+            f_macro_string_lengths_t_delete_simple(positions_start);
+            f_macro_fss_objects_t_delete_simple(objects);
+
+            return FL_fss_found_content;
+          }
+
+          depth--;
+        }
+        else {
+
+          // No valid object close found, seek until EOL.
+          while (range->start <= range->stop && range->start < buffer->used) {
+
+            if (buffer->string[range->start] == f_fss_eol) {
+              if (graph_first == 0x2) {
+                status = private_fl_fss_delimits_increase(delimits);
+                if (F_status_is_error(status)) break;
+
+                delimits->array[delimits->used++] = comment_delimit;
+              }
+
+              newline_last = range->start;
+              line_start = range->start + 1;
+              graph_first = 0x1;
+              break;
+            }
+
+            position_previous = range->start;
+
+            status = f_utf_buffer_increment(*buffer, range, 1);
+            if (F_status_is_error(status)) break;
+          } // while
+
+          if (F_status_is_error(status)) break;
+
+          if (depth > 0) {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_unterminated_nest_eos, F_unterminated_nest_stop)
+          }
+          else {
+            fl_macro_fss_nest_return_on_overflow((*buffer), (*range), (*found), (*delimits), delimits_used, (*comments), comments_used, positions_start, objects, F_data_not_eos, F_data_not_stop)
+          }
+        }
+      }
+      else if (graph_first == 0x1 && buffer->string[range->start] == f_fss_comment) {
+        position = range->start;
+
+        status = f_fss_seek_to_eol(*buffer, range);
+        if (F_status_is_error(status)) break;
+
+        status = private_fl_fss_ranges_increase(comments);
+        if (F_status_is_error(status)) break;
+
+        if (range->start > range->stop || range->start >= buffer->used) {
+          range->start--;
+        }
+        else {
+          if (graph_first == 0x2) {
+            status = private_fl_fss_delimits_increase(delimits);
+            if (F_status_is_error(status)) break;
+
+            delimits->array[delimits->used++] = comment_delimit;
+          }
+
+          newline_last = range->start;
+          graph_first = 0x1;
+        }
+
+        comments->array[comments->used].start = position;
+        comments->array[comments->used++].stop = range->start++;
+        continue;
+      }
+      else if (buffer->string[range->start] != f_fss_eol) {
+        position_previous = range->start;
+
+        if (graph_first == 0x1) {
+          status = f_fss_is_space(*buffer, *range);
+          if (F_status_is_error(status)) break;
+
+          if (status == F_false) {
+            graph_first = 0x0;
+          }
+        }
+
+        status = f_utf_buffer_increment(*buffer, range, 1);
+        if (F_status_is_error(status)) break;
+
+        if (range->start >= buffer->used || range->start > range->stop) {
+          break;
+        }
+
+        continue;
+      }
+
+      position_previous = range->start;
+
+      status = f_utf_buffer_increment(*buffer, range, 1);
+      if (F_status_is_error(status)) break;
+    } // while
+
+    f_macro_string_lengths_t_delete_simple(positions_start);
+    f_macro_fss_objects_t_delete_simple(objects);
+
+    delimits->used = delimits_used;
+    comments->used = comments_used;
+
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    if (range->start > range->stop) {
+      if (!depth) {
+        return F_status_set_error(F_unterminated_stop);
+      }
+
+      return F_status_set_error(F_unterminated_nest_stop);
+    }
+
+    if (!depth) {
+      return F_status_set_error(F_unterminated_eos);
+    }
+
+    return F_status_set_error(F_unterminated_nest_eos);
+  }
+#endif // _di_fl_fss_embedded_list_content_read_
+
+#ifndef _di_fl_fss_embedded_list_object_write_string_
+  f_return_status fl_fss_embedded_list_object_write_string(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    f_status_t status = f_fss_skip_past_delimit(object, range);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_none_eos) {
+      status = F_data_not_eos;
+    }
+    else if (status == F_none_stop) {
+      status = F_data_not_stop;
+    }
+
+    if (status == F_data_not_stop || status == F_data_not_eos) {
+      if (complete == f_fss_complete_partial || complete == f_fss_complete_partial_trim || complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+        const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination);
+        if (F_status_is_error(status_allocation)) return status_allocation;
+
+        destination->string[destination->used++] = f_fss_embedded_list_open;
+
+        if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+          destination->string[destination->used++] = f_fss_embedded_list_open_end;
+        }
+      }
+
+      return status;
+    }
+
+    // ensure that there is room for a slash delimit, the object open character, and the end of line character.
+    status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+    if (F_status_is_error(status)) return status;
+
+    const f_string_length_t input_start = range->start;
+    const f_string_length_t used_start = destination->used;
+
+    f_string_length_t i = 0;
+    f_string_length_t slash_count = 0;
+
+    f_string_range_t range_next = f_string_range_t_initialize;
+
+    bool ends_on_space = F_false;
+
+    uint8_t width = 0;
+
+    // find the first graph character.
+    while (range->start <= range->stop && range->start < object.used) {
+
+      if (object.string[range->start] == f_fss_comment) {
+
+        // when a comment is found, escape it.
+        status = private_fl_fss_destination_increase(destination);
+        if (F_status_is_error(status)) break;
+
+        destination->string[destination->used++] = f_fss_delimit_slash;
+        break;
+      }
+
+      status = f_fss_is_graph(object, *range);
+      if (F_status_is_error(status)) break;
+
+      if (status == F_true) break;
+
+      // objects will not have leading whitespaces, but having this does not result in an invalid object, so just write the provided spaces.
+      if (object.string[range->start] != f_fss_delimit_placeholder) {
+        if (object.string[range->start] == f_fss_eol) {
+          status = F_status_set_error(F_none_eol);
+          break;
+        }
+
+        status = f_fss_is_space(object, *range);
+        if (F_status_is_error(status)) break;
+
+        if (status == F_true) {
+          width = f_macro_utf_byte_width(object.string[range->start]);
+
+          status = private_fl_fss_destination_increase_by(width, destination);
+          if (F_status_is_error(status)) break;
+
+          for (i = 0; i < width; i++) {
+            destination->string[destination->used++] = object.string[range->start + i];
+          } // for
+        }
+      }
+
+      status = f_utf_buffer_increment(object, range, 1);
+      if (F_status_is_error(status)) break;
+    } // while
+
+    if (F_status_is_error(status)) {
+      destination->used = used_start;
+      return status;
+    }
+
+    while (range->start <= range->stop && range->start < object.used) {
+
+      if (object.string[range->start] == f_fss_delimit_slash) {
+        slash_count = 1;
+
+        for (range->start++; range->start <= range->stop && range->start < object.used; range->start++) {
+
+          if (object.string[range->start] == f_fss_delimit_placeholder) {
+            continue;
+          } else if (object.string[range->start] != f_fss_delimit_slash) {
+            break;
+          }
+
+          slash_count++;
+        } // for
+
+        if (F_status_is_error(status)) break;
+
+        if (range->start > range->stop || range->start >= object.used) {
+
+          // slashes at the end of the object must be delimited to avoid delimiting the object close character.
+          slash_count *= 2;
+        }
+
+        status = private_fl_fss_destination_increase_by(slash_count, destination);
+        if (F_status_is_error(status)) break;
+
+        while (slash_count--) {
+          destination->string[destination->used++] = f_fss_delimit_slash;
+        } // while
+
+        if (range->start > range->stop || range->start >= object.used) {
+          ends_on_space = F_false;
+          break;
+        }
+      }
+
+      if (object.string[range->start] != f_fss_delimit_placeholder) {
+        if (object.string[range->start] == f_fss_eol) {
+          status = F_status_set_error(F_none_eol);
+          break;
+        }
+
+        status = f_fss_is_space(object, *range);
+        if (F_status_is_error(status)) break;
+
+        ends_on_space = status == F_true;
+
+        width = f_macro_utf_byte_width(object.string[range->start]);
+
+        status = private_fl_fss_destination_increase_by(width, destination);
+        if (F_status_is_error(status)) break;
+
+        for (i = 0; i < width; i++) {
+          destination->string[destination->used++] = object.string[range->start + i];
+        } // for
+      }
+
+      status = f_utf_buffer_increment(object, range, 1);
+      if (F_status_is_error(status)) break;
+    } // while
+
+    if (F_status_is_error(status)) {
+      destination->used = used_start;
+      return status;
+    }
+
+    if (complete == f_fss_complete_partial || complete == f_fss_complete_partial_trim || complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+      if (complete == f_fss_complete_full_trim) {
+        status = private_fl_fss_basic_list_write_object_trim(used_start, destination);
+
+        if (F_status_is_error(status)) {
+          destination->used = used_start;
+          return status;
+        }
+
+        // prevent a space from being added post-trimming.
+        ends_on_space = F_true;
+      }
+
+      status = private_fl_fss_destination_increase_by(3, destination);
+
+      if (F_status_is_error(status)) {
+        destination->used = used_start;
+        return status;
+      }
+
+      if (!ends_on_space) {
+        destination->string[destination->used++] = f_fss_space;
+      }
+
+      destination->string[destination->used++] = f_fss_embedded_list_open;
+
+      if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim) {
+        destination->string[destination->used++] = f_fss_embedded_list_open_end;
+      }
+    }
+
+    if (range->start > range->stop) {
+      return F_none_stop;
+    }
+
+    if (range->start >= object.used) {
+      return F_none_eos;
+    }
+
+    return F_none;
+  }
+#endif // _di_fl_fss_embedded_list_object_write_string_
+
+#ifndef _di_fl_fss_embedded_list_content_write_string_
+  f_return_status fl_fss_embedded_list_content_write_string(const f_string_static_t content, const uint8_t complete, const f_string_static_t *prepend, const f_string_ranges_t *ignore, f_string_range_t *range, f_string_dynamic_t *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (!range) return F_status_set_error(F_parameter);
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    f_status_t status = f_fss_skip_past_delimit(content, range);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_none_eos) {
+      status = F_data_not_eos;
+    }
+    else if (status == F_none_stop) {
+      status = F_data_not_stop;
+    }
+
+    if (range->start > range->stop || range->start >= content.used) {
+      if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim || complete == f_fss_complete_end) {
+        const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination);
+        if (F_status_is_error(status_allocation)) return status_allocation;
+
+        destination->string[destination->used++] = f_fss_embedded_list_close;
+        destination->string[destination->used++] = f_fss_embedded_list_close_end;
+      }
+
+      return status;
+    }
+
+    // ensure that there is room for a slash delimit and possibly the end of content characters.
+    status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+    if (F_status_is_error(status)) return status;
+
+    const f_string_length_t input_start = range->start;
+    const f_string_length_t used_start = destination->used;
+
+    bool is_comment = F_false;
+    bool ends_on_eol = F_false;
+    bool has_graph = F_false;
+    bool do_prepend = F_true;
+
+    f_string_length_t i = 0;
+    f_string_length_t slash_count = 0;
+    f_string_length_t start = 0;
+
+    f_array_length_t r = 0;
+
+    uint8_t width = 0;
+
+    while (range->start <= range->stop && range->start < content.used) {
+
+      if (content.string[range->start] == f_fss_delimit_slash && !is_comment) {
+        slash_count = 1;
+
+        if (do_prepend) {
+          status = private_fl_fss_destination_prepend(prepend, destination);
+          if (F_status_is_error(status)) break;
+
+          do_prepend = F_false;
+        }
+
+        destination->string[destination->used++] = content.string[range->start];
+
+        for (range->start++; range->start <= range->stop && range->start < content.used; range->start++) {
+
+          if (content.string[range->start] == f_fss_delimit_placeholder) continue;
+          if (content.string[range->start] != f_fss_delimit_slash) break;
+
+          destination->string[destination->used++] = f_fss_delimit_slash;
+          slash_count++;
+        } // for
+
+        if (content.string[range->start] == f_fss_embedded_list_open || content.string[range->start] == f_fss_embedded_list_close) {
+          start = range->start++;
+
+          status = f_fss_skip_past_space(content, range);
+          if (F_status_is_error(status)) break;
+
+          if (has_graph && content.string[range->start] == f_fss_embedded_list_close) {
+            // do nothing.
+          }
+          else if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+
+            if (content.string[range->start] == f_fss_eol) {
+              ends_on_eol = F_true;
+            }
+            else {
+              ends_on_eol = F_false;
+            }
+
+            // increase by total slashes + 1, along with the extended list open and possible newline.
+            status = private_fl_fss_destination_increase_by(slash_count + 3, destination);
+            if (F_status_is_error(status)) break;
+
+            while (slash_count--) {
+              destination->string[destination->used++] = f_fss_delimit_slash;
+            } // while
+
+            destination->string[destination->used++] = f_fss_delimit_slash;
+            destination->string[destination->used++] = content.string[start];
+
+            range->start = start + 1;
+
+            status = private_fl_fss_basic_list_write_add_until_end(content, range, destination);
+            if (F_status_is_error(status)) break;
+
+            if (content.string[range->start] != f_fss_eol) {
+              has_graph = F_true;
+            }
+
+            continue;
+          }
+
+          // increase by character at "start" and possible newline.
+          status = private_fl_fss_destination_increase_by(2, destination);
+          if (F_status_is_error(status)) break;
+
+          destination->string[destination->used++] = content.string[start];
+
+          if (content.string[range->start] == f_fss_eol) {
+            destination->string[destination->used++] = f_fss_eol;
+            ends_on_eol = F_true;
+          }
+          else {
+            ends_on_eol = F_false;
+          }
+
+          range->start = start + 1;
+          continue;
+        }
+      }
+      else if ((content.string[range->start] == f_fss_embedded_list_open || (!has_graph && content.string[range->start] == f_fss_embedded_list_close)) && !is_comment) {
+        start = range->start++;
+
+        if (do_prepend) {
+          status = private_fl_fss_destination_prepend(prepend, destination);
+          if (F_status_is_error(status)) break;
+
+          do_prepend = F_false;
+        }
+
+        has_graph = F_true;
+
+        status = f_fss_skip_past_space(content, range);
+        if (F_status_is_error(status)) break;
+
+        if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+
+          if (content.string[range->start] == f_fss_eol) {
+            do_prepend = F_true;
+            ends_on_eol = F_true;
+          }
+          else {
+            ends_on_eol = F_false;
+          }
+
+          if (ignore && ignore->used) {
+
+            for (r = 0; r < ignore->used; r++) {
+              if (start >= ignore->array[r].start && start <= ignore->array[r].stop) break;
+            } // for
+
+            if (r < ignore->used) {
+              status = private_fl_fss_destination_increase(destination);
+              if (F_status_is_error(status)) break;
+
+              destination->string[destination->used++] = content.string[start];
+              range->start = start + 1;
+              continue;
+            }
+          }
+
+          // increase by slash and extended list open and possible newline.
+          status = private_fl_fss_destination_increase_by(3, destination);
+          if (F_status_is_error(status)) break;
+
+          destination->string[destination->used++] = f_fss_delimit_slash;
+          destination->string[destination->used++] = content.string[start];
+
+          range->start = start + 1;
+
+          status = private_fl_fss_basic_list_write_add_until_end(content, range, destination);
+          if (F_status_is_error(status)) break;
+
+          continue;
+        }
+
+        status = private_fl_fss_destination_increase(destination);
+        if (F_status_is_error(status)) break;
+
+        destination->string[destination->used++] = content.string[start];
+        range->start = start + 1;
+        continue;
+      }
+      else if (content.string[range->start] == f_fss_comment && !has_graph) {
+        is_comment = F_true;
+      }
+      else if (content.string[range->start] == f_fss_eol) {
+        has_graph = F_false;
+        is_comment = F_false;
+      }
+      else if ((status = f_fss_is_graph(content, *range)) == F_true) {
+        has_graph = F_true;
+      }
+      else if (F_status_is_error(status)) {
+        break;
+      }
+
+      if (content.string[range->start] != f_fss_delimit_placeholder) {
+        if (do_prepend) {
+          status = private_fl_fss_destination_prepend(prepend, destination);
+          if (F_status_is_error(status)) break;
+
+          do_prepend = F_false;
+        }
+
+        if (content.string[range->start] == f_fss_eol) {
+          do_prepend = F_true;
+          ends_on_eol = F_true;
+        }
+        else {
+          ends_on_eol = F_false;
+        }
+
+        width = f_macro_utf_byte_width(content.string[range->start]);
+
+        status = private_fl_fss_destination_increase_by(width, destination);
+        if (F_status_is_error(status)) break;
+
+        for (i = 0; i < width; i++) {
+          destination->string[destination->used++] = content.string[range->start + i];
+        } // for
+      }
+
+      status = f_utf_buffer_increment(content, range, 1);
+      if (F_status_is_error(status)) break;
+    } // while
+
+    if (F_status_is_error(status)) {
+      destination->used = used_start;
+      return status;
+    }
+
+    if (complete == f_fss_complete_full || complete == f_fss_complete_full_trim || complete == f_fss_complete_end) {
+      status = private_fl_fss_destination_increase_by(3, destination);
+      if (F_status_is_error(status)) return status;
+
+      if (!ends_on_eol) {
+        destination->string[destination->used++] = f_fss_eol;
+      }
+
+      destination->string[destination->used++] = f_fss_embedded_list_close;
+      destination->string[destination->used++] = f_fss_embedded_list_close_end;
+    }
+
+    if (range->start > range->stop) {
+      return F_none_stop;
+    }
+
+    if (range->start >= content.used) {
+      return F_none_eos;
+    }
+
+    return F_none;
+  }
+#endif // _di_fl_fss_embedded_list_content_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_1/fl_fss/c/fss_embedded_list.h b/level_1/fl_fss/c/fss_embedded_list.h
new file mode 100644 (file)
index 0000000..dc15a5c
--- /dev/null
@@ -0,0 +1,225 @@
+/**
+ * FLL - Level 1
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the fss-0008 implementation.
+ */
+#ifndef _FL_fss_embedded_list_h
+#define _FL_fss_embedded_list_h
+
+// libc includes
+#include <ctype.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/status.h>
+#include <level_0/fss.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/type.h>
+#include <level_0/utf.h>
+
+// fll-1 includes
+#include <level_1/fss.h>
+#include <level_1/fss_basic.h>
+#include <level_1/fss_status.h>
+#include <level_1/fss_macro.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read an fss-0008 object.
+ *
+ * This will record where delimit placeholders exist but will not apply the delimits.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ *   This will be updated with delimit placeholders as it is being processed.
+ * @param range
+ *   The start/stop location within the buffer to be processed.
+ *   The start location will be updated as the buffer is being processed.
+ *   The start location will represent where the read stopped on return.
+ *   A start location past the stop location or buffer used means that the entire range was processed.
+ * @param found
+ *   A location where a valid object was found.
+ * @param delimits
+ *   A delimits array representing where delimits exist within the buffer.
+ *
+ * @return
+ *   FL_fss_found_object on success and object was found (start location is at end of object).
+ *   FL_fss_found_object_not on success and no object was found (start location is after character designating this is not an object).
+ *   F_none_eos on success after reaching the end of the buffer (a valid object is not yet confirmed).
+ *   F_none_stop on success after reaching stopping point (a valid object is not yet confirmed).
+ *   F_data_not_eos no objects found after reaching the end of the buffer (essentially only comments are found).
+ *   F_data_not_stop no data found after reaching stopping point (essentially only comments are found).
+ *   F_unterminated_group_eos if EOS was reached before the a group termination was reached.
+ *   F_unterminated_group_stop if stop point was reached before the a group termination was reached.
+ *   F_array_too_large (with error bit) if a buffer is too large.
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ *   F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ *   Errors (with error bit) from: f_utf_buffer_increment().
+ *   Errors (with error bit) from: f_fss_is_graph().
+ *   Errors (with error bit) from: f_fss_is_space().
+ *   Errors (with error bit) from: f_fss_seek_to_eol().
+ *   Errors (with error bit) from: f_fss_skip_past_space().
+ */
+#ifndef _di_fl_fss_embedded_list_object_read_
+  extern f_return_status fl_fss_embedded_list_object_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_object_t *found, f_fss_delimits_t *delimits);
+#endif // _di_fl_fss_embedded_list_object_read_
+
+/**
+ * Read an fss-0008 content.
+ *
+ * @fixme the recursive part of this is actually fss-0008 (Embedded) content, fss-0008 is not recursive, oops!
+ *
+ * This will record where delimit placeholders exist but will not apply the delimits.
+ *
+ * This operates on the assumption that found.array[0].array[found.array[0].used].content is the current content being processed.
+ * Therefore the object for this content will also need to be found.array[0].array[found.array[0].used].object.
+ * The object at depth 0 will not be populated, but all nested objects will be populated at their respective depth along with the content.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ *   This will be updated with delimit placeholders as it is being processed.
+ * @param range
+ *   The start/stop location within the buffer to be processed.
+ *   The start location will be updated as the buffer is being processed.
+ *   The start location will represent where the read stopped on return.
+ *   A start location past the stop location or buffer used means that the entire range was processed.
+ * @param found
+ *   A set of all locations where a valid content was found.
+ * @param delimits
+ *   A delimits array representing where delimits exist within the buffer.
+ * @param comments
+ *   An array of ranges representing where comments are found within any valid content.
+ *   This only stores comments found within valid content only.
+ *   The comment range will include the trailing newline.
+ *
+ * @return
+ *   FL_fss_found_content on success and content was found (start location is at end of content).
+ *   FL_fss_found_content_not on success and no content was found (start location is after character designating this is not a content).
+ *   F_none_eos on success after reaching the end of the buffer (a valid object is not yet confirmed).
+ *   F_none_stop on success after reaching stopping point (a valid object is not yet confirmed).
+ *   F_data_not_eos no objects found after reaching the end of the buffer (essentially only comments are found).
+ *   F_data_not_stop no data found after reaching stopping point (essentially only comments are found).
+ *   F_unterminated_group_eos if EOS was reached before the a group termination was reached.
+ *   F_unterminated_group_stop if stop point was reached before the a group termination was reached.
+ *   F_array_too_large (with error bit) if a buffer is too large.
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ *   F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ *   Errors (with error bit) from: f_utf_buffer_increment().
+ *   Errors (with error bit) from: f_fss_is_graph().
+ *   Errors (with error bit) from: f_fss_is_space().
+ *   Errors (with error bit) from: f_fss_skip_past_space().
+ */
+#ifndef _di_fl_fss_embedded_list_content_read_
+  extern f_return_status fl_fss_embedded_list_content_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *found, f_fss_delimits_t *delimits, f_fss_comments_t *comments);
+#endif // _di_fl_fss_embedded_list_content_read_
+
+/**
+ * Write an fss-0008 object from a given string.
+ *
+ * This will write the given string range as a valid object.
+ * Anything within this range will be escaped as necessary.
+ * This will stop if EOL is reached.
+ *
+ * The destination string may have NULLs.
+ *
+ * @param object
+ *   The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ *   If f_fss_complete_none, then only the object name is written.
+ *   If f_fss_complete_full, this will write any appropriate open and close aspects of this object.
+ *   If f_fss_complete_full_trim, this will write any appropriate open and close aspects of this object, but will omit whitespace before and after the object.
+ *   If f_fss_complete_partial, this will write any appropriate open and close aspects of this object.
+ *   If f_fss_complete_partial_tim, this will write any appropriate open and close aspects of this object, but will omit whitespace before and after the object.
+ * @param range
+ *   The start/stop location within the object string to write as an object.
+ * @param destination
+ *   The buffer where the object is written to.
+ *
+ * @return
+ *   F_none on success.
+ *   F_none_eos on success after reaching the end of the buffer.
+ *   F_data_not_stop no data to write due start location being greater than stop location.
+ *   F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ *   F_none_stop on success after reaching stopping point .
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ *   Errors (with error bit) from: f_utf_buffer_increment().
+ */
+#ifndef _di_fl_fss_embedded_list_object_write_string_
+  extern f_return_status fl_fss_embedded_list_object_write_string(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination);
+#endif // _di_fl_fss_embedded_list_object_write_string_
+
+/**
+ * Write an fss-0008 content from a given string.
+ *
+ * This will write the given string range as a valid content.
+ * Anything within this range will be escaped as necessary.
+ *
+ * The destination string may have NULLs.
+ *
+ * @param content
+ *   The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ *   If f_fss_complete_none, then only the content is written.
+ *   If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ *   If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ *   If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ *   If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
+ * @param prepend
+ *   A string of whitespace to prepend at the start of each line.
+ *   This should only be whitespace, anything else could product invalid content.
+ *   Set the pointer address to 0 to disable.
+ * @param ignore
+ *   An optional list of ranges within the string to ignore.
+ *   These ranges are only checked/ignored if there is a valid nested object open or a valid nested object close.
+ *   Any valid nested object open or valid nested object close inside an ingore range will not be escaped.
+ *   Set the pointer address to 0 to disable.
+ * @param range
+ *   The start/stop location within the content string to write as an content.
+ * @param destination
+ *   The buffer where the content is written to.
+ *
+ * @return
+ *   F_none on success.
+ *   F_none_eos on success after reaching the end of the buffer.
+ *   F_data_not_stop no data to write due start location being greater than stop location.
+ *   F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ *   F_none_stop on success after reaching stopping point .
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ *   Errors (with error bit) from: f_utf_buffer_increment().
+ */
+#ifndef _di_fl_fss_embedded_list_content_write_string_
+  extern f_return_status fl_fss_embedded_list_content_write_string(const f_string_static_t content, const uint8_t complete, const f_string_static_t *prepend, const f_string_ranges_t *ignore, f_string_range_t *range, f_string_dynamic_t *destination);
+#endif // _di_fl_fss_embedded_list_content_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FL_fss_embedded_list_h
index 7285c2fff332bf350be4de05c3a865ded782fbd4..7f1e3d2894ec6a0c47dea456889291e8a5569963 100644 (file)
@@ -45,7 +45,7 @@ extern "C" {
  *   The start location will represent where the read stopped on return.
  *   A start location past the stop location or buffer used means that the entire range was processed.
  * @param found
- *   A set of all locations where a valid object was found.
+ *   A location where a valid object was found.
  * @param quoted
  *   This will store whether or not this object is quoted and what quote is in use.
  *   Set pointer address to 0 to not use.
index e5a1358b07581d5409a3cb8cc59028ed6feaea89..d21f569069bda1f6d4846e2830c4e06df1097896 100644 (file)
@@ -46,7 +46,7 @@ extern "C" {
  *   The start location will represent where the read stopped on return.
  *   A start location past the stop location or buffer used means that the entire range was processed.
  * @param found
- *   A set of all locations where a valid object was found.
+ *   A location where a valid object was found.
  * @param delimits
  *   A delimits array representing where delimits exist within the buffer.
  *
@@ -80,6 +80,8 @@ extern "C" {
 /**
  * Read an fss-0003 content.
  *
+ * @fixme the recursive part of this is actually fss-0008 (Embedded) content, fss-0003 is not recursive, oops!
+ *
  * This will record where delimit placeholders exist but will not apply the delimits.
  *
  * This operates on the assumption that found.array[0].array[found.array[0].used].content is the current content being processed.
index 3910c9068e2580369ccda708b06d4c2402ed8320..1bcef408c7687836c687851ac602fadaa3ff8f72 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-individual -lf_file -lf_fss -lf_memory -lf_utf
-build_sources_library private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c
+build_sources_library private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c
 build_sources_program
-build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h
+build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h
 build_sources_script
 build_sources_setting
 build_script yes
diff --git a/level_2/fll_fss/c/fss_embedded_list.c b/level_2/fll_fss/c/fss_embedded_list.c
new file mode 100644 (file)
index 0000000..39b7bf2
--- /dev/null
@@ -0,0 +1,151 @@
+#include "fss_embedded_list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fll_fss_embedded_list_read_
+  f_return_status fll_fss_embedded_list_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *nest, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) {
+    #ifndef _di_level_3_parameter_checking_
+      if (!buffer) return F_status_set_error(F_parameter);
+      if (!range) return F_status_set_error(F_parameter);
+      if (!nest) return F_status_set_error(F_parameter);
+      if (!objects_delimits) return F_status_set_error(F_parameter);
+      if (!comments) return F_status_set_error(F_parameter);
+    #endif // _di_level_3_parameter_checking_
+
+    f_status_t status = F_none;
+    f_status_t status2 = F_none;
+    f_string_length_t initial_used = 0;
+
+    bool found_data = F_false;
+
+    if (!nest->used) {
+      f_macro_fss_nest_t_resize(status2, (*nest), f_fss_default_allocation_step);
+      if (F_status_is_error(status2)) return status2;
+    }
+    else {
+      initial_used = nest->depth[0].used;
+    }
+
+    do {
+      do {
+        if (nest->depth[0].used == nest->depth[0].size) {
+          f_macro_fss_items_t_resize(status2, nest->depth[0], nest->depth[0].used + f_fss_default_allocation_step);
+          if (F_status_is_error(status)) return status;
+        }
+
+        status = fl_fss_embedded_list_object_read(buffer, range, &nest->depth[0].array[nest->depth[0].used].object, objects_delimits);
+        if (F_status_is_error(status)) return status;
+
+        if (range->start >= range->stop || range->start >= buffer->used) {
+          if (status == FL_fss_found_object || status == FL_fss_found_object_content_not) {
+
+            // extended list requires content closure, so this could be an error.
+            return FL_fss_found_object_content_not;
+          }
+
+          if (found_data) {
+            if (range->start >= buffer->used) {
+              return F_none_eos;
+            }
+
+            return F_none_stop;
+          }
+          else {
+            if (range->start >= buffer->used) {
+              return F_data_not_eos;
+            }
+
+            return F_data_not_stop;
+          }
+        }
+
+        if (status == FL_fss_found_object) {
+          found_data = F_true;
+
+          status = fl_fss_embedded_list_content_read(buffer, range, nest, contents_delimits ? contents_delimits : objects_delimits, comments);
+
+          break;
+        }
+        else if (status == FL_fss_found_object_content_not) {
+          found_data = F_true;
+          break;
+        }
+      } while (status == FL_fss_found_object_not);
+
+      if (status == F_none_eos || status == F_none_stop) {
+        return status;
+      }
+      else if (status == F_data_not_eos || status == F_data_not_stop) {
+
+        // If at least some valid object was found, then return F_none equivalents.
+        if (nest->depth[0].used > initial_used) {
+          if (status == F_data_not_eos) return F_none_eos;
+          if (status == F_data_not_stop) return F_none_stop;
+        }
+
+        return status;
+      }
+      else if (status == F_unterminated_eos || status == F_unterminated_stop || status == F_unterminated_nest_eos || status == F_unterminated_nest_stop) {
+
+        // If at least some valid object was found, then return F_none equivalents.
+        if (nest->depth[0].used > initial_used) {
+          if (status == F_data_not_eos) return F_none_eos;
+          if (status == F_data_not_stop) return F_none_stop;
+        }
+
+        return status;
+      }
+      else if (status != FL_fss_found_object && status != FL_fss_found_content && status != FL_fss_found_content_not && status != FL_fss_found_object_content_not) {
+        return status;
+      }
+      // When content is found, the range->start is incremented, if content is found at range->stop, then range->start will be > range.stop.
+      else if (range->start >= range->stop || range->start >= buffer->used) {
+        if (range->start >= buffer->used) {
+          return F_none_eos;
+        }
+
+        return F_none_stop;
+      }
+    } while (range->start < f_string_length_t_size);
+
+    return F_status_is_error(F_number_overflow);
+  }
+#endif // _di_fll_fss_embedded_list_read_
+
+#ifndef _di_fll_fss_embedded_list_write_string_
+  f_return_status fll_fss_embedded_list_write_string(const f_string_static_t object, const f_string_static_t content, const f_string_static_t *content_prepend, const f_string_ranges_t *ignore, f_string_dynamic_t *destination) {
+    #ifndef _di_level_2_parameter_checking_
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    f_status_t status = 0;
+    f_string_range_t range = f_macro_string_range_t_initialize(object.used);
+
+    status = fl_fss_embedded_list_object_write_string(object, f_fss_complete_full, &range, destination);
+
+    if (F_status_is_error(status) || status == F_data_not_stop || status == F_data_not_eos) {
+      return status;
+    }
+
+    if (status == F_none || status == F_none_stop || status == F_none_eos || status == F_none_eol) {
+      if (content.used) {
+        range.start = 0;
+        range.stop = content.used - 1;
+      }
+      else {
+        range.start = 1;
+        range.stop = 0;
+      }
+
+      status = fl_fss_embedded_list_content_write_string(content, f_fss_complete_full, content_prepend, ignore, &range, destination);
+    }
+
+    return status;
+  }
+#endif // _di_fll_fss_embedded_list_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_2/fll_fss/c/fss_embedded_list.h b/level_2/fll_fss/c/fss_embedded_list.h
new file mode 100644 (file)
index 0000000..c5351f0
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the fss-0008 implementation.
+ */
+#ifndef _FLL_fss_embedded_list_h
+#define _FLL_fss_embedded_list_h
+
+// fll-0 includes
+#include <level_0/status.h>
+#include <level_0/fss.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/type.h>
+
+// fll-1 includes
+#include <level_1/fss.h>
+#include <level_1/fss_embedded_list.h>
+#include <level_1/fss_status.h>
+#include <level_1/fss_macro.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read a buffer expected to be in fss-0008 format, getting all objects and their respective content.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ * @param range
+ *   The range within the buffer that is currently being read.
+ * @param nest
+ *   An nested set of all objects and content.
+ * @param objects_delimits
+ *   An array of delimits for objects detected during processing.
+ *   The caller is expected to decide if and when to process them.
+ * @param contents_delimits
+ *   (optional) An array of delimits for contents detected during processing.
+ *   The caller is expected to decide if and when to process them.
+ *   Set pointer address to 0 and all delimits will instead utilize objects_delimits.
+ * @param comments
+ *   An array of ranges representing where comments are found within any valid content.
+ *   This only stores comments found within valid content only.
+ *
+ * @return
+ *   F_none on success (both valid object and valid content found with start location is at end of content).
+ *   F_none_eos on success after reaching the end of the buffer (both valid object and valid content found with start location is at end of buffer).
+ *   F_none_stop on success after reaching stopping point (both valid object and valid content found with start location is at stop point).
+ *   F_data_not_eol if there is no data to write and EOL was reached (@todo: review related code and detemine what this is doing).
+ *   F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ *   F_data_not_stop no data to write due start location being greater than stop location.
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_incomplete_utf_eos (with error bit) if the end of buffer is reached before the complete UTF-8 character can be processed.
+ *   F_incomplete_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_number_overflow (with error bit) if the maximimum buffer size is reached.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_unterminated_eos (with error bit) if end of buffer is reached before a closing bracket is found (object was found).
+ *   F_unterminated_nest_eos (with error bit) if end of buffer is reached while inside a nested list before a closing bracket is found (object was found).
+ *   F_unterminated_nest_stop (with error bit) if stop location is reached while inside a nested list before a closing bracket is found (object was found).
+ *   F_unterminated_stop (with error bit) if stop location is reached before a closing bracket is found (object was found).
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *   FL_fss_found_object_content_not on success and object was found but no content was found (start location is at end of object).
+ *
+ *   Errors (with error bit) from: fl_fss_embedded_list_content_read().
+ *   Errors (with error bit) from: fl_fss_embedded_list_object_read().
+ */
+#ifndef _di_fll_fss_embedded_list_read_
+  extern f_return_status fll_fss_embedded_list_read(f_string_dynamic_t *buffer, f_string_range_t *range, f_fss_nest_t *nest, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments);
+#endif // _di_fll_fss_embedded_list_read_
+
+/**
+ * Write a single object string and content string to a buffer, using fss-0008 format.
+ *
+ * @param object
+ *   A string representing the object.
+ * @param content
+ *   A string representing the content.
+ * @param content_prepend
+ *   A string to prepend at the start of each line in content, such as spaces.
+ *   Set the pointer address to 0 to disable.
+ * @param ignore
+ *   An optional list of ranges within the string to ignore.
+ *   These ranges are only checked/ignored if there is a valid nested object open or a valid nested object close.
+ *   Any valid nested object open or valid nested object close inside an ingore range will not be escaped.
+ *   Set the pointer address to 0 to disable.
+ * @param destination
+ *   The buffer where the content is written to.
+ *
+ * @return
+ *   F_none on success.
+ *   F_none_eos on success after reaching the end of the buffer.
+ *   F_none_stop on success after reaching stopping point.
+ *   F_data_not_eos no data to write due start location being greater than or equal to buffer size.
+ *   F_data_not_stop no data to write due start location being greater than stop location.
+ *   F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
+ *   F_memory_reallocation (with error bit) on reallocation error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
+ *
+ *   Errors (with error bit) from: fl_fss_embedded_list_content_write_string().
+ *   Errors (with error bit) from: fl_fss_embedded_list_object_write_string().
+ *   Errors (with error bit) from: fl_string_dynamic_increase_by().
+ */
+#ifndef _di_fll_fss_embedded_list_write_string_
+  extern f_return_status fll_fss_embedded_list_write_string(const f_string_static_t object, const f_string_static_t content, const f_string_static_t *content_prepend, const f_string_ranges_t *ignore, f_string_dynamic_t *destination);
+#endif // _di_fll_fss_embedded_list_write_string_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FLL_fss_embedded_list_h
index c98f4e253cf754ed06dc9f4394190f4dbcffbca8..660ddf44c4be2f6e7d0d8d08db211c54ad94d5f5 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-individual -lfl_conversion -lfl_fss -lfl_status -lfl_string -lf_conversion -lf_file -lf_fss -lf_memory -lf_utf
-build_sources_library fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c
+build_sources_library fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c
 build_sources_program
-build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h
+build_sources_headers fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h
 build_sources_script
 build_sources_setting
 build_script yes
diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c
new file mode 100644 (file)
index 0000000..c625e52
--- /dev/null
@@ -0,0 +1,529 @@
+#include "fss_embedded_list_read.h"
+#include "private-fss_embedded_list_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_print_help_
+  f_return_status fss_embedded_list_read_print_help(const f_file_t output, const f_color_context_t context) {
+
+    fll_program_print_help_header(output, context, fss_embedded_list_read_name_long, fss_embedded_list_read_version);
+
+    fll_program_print_help_option(output, context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Print this help message.");
+    fll_program_print_help_option(output, context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, "    Output using colors that show up better on dark backgrounds.");
+    fll_program_print_help_option(output, context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Output using colors that show up better on light backgrounds.");
+    fll_program_print_help_option(output, context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color.");
+    fll_program_print_help_option(output, context, f_console_standard_short_quiet, f_console_standard_long_quiet, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Decrease verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_normal, f_console_standard_long_normal, f_console_symbol_short_disable, f_console_symbol_long_disable, "  Set verbosity to normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_verbose, f_console_standard_long_verbose, f_console_symbol_short_disable, f_console_symbol_long_disable, " Increase verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_debug, f_console_standard_long_debug, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Enable debugging, inceasing verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number.");
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_at, fss_embedded_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(output, context, fss_embedded_list_read_short_content, fss_embedded_list_read_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the content (default).");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_delimit, fss_embedded_list_read_long_delimit, f_console_symbol_short_enable, f_console_symbol_long_enable, " Designate how to handle applying delimits.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_depth, fss_embedded_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(output, context, fss_embedded_list_read_short_empty, fss_embedded_list_read_long_empty, f_console_symbol_short_enable, f_console_symbol_long_enable, "   Include empty content when processing.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_line, fss_embedded_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(output, context, fss_embedded_list_read_short_name, fss_embedded_list_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Select object with this name.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_object, fss_embedded_list_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, "  Print the object.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_pipe, fss_embedded_list_read_long_pipe, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Print using the special pipe format.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_select, fss_embedded_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(output, context, fss_embedded_list_read_short_total, fss_embedded_list_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, "   Print the total number of lines.");
+    fll_program_print_help_option(output, context, fss_embedded_list_read_short_trim, fss_embedded_list_read_long_trim, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Trim object names on select or print.");
+
+    fll_program_print_help_usage(output, context, fss_embedded_list_read_name, "filename(s)");
+
+    fl_color_print(output.stream, context.set.important, " Notes:");
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  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[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  When using the ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+    fprintf(output.stream, " option, an order of operations is enforced on the parameters.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  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[0]);
+
+    fprintf(output.stream, "    ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+    fprintf(output.stream, ": An object index at the specified depth.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "    ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+    fprintf(output.stream, ": A new depth within the specified depth, indexed from the root.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "    ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+    fprintf(output.stream, ": An object name at the specified depth.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The parameter ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+    fprintf(output.stream, " must be in numeric order, but values in between may be skipped.%c", f_string_eol[0]);
+    fprintf(output.stream, "    ('-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[0]);
+    fprintf(output.stream, "    ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The parameter ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+    fprintf(output.stream, " selects a content index at a given depth.%c", f_string_eol[0]);
+    fprintf(output.stream, "    (This parameter is not synonymous with the depth parameter and does not relate to nested content).%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  Specify both ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+    fprintf(output.stream, " and the ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+    fprintf(output.stream, " parameters to get the total objects.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  When both ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+    fprintf(output.stream, " and ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+    fprintf(output.stream, " parameters are specified (at the same depth), the ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+    fprintf(output.stream, " parameter value will be treated as a position relative to the specified ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+    fprintf(output.stream, " parameter value.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  This program may support parameters, such as ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+    fprintf(output.stream, " or ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+    fprintf(output.stream, ", even if not supported by the standard.%c", f_string_eol[0]);
+    fprintf(output.stream, "  This is done to help ensure consistency for scripting.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  For parameters like ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+    fprintf(output.stream, ", if the standard doesn't support nested content, then only a depth of 0 would be valid.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  For parameters like ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+    fprintf(output.stream, ", if the standard doesn't support multiple content groups, then only a select of 0 would be valid.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The parameter ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_trim);
+    fprintf(output.stream, " will remove leading and trailing whitespaces when selecting objects or when printing objects.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  When specifying both the ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+    fprintf(output.stream, " parameter and the ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_content);
+    fprintf(output.stream, " parameter, the entire object and content are printed, including the formatting.%c", f_string_eol[0]);
+    fprintf(output.stream, "  Both the object and content printed are already escaped.%c", f_string_eol[0]);
+    fprintf(output.stream, "  Both the object and content are separated by an EOL.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The parameter ");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+    fprintf(output.stream, " accepts the following:%c", f_string_eol[0]);
+    fprintf(output.stream, "  - ");
+    fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_none);
+    fprintf(output.stream, ": Do not apply delimits.%c", f_string_eol[0]);
+    fprintf(output.stream, "  - ");
+    fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_all);
+    fprintf(output.stream, ": (default) apply all delimits.%c", f_string_eol[0]);
+    fprintf(output.stream, "  - a number, 0 or greater: apply delimits for the specified depth.%c", f_string_eol[0]);
+    fprintf(output.stream, "  - a number, 0 or greater, followed by a ");
+    fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_greater);
+    fprintf(output.stream, ": (such as '1+') apply delimits for the specified depth and any greater depth (numerically).%c", f_string_eol[0]);
+    fprintf(output.stream, "  - a number, 0 or greater, followed by a ");
+    fl_color_print(output.stream, context.set.notable, "%s", fss_embedded_list_read_delimit_mode_name_lesser);
+    fprintf(output.stream, ": (such as '1-') apply delimits for the specified depth and any lesser depth (numerically).%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_read_print_help_
+
+#ifndef _di_fss_embedded_list_read_main_
+  f_return_status fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data) {
+    f_status_t status = F_none;
+
+    {
+      const f_console_parameters_t parameters = f_macro_console_parameters_t_initialize(data->parameters, fss_embedded_list_read_total_parameters);
+
+      {
+        f_console_parameter_id_t ids[3] = { fss_embedded_list_read_parameter_no_color, fss_embedded_list_read_parameter_light, fss_embedded_list_read_parameter_dark };
+        const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 3);
+
+        status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+        data->error.context = data->context.set.error;
+        data->error.notable = data->context.set.notable;
+
+        if (F_status_is_error(status)) {
+          fss_embedded_list_read_delete_data(data);
+          return F_status_set_error(status);
+        }
+      }
+
+      // Identify priority of verbosity related parameters.
+      {
+        f_console_parameter_id_t ids[4] = { fss_embedded_list_read_parameter_verbosity_quiet, fss_embedded_list_read_parameter_verbosity_normal, fss_embedded_list_read_parameter_verbosity_verbose, fss_embedded_list_read_parameter_verbosity_debug };
+        f_console_parameter_id_t choice = 0;
+        const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 4);
+
+        status = f_console_parameter_prioritize_right(parameters, choices, &choice);
+
+        if (F_status_is_error(status)) {
+          fss_embedded_list_read_delete_data(data);
+          return status;
+        }
+
+        if (choice == fss_embedded_list_read_parameter_verbosity_quiet) {
+          data->error.verbosity = f_console_verbosity_quiet;
+        }
+        else if (choice == fss_embedded_list_read_parameter_verbosity_normal) {
+          data->error.verbosity = f_console_verbosity_normal;
+        }
+        else if (choice == fss_embedded_list_read_parameter_verbosity_verbose) {
+          data->error.verbosity = f_console_verbosity_verbose;
+        }
+        else if (choice == fss_embedded_list_read_parameter_verbosity_debug) {
+          data->error.verbosity = f_console_verbosity_debug;
+        }
+      }
+
+      status = F_none;
+    }
+
+    if (data->parameters[fss_embedded_list_read_parameter_help].result == f_console_result_found) {
+      fss_embedded_list_read_print_help(data->output, data->context);
+
+      fss_embedded_list_read_delete_data(data);
+      return F_none;
+    }
+
+    if (data->parameters[fss_embedded_list_read_parameter_version].result == f_console_result_found) {
+      fll_program_print_version(data->output, fss_embedded_list_read_version);
+
+      fss_embedded_list_read_delete_data(data);
+      return F_none;
+    }
+
+    if (data->remaining.used > 0 || data->process_pipe) {
+      if (data->parameters[fss_embedded_list_read_parameter_at].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_at);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_name].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_name);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' requires a string.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' requires a positive number.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (data->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found) {
+        if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+
+        if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_additional) {
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+
+        if (data->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+          if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify both the '", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_object);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' and the '");
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_content);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+            status = F_status_set_error(F_parameter);
+          }
+        }
+      }
+
+      if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+        if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_line);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+      }
+
+      if (data->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+        if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sCannot specify the '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_pipe);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_total);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+      }
+
+      if (F_status_is_error_not(status)) {
+        if (data->parameters[fss_embedded_list_read_parameter_delimit].result == f_console_result_found) {
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' requires a value.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+        else if (data->parameters[fss_embedded_list_read_parameter_delimit].result == f_console_result_additional) {
+          const f_string_length_t location = data->parameters[fss_embedded_list_read_parameter_delimit].values.array[0];
+          f_string_length_t length = strnlen(arguments.argv[location], f_console_length_size);
+
+          if (length == 0) {
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_delimit);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' must not be empty.%c", f_string_eol[0]);
+
+            status = F_status_set_error(F_parameter);
+          }
+          else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_none, length, fss_embedded_list_read_delimit_mode_name_none_length) == F_equal_to) {
+            data->delimit_mode = fss_embedded_list_read_delimit_mode_none;
+          }
+          else if (fl_string_compare(arguments.argv[location], fss_embedded_list_read_delimit_mode_name_all, length, fss_embedded_list_read_delimit_mode_name_all_length) == F_equal_to) {
+            data->delimit_mode = fss_embedded_list_read_delimit_mode_all;
+          }
+          else {
+            data->delimit_mode = fss_embedded_list_read_delimit_mode_depth;
+
+            if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_greater[0]) {
+              data->delimit_mode = fss_embedded_list_read_delimit_mode_depth_greater;
+
+              // shorten the length to better convert the remainder to a number.
+              length--;
+            }
+            else if (arguments.argv[location][length - 1] == fss_embedded_list_read_delimit_mode_name_lesser[0]) {
+              data->delimit_mode = fss_embedded_list_read_delimit_mode_depth_lesser;
+
+              // shorten the length to better convert the remainder to a number.
+              length--;
+            }
+
+            f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+            // ignore leading plus sign.
+            if (arguments.argv[location][0] == '+') {
+              range.start++;
+            }
+
+            status = fl_conversion_string_to_number_unsigned(arguments.argv[location], &data->delimit_depth, range);
+
+            if (F_status_is_error(status)) {
+              fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_delimit, arguments.argv[location]);
+            }
+          }
+        }
+      }
+
+      fss_embedded_list_read_depths_t depths = fss_embedded_list_read_depths_t_initialize;
+
+      f_fss_delimits_t objects_delimits = f_fss_delimits_t_initialize;
+      f_fss_delimits_t contents_delimits = f_fss_delimits_t_initialize;
+      f_fss_comments_t comments = f_fss_comments_t_initialize;
+
+      f_string_length_t original_size = data->quantity.total;
+
+      if (F_status_is_error_not(status)) {
+        status = fss_embedded_list_read_main_preprocess_depth(arguments, *data, &depths);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true);
+        }
+      }
+
+      if (F_status_is_error_not(status) && data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_found) {
+        fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+        fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_select);
+        fl_color_print(data->error.to.stream, data->context.set.error, "' parameter requires a positive number.%c", f_string_eol[0]);
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->process_pipe) {
+        f_file_t file = f_file_t_initialize;
+
+        file.id = f_type_descriptor_input;
+
+        status = f_file_read(file, &data->buffer);
+
+        if (F_status_is_error(status)) {
+          fll_error_file_print(data->error, F_status_set_fine(status), "f_file_read", F_true, "-", "read", fll_error_file_type_pipe);
+        }
+        else {
+          status = fss_embedded_list_read_main_process_file(arguments, data, "-", depths, &objects_delimits, &contents_delimits, &comments);
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, "-", "read", fll_error_file_type_pipe);
+          }
+        }
+
+        // Clear buffers before continuing.
+        f_macro_fss_nest_t_delete_simple(data->nest);
+        f_macro_string_dynamic_t_delete_simple(data->buffer);
+      }
+
+      if (F_status_is_error_not(status) && data->remaining.used > 0) {
+        for (f_array_length_t i = 0; i < data->remaining.used; i++) {
+          f_file_t file = f_file_t_initialize;
+
+          status = f_file_open(arguments.argv[data->remaining.array[i]], 0, &file);
+
+          data->quantity.total = original_size;
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "f_file_open", F_true, arguments.argv[data->remaining.array[i]], "open", fll_error_file_type_file);
+            break;
+          }
+
+          if (!data->quantity.total) {
+            status = f_file_size_by_id(file.id, &data->quantity.total);
+            if (F_status_is_error(status)) {
+              fll_error_file_print(data->error, F_status_set_fine(status), "f_file_size_by_id", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+
+              f_file_stream_close(F_true, &file);
+              break;
+            }
+
+            // Skip past empty files.
+            if (!data->quantity.total) {
+              if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+                fprintf(data->output.stream, "0%c", f_string_eol[0]);
+              }
+
+              f_file_stream_close(F_true, &file);
+              continue;
+            }
+          }
+
+          status = f_file_read_until(file, data->quantity.total, &data->buffer);
+
+          f_file_stream_close(F_true, &file);
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "f_file_read_until", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+            break;
+          }
+
+          status = fss_embedded_list_read_main_process_file(arguments, data, arguments.argv[data->remaining.array[i]], depths, &objects_delimits, &contents_delimits, &comments);
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "fss_embedded_list_read_main_process_file", F_true, arguments.argv[data->remaining.array[i]], "read", fll_error_file_type_file);
+            break;
+          }
+
+          // Clear buffers before repeating the loop.
+          f_macro_fss_nest_t_delete_simple(data->nest);
+          f_macro_string_dynamic_t_delete_simple(data->buffer);
+        } // for
+
+        if (F_status_is_error(status)) {
+          f_macro_fss_nest_t_delete_simple(data->nest);
+          f_macro_string_dynamic_t_delete_simple(data->buffer);
+        }
+      }
+
+      macro_fss_embedded_list_read_depths_t_delete_simple(depths);
+      f_macro_fss_delimits_t_delete_simple(objects_delimits);
+      f_macro_fss_delimits_t_delete_simple(contents_delimits);
+      f_macro_fss_comments_t_delete_simple(comments);
+    }
+    else {
+      fl_color_print(data->error.to.stream, data->context.set.error, "%sYou failed to specify one or more files.%c", fll_error_print_error, f_string_eol[0]);
+      status = F_status_set_error(F_parameter);
+    }
+
+    fss_embedded_list_read_delete_data(data);
+    return status;
+  }
+#endif // _di_fss_embedded_list_read_main_
+
+#ifndef _di_fss_embedded_list_read_delete_data_
+  f_return_status fss_embedded_list_read_delete_data(fss_embedded_list_read_data_t *data) {
+
+    for (f_string_length_t i = 0; i < fss_embedded_list_read_total_parameters; i++) {
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].locations);
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub);
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].values);
+    } // for
+
+    f_macro_fss_nest_t_delete_simple(data->nest);
+
+    f_macro_string_dynamic_t_delete_simple(data->buffer);
+    f_macro_string_lengths_t_delete_simple(data->remaining);
+
+    f_macro_color_context_t_delete_simple(data->context);
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h
new file mode 100644 (file)
index 0000000..255c83d
--- /dev/null
@@ -0,0 +1,263 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the FSS Basic List Read program
+ * This program utilizes the Featureless Linux Library.
+ * This program processes files or other input in fss format and stores the results in the fss_embedded_list_read_data_t.
+ *
+ * This processes in accordance to the FSS-0008 Embedded List specification.
+ */
+#ifndef _fss_embedded_list_read_h
+
+// libc includes
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/console.h>
+#include <level_0/directory.h>
+#include <level_0/file.h>
+#include <level_0/pipe.h>
+#include <level_0/print.h>
+
+// fll-1 includes
+#include <level_1/color.h>
+#include <level_1/console.h>
+#include <level_1/conversion.h>
+#include <level_1/print.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/error.h>
+#include <level_2/execute.h>
+#include <level_2/file.h>
+#include <level_2/fss_embedded_list.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_version_
+  #define fss_embedded_list_read_major_version "0"
+  #define fss_embedded_list_read_minor_version "5"
+  #define fss_embedded_list_read_micro_version "2"
+  #define fss_embedded_list_read_version fss_embedded_list_read_major_version "." fss_embedded_list_read_minor_version "." fss_embedded_list_read_micro_version
+#endif // _di_fss_embedded_list_read_version_
+
+#ifndef _di_fss_embedded_list_read_name_
+  #define fss_embedded_list_read_name      "fss_embedded_list_read"
+  #define fss_embedded_list_read_name_long "FSS Embedded List Read"
+#endif // _di_fss_embedded_list_read_name_
+
+#ifndef _di_fss_embedded_list_read_defines_
+  #define fss_embedded_list_read_pipe_content_end    '\f'
+  #define fss_embedded_list_read_pipe_content_ignore '\v'
+  #define fss_embedded_list_read_pipe_content_start  '\b'
+
+  #define fss_embedded_list_read_short_at      "a"
+  #define fss_embedded_list_read_short_content "c"
+  #define fss_embedded_list_read_short_delimit "D"
+  #define fss_embedded_list_read_short_depth   "d"
+  #define fss_embedded_list_read_short_empty   "e"
+  #define fss_embedded_list_read_short_line    "l"
+  #define fss_embedded_list_read_short_name    "n"
+  #define fss_embedded_list_read_short_object  "o"
+  #define fss_embedded_list_read_short_pipe    "p"
+  #define fss_embedded_list_read_short_select  "s"
+  #define fss_embedded_list_read_short_total   "t"
+  #define fss_embedded_list_read_short_trim    "T"
+
+  #define fss_embedded_list_read_long_at      "at"
+  #define fss_embedded_list_read_long_content "content"
+  #define fss_embedded_list_read_long_delimit "delimit"
+  #define fss_embedded_list_read_long_depth   "depth"
+  #define fss_embedded_list_read_long_empty   "empty"
+  #define fss_embedded_list_read_long_line    "line"
+  #define fss_embedded_list_read_long_name    "name"
+  #define fss_embedded_list_read_long_object  "object"
+  #define fss_embedded_list_read_long_pipe    "pipe"
+  #define fss_embedded_list_read_long_select  "select"
+  #define fss_embedded_list_read_long_total   "total"
+  #define fss_embedded_list_read_long_trim    "trim"
+
+  enum {
+    fss_embedded_list_read_parameter_help,
+    fss_embedded_list_read_parameter_light,
+    fss_embedded_list_read_parameter_dark,
+    fss_embedded_list_read_parameter_no_color,
+    fss_embedded_list_read_parameter_verbosity_quiet,
+    fss_embedded_list_read_parameter_verbosity_normal,
+    fss_embedded_list_read_parameter_verbosity_verbose,
+    fss_embedded_list_read_parameter_verbosity_debug,
+    fss_embedded_list_read_parameter_version,
+
+    fss_embedded_list_read_parameter_at,
+    fss_embedded_list_read_parameter_content,
+    fss_embedded_list_read_parameter_delimit,
+    fss_embedded_list_read_parameter_depth,
+    fss_embedded_list_read_parameter_empty,
+    fss_embedded_list_read_parameter_line,
+    fss_embedded_list_read_parameter_name,
+    fss_embedded_list_read_parameter_object,
+    fss_embedded_list_read_parameter_pipe,
+    fss_embedded_list_read_parameter_select,
+    fss_embedded_list_read_parameter_total,
+    fss_embedded_list_read_parameter_trim,
+  };
+
+  #define fss_embedded_list_read_console_parameter_t_initialize \
+    { \
+      f_console_parameter_t_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_normal, f_console_standard_long_normal, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_debug, f_console_standard_long_debug, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_at, fss_embedded_list_read_long_at, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_content, fss_embedded_list_read_long_content, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_delimit, fss_embedded_list_read_long_delimit, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_depth, fss_embedded_list_read_long_depth, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_empty, fss_embedded_list_read_long_empty, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_line, fss_embedded_list_read_long_line, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_name, fss_embedded_list_read_long_name, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_object, fss_embedded_list_read_long_object, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_pipe, fss_embedded_list_read_long_pipe, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_select, fss_embedded_list_read_long_select, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_total, fss_embedded_list_read_long_total, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_read_short_trim, fss_embedded_list_read_long_trim, 0, 0, f_console_type_normal), \
+    }
+
+  #define fss_embedded_list_read_total_parameters 21
+#endif // _di_fss_embedded_list_read_defines_
+
+#ifndef _di_fss_embedded_list_read_delimit_mode_
+  #define fss_embedded_list_read_delimit_mode_name_none    "none"
+  #define fss_embedded_list_read_delimit_mode_name_all     "all"
+  #define fss_embedded_list_read_delimit_mode_name_greater "+"
+  #define fss_embedded_list_read_delimit_mode_name_lesser  "-"
+
+  #define fss_embedded_list_read_delimit_mode_name_none_length    4
+  #define fss_embedded_list_read_delimit_mode_name_all_length     3
+  #define fss_embedded_list_read_delimit_mode_name_greater_length 1
+  #define fss_embedded_list_read_delimit_mode_name_lesser_length  1
+
+  enum {
+    fss_embedded_list_read_delimit_mode_none = 1,
+    fss_embedded_list_read_delimit_mode_all,
+    fss_embedded_list_read_delimit_mode_depth,
+    fss_embedded_list_read_delimit_mode_depth_greater,
+    fss_embedded_list_read_delimit_mode_depth_lesser,
+  };
+#endif // _di_fss_embedded_list_read_delimit_modes_
+
+#ifndef _di_fss_embedded_list_read_data_t_
+  typedef struct {
+    f_console_parameter_t parameters[fss_embedded_list_read_total_parameters];
+
+    f_string_lengths_t remaining;
+    bool process_pipe;
+
+    f_file_t output;
+    fll_error_print_t error;
+
+    f_string_dynamic_t buffer;
+    f_fss_nest_t nest;
+    f_string_quantity_t quantity;
+
+    uint8_t delimit_mode;
+    f_string_length_t delimit_depth;
+
+    f_color_context_t context;
+  } fss_embedded_list_read_data_t;
+
+  #define fss_embedded_list_read_data_t_initialize \
+    { \
+      fss_embedded_list_read_console_parameter_t_initialize, \
+      f_string_lengths_t_initialize, \
+      F_false, \
+      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      fll_error_print_t_initialize, \
+      f_string_dynamic_t_initialize, \
+      f_fss_nest_t_initialize, \
+      f_string_quantity_t_initialize, \
+      fss_embedded_list_read_delimit_mode_all, \
+      0, \
+      f_color_context_t_initialize, \
+    }
+#endif // _di_fss_embedded_list_read_data_t_
+
+/**
+ * Print help.
+ *
+ * @param output
+ *   The file to print to.
+ * @param context
+ *   The color context settings.
+ *
+ * @return
+ *   F_none on success.
+ */
+#ifndef _di_fss_embedded_list_read_print_help_
+  extern f_return_status fss_embedded_list_read_print_help(const f_file_t output, const f_color_context_t context);
+#endif // _di_fss_embedded_list_read_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call fss_embedded_list_read_delete_data() after executing this.
+ *
+ * @param arguments
+ *   The parameters passed to the process.
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_delete_data()
+ */
+#ifndef _di_fss_embedded_list_read_main_
+  extern f_return_status fss_embedded_list_read_main(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data);
+#endif // _di_fss_embedded_list_read_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing fss_embedded_list_read_main().
+ *
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_main()
+ */
+#ifndef _di_fss_embedded_list_read_delete_data_
+  extern f_return_status fss_embedded_list_read_delete_data(fss_embedded_list_read_data_t *data);
+#endif // _di_fss_embedded_list_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _fss_embedded_list_read_h
diff --git a/level_3/fss_embedded_list_read/c/main.c b/level_3/fss_embedded_list_read/c/main.c
new file mode 100644 (file)
index 0000000..904d21f
--- /dev/null
@@ -0,0 +1,16 @@
+#include "fss_embedded_list_read.h"
+
+int main(const unsigned long argc, const f_string_t *argv) {
+  const f_console_arguments_t arguments = { argc, argv };
+  fss_embedded_list_read_data_t data = fss_embedded_list_read_data_t_initialize;
+
+  if (f_pipe_input_exists()) {
+    data.process_pipe = F_true;
+  }
+
+  if (F_status_is_error(fss_embedded_list_read_main(arguments, &data))) {
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.c
new file mode 100644 (file)
index 0000000..d9539ca
--- /dev/null
@@ -0,0 +1,894 @@
+#include "fss_embedded_list_read.h"
+#include "private-fss_embedded_list_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_read_main_preprocess_depth_
+  f_return_status fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_data_t data, fss_embedded_list_read_depths_t *depths) {
+    f_status_t status = F_none;
+
+    const f_array_length_t values_total = data.parameters[fss_embedded_list_read_parameter_depth].values.used + data.parameters[fss_embedded_list_read_parameter_at].values.used + data.parameters[fss_embedded_list_read_parameter_name].values.used;
+
+    f_array_length_t values_order[values_total];
+    f_array_length_t values_type[values_total];
+
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+
+    // determine the linear order in which all of the three parameter values are to be applied.
+    if (values_total) {
+      memset(values_order, 0, values_total);
+
+      f_array_length_t k = 0;
+      f_array_length_t l = 0;
+
+      for (; j < data.parameters[fss_embedded_list_read_parameter_depth].values.used; ++j) {
+
+        values_order[i] = data.parameters[fss_embedded_list_read_parameter_depth].values.array[j];
+        values_type[i++] = fss_embedded_list_read_parameter_depth;
+      } // for
+
+      if (i) {
+        for (j = 0; j < data.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) {
+
+          for (k = 0; k < i; ++k) {
+
+            if (values_order[k] > data.parameters[fss_embedded_list_read_parameter_at].values.array[j]) {
+              for (l = i; l > k; --l) {
+                values_order[l] = values_order[l - 1];
+                values_type[l] = values_type[l - 1];
+              } // for
+
+              values_order[k] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+              values_type[k] = fss_embedded_list_read_parameter_at;
+              i++;
+              break;
+            }
+          } // for
+
+          if (k == i) {
+            values_order[i] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+            values_type[i++] = fss_embedded_list_read_parameter_at;
+          }
+        } // for
+      }
+      else {
+        for (; j < data.parameters[fss_embedded_list_read_parameter_at].values.used; ++j) {
+
+          values_order[i] = data.parameters[fss_embedded_list_read_parameter_at].values.array[j];
+          values_type[i++] = fss_embedded_list_read_parameter_at;
+        } // for
+      }
+
+      if (i) {
+        for (j = 0; j < data.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) {
+
+          for (k = 0; k < i; ++k) {
+
+            if (values_order[k] > data.parameters[fss_embedded_list_read_parameter_name].values.array[j]) {
+              for (l = i; l > k; --l) {
+                values_order[l] = values_order[l - 1];
+                values_type[l] = values_type[l - 1];
+              } // for
+
+              values_order[k] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+              values_type[k] = fss_embedded_list_read_parameter_name;
+              i++;
+              break;
+            }
+          } // for
+
+          if (k == i) {
+            values_order[i] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+            values_type[i++] = fss_embedded_list_read_parameter_name;
+          }
+        } // for
+      }
+      else {
+        for (; j < data.parameters[fss_embedded_list_read_parameter_name].values.used; ++j) {
+
+          values_order[i] = data.parameters[fss_embedded_list_read_parameter_name].values.array[j];
+          values_type[i++] = fss_embedded_list_read_parameter_name;
+        } // for
+      }
+    }
+
+    {
+      i = 1;
+
+      if (data.parameters[fss_embedded_list_read_parameter_depth].result == f_console_result_additional) {
+        i = data.parameters[fss_embedded_list_read_parameter_depth].values.used + 1;
+      }
+
+      macro_fss_embedded_list_read_depths_t_new(status, (*depths), i);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fss_embedded_list_read_main_preprocess_depth", F_true);
+        return status;
+      }
+    }
+
+    // provide default level-0 depth values.
+    depths->array[0].depth = 0;
+    depths->array[0].index_at = 0;
+    depths->array[0].index_name = 0;
+    depths->array[0].value_at = 0;
+
+    {
+      f_number_unsigned_t number = 0;
+      bool first_depth = F_true;
+
+      for (i = 0; i < values_total; ++i) {
+
+        if (values_type[i] == fss_embedded_list_read_parameter_depth || values_type[i] == fss_embedded_list_read_parameter_at) {
+          const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[values_order[i]]));
+
+          status = fl_conversion_string_to_number_unsigned(arguments.argv[values_order[i]], &number, range);
+
+          if (F_status_is_error(status)) {
+            fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_depth, arguments.argv[values_order[i]]);
+            return status;
+          }
+        }
+
+        if (values_type[i] == fss_embedded_list_read_parameter_depth) {
+
+          if (first_depth) {
+            if (i && number) {
+              depths->array[++depths->used].index_at = 0;
+              depths->array[depths->used].index_name = 0;
+              depths->array[depths->used].value_at = 0;
+            }
+
+            first_depth = F_false;
+            depths->array[depths->used].depth = number;
+          }
+          else {
+            depths->array[++depths->used].depth = number;
+            depths->array[depths->used].index_at = 0;
+            depths->array[depths->used].index_name = 0;
+            depths->array[depths->used].value_at = 0;
+          }
+        }
+        else if (values_type[i] == fss_embedded_list_read_parameter_at) {
+          depths->array[depths->used].index_at = values_order[i];
+          depths->array[depths->used].value_at = number;
+        }
+        else if (values_type[i] == fss_embedded_list_read_parameter_name) {
+          depths->array[depths->used].index_name = values_order[i];
+          depths->array[depths->used].value_name.used = 0;
+
+          if (data.parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+            status = fl_string_rip(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_length_size), &depths->array[depths->used].value_name);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(data.error, F_status_set_fine(status), "fl_string_rip", F_true);
+              return status;
+            }
+          }
+          else {
+            status = fl_string_append(arguments.argv[values_order[i]], strnlen(arguments.argv[values_order[i]], f_console_length_size), &depths->array[depths->used].value_name);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+              return status;
+            }
+          }
+        }
+      } // for
+
+      depths->used++;
+    }
+
+    for (i = 0; i < depths->used; i++) {
+
+      for (j = i + 1; j < depths->used; j++) {
+
+        if (depths->array[i].depth == depths->array[j].depth) {
+          fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data.error.to.stream, data.context.set.error, "%sThe value '", fll_error_print_error);
+          fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[i].depth);
+          fl_color_print(data.error.to.stream, data.context.set.error, "' may only be specified once for the parameter '");
+          fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+          fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]);
+
+          return F_status_set_error(F_parameter);
+        }
+        else if (depths->array[i].depth > depths->array[j].depth) {
+          fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error);
+          fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_read_long_depth);
+          fl_color_print(data.error.to.stream, data.context.set.error, "' may not have the value '");
+          fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[i].depth);
+          fl_color_print(data.error.to.stream, data.context.set.error, "' before the value '");
+          fl_color_print(data.error.to.stream, data.context.set.notable, "%llu", depths->array[j].depth);
+          fl_color_print(data.error.to.stream, data.context.set.error, "'.%c", f_string_eol[0]);
+
+          return F_status_set_error(F_parameter);
+        }
+      } // for
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_read_main_preprocess_depth_
+
+#ifndef _di_fss_embedded_list_read_main_process_file_
+  f_return_status fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data, const f_string_t filename, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) {
+    f_status_t status = F_none;
+
+    {
+      f_string_range_t input = f_macro_string_range_t_initialize(data->buffer.used);
+
+      objects_delimits->used = 0;
+      contents_delimits->used = 0;
+      comments->used = 0;
+
+      status = fll_fss_embedded_list_read(&data->buffer, &input, &data->nest, objects_delimits, contents_delimits, comments);
+
+      if (F_status_is_error(status)) {
+        // @todo: detect and replace fll_error_file_type_file with fll_error_file_type_pipe as appropriate.
+        fll_error_file_print(data->error, F_status_set_fine(status), "fll_fss_embedded_list_read", F_true, filename, "process", fll_error_file_type_file);
+      }
+      else if (status == F_data_not_stop || status == F_data_not_eos) {
+        f_macro_fss_nest_t_delete_simple(data->nest);
+        f_macro_string_dynamic_t_delete_simple(data->buffer);
+
+        if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+          fprintf(data->output.stream, "0%c", f_string_eol[0]);
+          return F_none;
+        }
+
+        return F_status_set_warning(status);
+      }
+
+      if (F_status_is_error(status)) {
+        f_macro_fss_nest_t_delete_simple(data->nest);
+        f_macro_string_dynamic_t_delete_simple(data->buffer);
+
+        return status;
+      }
+
+      f_array_length_t i = 0;
+      f_array_length_t j = 0;
+
+      // comments are not to be part of the file, so remove them.
+      for (; i < comments->used; ++i) {
+        for (j = comments->array[i].start; j <= comments->array[i].stop; ++j) {
+          data->buffer.string[j] = f_fss_delimit_placeholder;
+        } // for
+      } // for
+    }
+
+    // Requested depths cannot be greater than contents depth.
+    if (depths.used > data->nest.used) {
+      if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+        fprintf(data->output.stream, "0%c", f_string_eol[0]);
+        return F_none;
+      }
+
+      return F_none;
+    }
+
+    {
+      f_number_unsigned_t select = 0;
+
+      if (data->parameters[fss_embedded_list_read_parameter_select].result == f_console_result_additional) {
+        const f_string_length_t index = data->parameters[fss_embedded_list_read_parameter_select].values.array[data->parameters[fss_embedded_list_read_parameter_select].values.used - 1];
+        const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[index]));
+
+        status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &select, range);
+
+        if (F_status_is_error(status)) {
+          fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_select, arguments.argv[index]);
+          return status;
+        }
+
+        // This standard does not support multiple content groups.
+        if (select > 0) {
+          return F_none;
+        }
+      }
+    }
+
+    f_array_length_t line = 0;
+
+    if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+      const f_array_length_t index = data->parameters[fss_embedded_list_read_parameter_line].values.array[data->parameters[fss_embedded_list_read_parameter_line].values.used - 1];
+      const f_string_range_t range = f_macro_string_range_t_initialize(strlen(arguments.argv[index]));
+
+      status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &line, range);
+
+      if (F_status_is_error(status)) {
+        fll_error_parameter_integer_print(data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_read_long_line, arguments.argv[index]);
+        return status;
+      }
+    }
+
+    fss_embedded_list_read_process_delimits(*data, objects_delimits, contents_delimits);
+
+    const fss_embedded_list_read_skip_t parents = fss_embedded_list_read_skip_t_initialize;
+
+    return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, 0, line, parents, data, objects_delimits, contents_delimits);
+  }
+#endif // _di_fss_embedded_list_read_main_process_file_
+
+#ifndef _di_fss_embedded_list_read_main_process_for_depth_
+  f_return_status fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_data_t *data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) {
+
+    f_fss_items_t *items = &data->nest.depth[depths.array[depths_index].depth];
+
+    bool skip[items->used];
+
+    // setup defaults to be not skipped unless any given parent is skipped.
+    memset(skip, F_false, sizeof(skip) * items->used);
+
+    if (parents.used) {
+      for (f_array_length_t i = 0; i < items->used; ++i) {
+
+        if (items->array[i].parent >= parents.used || parents.skip[items->array[i].parent]) {
+          skip[i] = F_true;
+        }
+      } // for
+    }
+
+    if (depths.array[depths_index].index_name || depths.array[depths_index].index_at) {
+      const f_string_lengths_t except_none = f_string_lengths_t_initialize;
+
+      f_array_length_t i = 0;
+      f_array_length_t j = 0;
+
+      if (!depths.array[depths_index].index_name || (depths.array[depths_index].index_at && depths.array[depths_index].index_at < depths.array[depths_index].index_name)) {
+
+        // all other non-"at" parameters must be FALSE.
+        for (; i < items->used; ++i) {
+
+          if (skip[i]) continue;
+
+          if (j != depths.array[depths_index].value_at) {
+            skip[i] = F_true;
+          }
+
+          ++j;
+        } // for
+
+        if (depths.array[depths_index].value_at < items->used && !skip[depths.array[depths_index].value_at]) {
+          if (depths.array[depths_index].index_name) {
+
+            if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+
+              if (fl_string_dynamic_partial_compare_except_trim_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[depths.array[depths_index].value_at].object, except_none, *objects_delimits) != F_equal_to) {
+                skip[depths.array[depths_index].value_at] = F_true;
+              }
+            }
+            else {
+              if (fl_string_dynamic_partial_compare_except_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[depths.array[depths_index].value_at].object, except_none, *objects_delimits) != F_equal_to) {
+                skip[depths.array[depths_index].value_at] = F_true;
+              }
+            }
+          }
+        }
+      }
+      else {
+
+        if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+
+          for (i = 0; i < items->used; ++i) {
+
+            if (skip[i]) continue;
+
+            if (fl_string_dynamic_partial_compare_except_trim_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[i].object, except_none, *objects_delimits) != F_equal_to) {
+              skip[i] = F_true;
+            }
+          } // for
+        }
+        else {
+
+          for (i = 0; i < items->used; ++i) {
+
+            if (skip[i]) continue;
+
+            if (fl_string_dynamic_partial_compare_except_dynamic(depths.array[depths_index].value_name, data->buffer, items->array[i].object, except_none, *objects_delimits) != F_equal_to) {
+              skip[i] = F_true;
+            }
+          } // for
+        }
+
+        if (depths.array[depths_index].index_at) {
+
+        // all other non-"at" parameters must be FALSE.
+        for (i = 0, j = 0; i < items->used; ++i) {
+
+          if (skip[i]) continue;
+
+          if (j != depths.array[depths_index].value_at) {
+            skip[i] = F_true;
+          }
+
+          ++j;
+        } // for
+        }
+      }
+    }
+
+    // if the current depth is not the final depth, then recurse into the next depth.
+    if (depths_index + 1 < depths.used) {
+      bool skip_next[data->nest.depth[depths.array[depths_index + 1].depth - 1].used];
+
+      fss_embedded_list_read_skip_t parents_next = fss_embedded_list_read_skip_t_initialize;
+
+      if (depths.array[depths_index].depth + 1 == depths.array[depths_index + 1].depth) {
+        parents_next.skip = skip;
+        parents_next.used = items->used;
+      }
+      else {
+        const f_array_length_t parents_depth = depths.array[depths_index + 1].depth - 1;
+        const f_array_length_t depth_next = depths.array[depths_index + 1].depth;
+
+        parents_next.skip = skip_next;
+        parents_next.used = data->nest.depth[parents_depth].used;
+
+        memset(skip_next, F_true, sizeof(skip_next) * parents_next.used);
+
+        f_fss_items_t *items_next = &data->nest.depth[depth_next];
+        f_fss_items_t *items_previous = 0;
+        f_fss_item_t *item_previous = 0;
+
+        f_array_length_t i = 0;
+        f_array_length_t j = 0;
+
+        for (; i < items_next->used; ++i) {
+
+          j = depth_next;
+
+          item_previous = &items_next->array[i];
+          items_previous = &data->nest.depth[--j];
+
+          while (j > depths.array[depths_index].depth) {
+
+            item_previous = &items_previous->array[item_previous->parent];
+            items_previous = &data->nest.depth[--j];
+          } // while
+
+          if (skip[item_previous->parent]) {
+            skip_next[items_next->array[i].parent] = F_true;
+          }
+          else {
+            skip_next[items_next->array[i].parent] = F_false;
+          }
+        } // for
+      }
+
+      return fss_embedded_list_read_main_process_for_depth(arguments, filename, depths, depths_index + 1, line, parents_next, data, objects_delimits, contents_delimits);
+    }
+
+    // process objects.
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+
+    if (data->parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found) {
+      if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+        f_array_length_t total = 0;
+
+        for (i = 0; i < items->used; i++) {
+          if (skip[i]) continue;
+
+          total++;
+        } // for
+
+        fprintf(data->output.stream, "%llu%c", total, f_string_eol[0]);
+
+        return F_none;
+      }
+
+      f_return_status (*print_object)(FILE *, const f_string_static_t, const f_string_range_t, const f_string_lengths_t) = &f_print_except_dynamic_partial;
+
+      if (data->parameters[fss_embedded_list_read_parameter_trim].result == f_console_result_found) {
+        print_object = &fl_print_trim_except_dynamic_partial;
+      }
+
+      for (i = 0; i < items->used; i++) {
+
+        if (skip[i]) continue;
+
+        print_object(data->output.stream, data->buffer, items->array[i].object, *objects_delimits);
+
+        if (data->parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+          fss_embedded_list_read_print_object_end(*data);
+
+          if (items->array[i].content.used) {
+            f_print_except_dynamic_partial(data->output.stream, data->buffer, items->array[i].content.array[0], *contents_delimits);
+          }
+        }
+
+        fss_embedded_list_read_print_set_end(*data);
+      } // for
+
+      return F_none;
+    }
+
+    // process contents.
+    bool include_empty = 0;
+
+    if (data->parameters[fss_embedded_list_read_parameter_empty].result == f_console_result_found) {
+      include_empty = 1;
+    }
+
+    if (data->parameters[fss_embedded_list_read_parameter_total].result == f_console_result_found) {
+      f_array_length_t total = 0;
+
+      for (i = 0; i < items->used; ++i) {
+
+        if (skip[i]) continue;
+
+        if (!items->array[i].content.used) {
+          if (include_empty) {
+            total++;
+          }
+
+          continue;
+        }
+
+        for (j = items->array[i].content.array[0].start; j <= items->array[i].content.array[0].stop; ++j) {
+
+          if (!data->buffer.string[j]) continue;
+
+          if (data->buffer.string[j] == f_string_eol[0]) {
+            total++;
+          }
+        } // for
+      } // for
+
+      fprintf(data->output.stream, "%llu%c", total, f_string_eol[0]);
+      return F_none;
+    }
+
+    if (data->parameters[fss_embedded_list_read_parameter_line].result == f_console_result_additional) {
+      f_array_length_t line_current = 0;
+
+      for (; i < items->used; ++i) {
+
+        if (skip[i]) continue;
+
+        if (!items->array[i].content.used) {
+          if (include_empty) {
+            if (line_current == line) {
+              fss_embedded_list_read_print_set_end(*data);
+              break;
+            }
+
+            line_current++;
+          }
+
+          continue;
+        }
+
+        j = items->array[i].content.array[0].start;
+
+        if (line_current != line) {
+          for (; j <= items->array[i].content.array[0].stop; ++j) {
+
+            if (data->buffer.string[j] == f_string_eol[0]) {
+              line_current++;
+
+              if (line_current == line) {
+                ++j;
+                break;
+              }
+            }
+          } // for
+        }
+
+        if (line_current == line) {
+          if (j > items->array[i].content.array[0].stop) continue;
+
+          for (; j <= items->array[i].content.array[0].stop; ++j) {
+
+            if (!data->buffer.string[j]) continue;
+
+            if (data->buffer.string[j] == f_string_eol[0]) {
+              fprintf(data->output.stream, "%c", f_string_eol[0]);
+              break;
+            }
+
+            fprintf(data->output.stream, "%c", data->buffer.string[j]);
+          } // for
+
+          break;
+        }
+      } // for
+
+      return F_none;
+    }
+
+    for (i = 0; i < items->used; i++) {
+
+      if (skip[i]) continue;
+
+      if (!items->array[i].content.used) {
+        if (include_empty) {
+          fss_embedded_list_read_print_set_end(*data);
+        }
+
+        continue;
+      }
+
+      f_print_except_dynamic_partial(data->output.stream, data->buffer, items->array[i].content.array[0], *contents_delimits);
+
+      if (data->parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+        fprintf(data->output.stream, "%c", fss_embedded_list_read_pipe_content_end);
+      }
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_read_main_process_for_depth_
+
+#ifndef _di_fss_embedded_list_read_print_object_end_
+  void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_data_t data) {
+
+    if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+      fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_start);
+    }
+    else {
+      if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+        fprintf(data.output.stream, "%c%c", f_fss_embedded_list_open, f_fss_embedded_list_open_end);
+      }
+      else {
+        fprintf(data.output.stream, "%c", f_fss_eol);
+      }
+    }
+  }
+#endif // _di_fss_embedded_list_read_print_object_end_
+
+#ifndef _di_fss_embedded_list_read_print_content_end_
+  void fss_embedded_list_read_print_content_end(const fss_embedded_list_read_data_t data) {
+
+    if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+      fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_start);
+    }
+    else {
+      if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+        fprintf(data.output.stream, "%c%c", f_fss_embedded_list_close, f_fss_embedded_list_close_end);
+      }
+      else {
+        fprintf(data.output.stream, "%c", f_fss_eol);
+      }
+    }
+  }
+#endif // _di_fss_embedded_list_read_print_content_end_
+
+#ifndef _di_fss_embedded_list_read_print_content_ignore_
+  void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_data_t data) {
+
+    if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+      fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_ignore);
+    }
+  }
+#endif // _di_fss_embedded_list_read_print_content_ignore_
+
+#ifndef _di_fss_embedded_list_read_print_set_end_
+  void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_data_t data) {
+
+    if (data.parameters[fss_embedded_list_read_parameter_pipe].result == f_console_result_found) {
+      fprintf(data.output.stream, "%c", fss_embedded_list_read_pipe_content_end);
+    }
+    else {
+      if (data.parameters[fss_embedded_list_read_parameter_object].result == f_console_result_found && data.parameters[fss_embedded_list_read_parameter_content].result == f_console_result_found) {
+        fprintf(data.output.stream, "%c%c", f_fss_embedded_list_close, f_fss_embedded_list_close_end);
+      }
+      else {
+        fprintf(data.output.stream, "%c", f_fss_eol);
+      }
+    }
+  }
+#endif // _di_fss_embedded_list_read_print_set_end_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_
+  void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_data_t data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) {
+
+    if (!data.nest.used) return;
+
+    if ((!objects_delimits->used && !contents_delimits->used) || data.delimit_mode == fss_embedded_list_read_delimit_mode_all) return;
+
+    if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser && data.nest.used < data.delimit_depth) return;
+    if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater && data.delimit_depth == 0) return;
+
+    if (data.delimit_mode == fss_embedded_list_read_delimit_mode_none) {
+      objects_delimits->used = 0;
+      contents_delimits->used = 0;
+      return;
+    }
+
+    if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth || data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) {
+      if (data.delimit_depth >= data.nest.used) {
+        objects_delimits->used = 0;
+        contents_delimits->used = 0;
+        return;
+      }
+    }
+
+    const f_string_length_t original_objects_used = objects_delimits->used;
+    const f_string_length_t original_contents_used = contents_delimits->used;
+
+    f_string_length_t original_objects_delimits[original_objects_used];
+    f_string_length_t original_contents_delimits[original_contents_used];
+
+    memcpy(&original_objects_delimits, objects_delimits->array, original_objects_used * sizeof(f_string_length_t));
+    memcpy(&original_contents_delimits, contents_delimits->array, original_contents_used * sizeof(f_string_length_t));
+
+    objects_delimits->used = 0;
+    contents_delimits->used = 0;
+
+    if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth) {
+
+      // only depth 0 objects are stored in objects_delimits.
+      if (data.delimit_depth) {
+        fss_embedded_list_read_process_delimits_objects(data, data.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits);
+      }
+      else {
+        fss_embedded_list_read_process_delimits_objects(data, data.delimit_depth, original_objects_delimits, original_objects_used, objects_delimits);
+      }
+
+      fss_embedded_list_read_process_delimits_contents(data, data.delimit_depth, original_contents_delimits, original_contents_used, contents_delimits);
+    }
+    else {
+
+      if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_lesser) {
+
+        // only depth 0 objects are stored in objects_delimits.
+        fss_embedded_list_read_process_delimits_objects(data, 0, original_objects_delimits, original_objects_used, objects_delimits);
+        fss_embedded_list_read_process_delimits_contents(data, 0, original_contents_delimits, original_contents_used, contents_delimits);
+
+        for (f_array_length_t i = 1; i <= data.delimit_depth && i < data.nest.used; ++i) {
+
+          fss_embedded_list_read_process_delimits_objects(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+          fss_embedded_list_read_process_delimits_contents(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+        } // for
+      }
+      else if (data.delimit_mode == fss_embedded_list_read_delimit_mode_depth_greater) {
+        for (f_array_length_t i = data.delimit_depth; i < data.nest.used; ++i) {
+
+          fss_embedded_list_read_process_delimits_objects(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+          fss_embedded_list_read_process_delimits_contents(data, i, original_contents_delimits, original_contents_used, contents_delimits);
+        } // for
+      }
+    }
+  }
+#endif // _di_fss_embedded_list_read_process_delimits_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_contents_
+  void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) {
+
+    if (!original_used) return;
+
+    f_fss_items_t *items = &data.nest.depth[depth];
+
+    if (!items->used) return;
+
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+    f_array_length_t k = 0;
+    f_array_length_t l = 0;
+    f_array_length_t m = 0;
+
+    for (i = 0; i < items->used; ++i) {
+
+      for (j = 0; j < original_used; ++j) {
+
+        for (k = 0; k < items->array[i].content.used; ++k) {
+
+          if (original_delimits[j] >= items->array[i].content.array[k].start && original_delimits[j] <= items->array[i].content.array[k].stop) {
+
+            // preserve linear order when adding back delimits.
+            if (delimits->used) {
+              for (l = 0; l < delimits->used; ++l) {
+
+                if (original_delimits[j] > delimits->array[l]) continue;
+                if (original_delimits[j] == delimits->array[l]) break;
+
+                for (m = delimits->used; m > l; --m) {
+                  delimits->array[m] = delimits->array[m - 1];
+                } // for
+
+                if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+                  delimits->array[l] = original_delimits[j];
+                  delimits->used++;
+                }
+
+                break;
+              } // for
+            }
+            else if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+              delimits->array[0] = original_delimits[j];
+              delimits->used = 1;
+            }
+          }
+        }
+      } // for
+    } // for
+  }
+#endif // _di_fss_embedded_list_read_process_delimits_contents_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_objects_
+  void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) {
+
+    if (!original_used) return;
+
+    f_fss_items_t *items = &data.nest.depth[depth];
+
+    if (!items->used) return;
+
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+    f_array_length_t k = 0;
+    f_array_length_t l = 0;
+
+    for (i = 0; i < items->used; ++i) {
+
+      for (j = 0; j < original_used; ++j) {
+
+        if (original_delimits[j] >= items->array[i].object.start && original_delimits[j] <= items->array[i].object.stop) {
+
+          // preserve linear order when adding back delimits.
+          if (delimits->used) {
+            for (k = 0; k < delimits->used; ++k) {
+
+              if (original_delimits[j] > delimits->array[k]) continue;
+              if (original_delimits[j] == delimits->array[k]) break;
+
+              for (l = delimits->used; l > k; --l) {
+                delimits->array[l] = delimits->array[l - 1];
+              } // for
+
+              if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+                delimits->array[k] = original_delimits[j];
+                delimits->used++;
+              }
+
+              break;
+            } // for
+          }
+          else if (fss_embedded_list_read_process_delimits_within_greater(data, depth, original_delimits[j]) == F_false) {
+            delimits->array[0] = original_delimits[j];
+            delimits->used = 1;
+          }
+        }
+      } // for
+    } // for
+  }
+#endif // _di_fss_embedded_list_read_process_delimits_objects_
+
+#ifndef _di_fss_embedded_list_read_process_delimits_within_greater_
+  f_return_status fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t location) {
+
+    if (depth + 1 >= data.nest.used) return F_false;
+
+    f_fss_items_t *items = 0;
+
+    f_string_length_t i = 0;
+    f_string_length_t j = 0;
+
+    for (f_string_length_t d = depth + 1; d < data.nest.used; ++d) {
+      items = &data.nest.depth[d];
+
+      for (i = 0; i < items->used; ++i) {
+
+        for (j = 0; j < items->array[i].content.used; ++j) {
+
+          if (location >= items->array[i].content.array[j].start && location <= items->array[i].content.array[j].stop) {
+            return F_true;
+          }
+        } // for
+      } // for
+    } // for
+
+    return F_false;
+  }
+#endif // _di_fss_embedded_list_read_process_delimits_within_greater_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h b/level_3/fss_embedded_list_read/c/private-fss_embedded_list_read.h
new file mode 100644 (file)
index 0000000..b810059
--- /dev/null
@@ -0,0 +1,396 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_fss_embedded_list_read_h
+#define _PRIVATE_fss_embedded_list_read_h
+
+#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.
+ *
+ * index_at:   position of the "--at" parameter value in the argv list, when 0 there is no parameter.
+ * index_name: position of the "--name" parameter value in the argv list, when 0 there is no parameter.
+ *
+ * value_at:   the value of the "--at" parameter, already processed and ready to use, only when index_at > 0.
+ * value_name: the value of the "--name" parameter, already processed and ready to use, only when index_name > 0.
+ */
+#ifndef _di_fss_embedded_list_read_depth_t_
+  typedef struct {
+    f_string_length_t depth;
+
+    f_array_length_t index_at;
+    f_array_length_t index_name;
+
+    f_number_unsigned_t value_at;
+    f_string_dynamic_t  value_name;
+  } fss_embedded_list_read_depth_t;
+
+  #define fss_embedded_list_read_depth_t_initialize \
+    { \
+      0, \
+      0, \
+      0, \
+      0, \
+      f_string_dynamic_t_initialize, \
+    }
+
+  #define macro_fss_embedded_list_read_depth_t_clear(structure) \
+    structure.depth = 0; \
+    structure.index_at = 0; \
+    structure.index_name = 0; \
+    structure.value_at = 0; \
+    f_macro_string_dynamic_t_clear(structure.value_name)
+
+  #define macro_fss_embedded_list_read_depth_t_delete(status, structure)  f_macro_string_dynamic_t_delete(status, structure.value_name)
+  #define macro_fss_embedded_list_read_depth_t_destroy(status, structure) f_macro_string_dynamic_t_destroy(status, structure.value_name)
+
+  #define macro_fss_embedded_list_read_depth_t_delete_simple(structure)  f_macro_string_dynamic_t_delete_simple(structure.value_name)
+  #define macro_fss_embedded_list_read_depth_t_destroy_simple(structure) f_macro_string_dynamic_t_destroy_simple(structure.value_name)
+#endif // _di_fss_embedded_list_read_depth_t_
+
+/**
+ * A structure containing a statically allocated array of booleans and the array length.
+ *
+ * skip: a statically allocated array representing list items that are to be skipped.
+ * used: the length of the statically allocated skip array.
+ */
+#ifndef _di_fss_embedded_list_read_skip_t_
+  typedef struct {
+    bool *skip;
+    f_array_length_t used;
+  } fss_embedded_list_read_skip_t;
+
+  #define fss_embedded_list_read_skip_t_initialize \
+    { \
+      0, \
+      0, \
+    }
+
+  #define macro_fss_embedded_list_read_skip_t_initialize(skip, used) \
+    { \
+      skip, \
+      used, \
+    }
+#endif // _di_fss_embedded_list_read_skip_t_
+
+/**
+ * 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_embedded_list_read_depths_t_
+  typedef struct {
+    fss_embedded_list_read_depth_t *array;
+
+    f_array_length_t size;
+    f_array_length_t used;
+  } fss_embedded_list_read_depths_t;
+
+  #define fss_embedded_list_read_depths_t_initialize { 0, 0, 0 }
+
+  #define macro_fss_embedded_list_read_depths_t_clear(depths) f_macro_memory_structure_t_clear(depths)
+
+  #define macro_fss_embedded_list_read_depths_t_new(status, depths, length) f_macro_memory_structure_t_new(status, depths, fss_embedded_list_read_depth_t, length)
+
+  #define macro_fss_embedded_list_read_depths_t_delete(status, depths) \
+    status = F_none; \
+    depths.used = depths.size; \
+    while (depths.used > 0) { \
+      depths.used--; \
+      macro_fss_embedded_list_read_depth_t_delete(status, depths.array[depths.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) f_macro_memory_structure_t_delete(depths, fss_embedded_list_read_depth_t)
+
+  #define macro_fss_embedded_list_read_depths_t_destroy(status, depths) \
+    status = F_none; \
+    depths.used = depths.size; \
+    while (depths.used > 0) { \
+      depths.used--; \
+      macro_fss_embedded_list_read_depth_t_destroy(status, depths.array[depths.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) f_macro_memory_structure_t_destroy(depths, fss_embedded_list_read_depth_t)
+
+  #define macro_fss_embedded_list_read_depths_t_delete_simple(depths) \
+    depths.used = depths.size; \
+    while (depths.used > 0) { \
+      depths.used--; \
+      macro_fss_embedded_list_read_depth_t_delete_simple(depths.array[depths.used]); \
+    } \
+    if (!depths.used) f_macro_memory_structure_t_delete_simple(depths, fss_embedded_list_read_depth_t)
+
+  #define macro_fss_embedded_list_read_depths_t_destroy_simple(depths) \
+    depths.used = depths.size; \
+    while (depths.used > 0) { \
+      depths.used--; \
+      macro_fss_embedded_list_read_depth_t_destroy_simple(depths.array[depths.used]); \
+    } \
+    if (!depths.used) f_macro_memory_structure_t_destroy_simple(depths, fss_embedded_list_read_depth_t)
+
+  #define macro_fss_embedded_list_read_t_depths_resize(status, depths, new_length) \
+    status = F_none; \
+    if (new_length < depths.size) { \
+      f_array_length_t i = depths.size - new_length; \
+      for (; i < depths.size; i++) { \
+        macro_fss_embedded_list_read_depth_t_delete(status, depths.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_resize((void **) & depths.array, sizeof(fss_embedded_list_read_depth_t), depths.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > depths.size) { \
+        f_array_length_t i = depths.size; \
+        for (; i < new_length; i++) { \
+          memset(&depths.array[i], 0, sizeof(fss_embedded_list_read_depth_t)); \
+        } \
+      } \
+      depths.size = new_length; \
+      if (depths.used > depths.size) depths.used = new_length; \
+    }
+
+  #define macro_fss_embedded_list_read_depths_t_adjust(status, depths, new_length) \
+    status = F_none; \
+    if (new_length < depths.size) { \
+      f_array_length_t i = depths.size - new_length; \
+      for (; i < depths.size; i++) { \
+        macro_fss_embedded_list_read_depth_t_delete(status, depths.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_adjust((void **) & depths.array, sizeof(fss_embedded_list_read_depth_t), depths.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > depths.size) { \
+        f_array_length_t i = depths.size; \
+        for (; i < new_length; i++) { \
+          memset(&depths.array[i], 0, sizeof(fss_embedded_list_read_depth_t)); \
+        } \
+      } \
+      depths.size = new_length; \
+      if (depths.used > depths.size) depths.used = new_length; \
+    }
+#endif // _di_fss_embedded_list_read_depths_t_
+
+/**
+ * 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.
+ * @param depths
+ *   This stores the pre-processed depth parameters.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fss_embedded_list_read_main_preprocess_depth_
+  extern f_return_status fss_embedded_list_read_main_preprocess_depth(const f_console_arguments_t arguments, const fss_embedded_list_read_data_t data, fss_embedded_list_read_depths_t *depths) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_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.
+ * @param objects_delimits
+ *   An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ *   An array of delimits detected during processing, for contents.
+ * @param comments
+ *   An array of ranges representing where comments are found within any valid content.
+ *   This only stores comments found within valid content only.
+ *
+ * @see fss_embedded_list_read_main_preprocess_depth()
+ * @see fss_embedded_list_read_main_process_for_depth()
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fss_embedded_list_read_main_process_file_
+  extern f_return_status fss_embedded_list_read_main_process_file(const f_console_arguments_t arguments, fss_embedded_list_read_data_t *data, const f_string_t file_name, const fss_embedded_list_read_depths_t depths, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits, f_fss_comments_t *comments) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_main_process_file_
+
+/**
+ * Process the items for a given depth.
+ *
+ * This will recursively continue down the depth chain until the final depth is reached.
+ *
+ * @param arguments
+ *   The console arguments passed to the program.
+ * @param file_name
+ *   The name of the file being processed.
+ * @param depths
+ *   The array of all depth related parameter settings.
+ * @param depths_index
+ *   The array location within depth being worked on.
+ * @param line
+ *   The line number parameter value, used for printing a specific line number for content.
+ * @param parents
+ *   The skip status of any parent lists.
+ *   Set parents.length to 0 for depth 0.
+ * @param data
+ *   The program specific data.
+ * @param objects_delimits
+ *   An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ *   An array of delimits detected during processing, for contents.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_read_main_process_file()
+ */
+#ifndef _di_fss_embedded_list_read_main_process_for_depth_
+  extern f_return_status fss_embedded_list_read_main_process_for_depth(const f_console_arguments_t arguments, const f_string_t filename, const fss_embedded_list_read_depths_t depths, const f_array_length_t depths_index, const f_array_length_t line, const fss_embedded_list_read_skip_t parents, fss_embedded_list_read_data_t *data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_main_process_for_depth_
+
+/**
+ * Print the end of an content.
+ *
+ * @param data
+ *   The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_content_end_
+  extern void fss_embedded_list_read_print_content_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_content_end_
+
+/**
+ * Print the ignore character for content.
+ *
+ * This is only used in pipe output mode.
+ *
+ * @param data
+ *   The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_content_ignore_
+  extern void fss_embedded_list_read_print_content_ignore(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_content_ignore_
+
+/**
+ * Print the end of an object (which is essentially the start of a content).
+ *
+ * @param data
+ *   The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_object_end_
+  extern void fss_embedded_list_read_print_object_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_object_end_
+
+/**
+ * Print the end of an object/content set.
+ *
+ * @param data
+ *   The program specific data.
+ */
+#ifndef _di_fss_embedded_list_read_print_set_end_
+  extern void fss_embedded_list_read_print_set_end(const fss_embedded_list_read_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_print_set_end_
+
+/**
+ * Rewrite the object and content delimit ranges to be within the given depth range.
+ *
+ * @param data
+ *   The program specific data.
+ * @param objects_delimits
+ *   An array of delimits detected during processing, for top-level objects.
+ * @param contents_delimits
+ *   An array of delimits detected during processing, for contents.
+ *
+ * @see fss_embedded_list_read_main_process_file()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_
+  extern void fss_embedded_list_read_process_delimits(const fss_embedded_list_read_data_t data, f_fss_delimits_t *objects_delimits, f_fss_delimits_t *contents_delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_
+
+/**
+ * Write the given delimits at the given depth back into the new delimits array, specifically for contents.
+ *
+ * @param data
+ *   The program specific data.
+ * @param depth
+ *   The depth in which to process.
+ * @param original_delimits
+ *   The original delimits structure.
+ * @param original_used
+ *   The size of the original delimits structure.
+ * @param delimits
+ *   The delimits array in which the delimits are written to.
+ *
+ * @see fss_embedded_list_read_process_delimits()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_contents_
+  extern void fss_embedded_list_read_process_delimits_contents(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_contents_
+
+/**
+ * Write the given delimits at the given depth back into the new delimits array, specifically for objects.
+ *
+ * @param data
+ *   The program specific data.
+ * @param depth
+ *   The depth in which to process.
+ * @param original_delimits
+ *   The original delimits structure.
+ * @param original_used
+ *   The size of the original delimits structure.
+ * @param delimits
+ *   The delimits array in which the delimits are written to.
+ *
+ * @see fss_embedded_list_read_process_delimits()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_objects_
+  extern void fss_embedded_list_read_process_delimits_objects(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t original_delimits[], const f_string_length_t original_used, f_fss_delimits_t *delimits) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_objects_
+
+/**
+ * Determine if the given location is actually within another depth.
+ *
+ * @param data
+ *   The program specific data.
+ * @param depth
+ *   The depth in which to process.
+ * @param location
+ *   The location to investigate.
+ *
+ * @return
+ *   TRUE if location is within a greater depth.
+ *   FALSE if location is not within a greater depth.
+ *
+ * @see fss_embedded_list_read_process_delimits_objects()
+ * @see fss_embedded_list_read_process_delimits_contents()
+ */
+#ifndef _di_fss_embedded_list_read_process_delimits_within_greater_
+  extern f_return_status fss_embedded_list_read_process_delimits_within_greater(const fss_embedded_list_read_data_t data, const f_string_length_t depth, const f_string_length_t location) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_read_process_delimits_within_greater_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_fss_embedded_list_read_h
diff --git a/level_3/fss_embedded_list_read/data/build/defines b/level_3/fss_embedded_list_read/data/build/defines
new file mode 100644 (file)
index 0000000..c665317
--- /dev/null
@@ -0,0 +1,2 @@
+# fss-0000
+
diff --git a/level_3/fss_embedded_list_read/data/build/dependencies b/level_3/fss_embedded_list_read/data/build/dependencies
new file mode 100644 (file)
index 0000000..4f23c89
--- /dev/null
@@ -0,0 +1,27 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_directory
+f_environment
+f_file
+f_fss
+f_pipe
+f_print
+fl_color
+fl_console
+fl_conversion
+fl_fss
+fl_print
+fl_status
+fl_string
+fll_error
+fll_execute
+fll_file
+fll_fss
+fll_program
diff --git a/level_3/fss_embedded_list_read/data/build/settings b/level_3/fss_embedded_list_read/data/build/settings
new file mode 100644 (file)
index 0000000..fd9b43c
--- /dev/null
@@ -0,0 +1,57 @@
+# fss-0001
+
+project_name fss_embedded_list_read
+
+version_major 0
+version_minor 5
+version_micro 2
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default monolithic
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library fss_embedded_list_read.c private-fss_embedded_list_read.c
+build_sources_program main.c
+build_sources_headers fss_embedded_list_read.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_headers_preserve no
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c
new file mode 100644 (file)
index 0000000..dae753a
--- /dev/null
@@ -0,0 +1,529 @@
+#include "fss_embedded_list_write.h"
+#include "private-fss_embedded_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_print_help_
+  f_return_status fss_embedded_list_write_print_help(const f_file_t output, const f_color_context_t context) {
+
+    fll_program_print_help_header(output, context, fss_embedded_list_write_name_long, fss_embedded_list_write_version);
+
+    fll_program_print_help_option(output, context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Print this help message.");
+    fll_program_print_help_option(output, context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, "    Output using colors that show up better on dark backgrounds.");
+    fll_program_print_help_option(output, context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Output using colors that show up better on light backgrounds.");
+    fll_program_print_help_option(output, context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color.");
+    fll_program_print_help_option(output, context, f_console_standard_short_quiet, f_console_standard_long_quiet, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Decrease verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_normal, f_console_standard_long_normal, f_console_symbol_short_disable, f_console_symbol_long_disable, "  Set verbosity to normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_verbose, f_console_standard_long_verbose, f_console_symbol_short_disable, f_console_symbol_long_disable, " Increase verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_debug, f_console_standard_long_debug, f_console_symbol_short_disable, f_console_symbol_long_disable, "   Enable debugging, inceasing verbosity beyond normal output.");
+    fll_program_print_help_option(output, context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number.");
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_file, fss_embedded_list_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, "   Specify a file to send output to.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_content, fss_embedded_list_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_double, fss_embedded_list_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_ignore, fss_embedded_list_write_long_ignore, f_console_symbol_short_enable, f_console_symbol_long_enable, " Ignore a given range within a content.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_object, fss_embedded_list_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_partial, fss_embedded_list_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_prepend, fss_embedded_list_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_single, fss_embedded_list_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
+    fll_program_print_help_option(output, context, fss_embedded_list_write_short_trim, fss_embedded_list_write_long_trim, f_console_symbol_short_enable, f_console_symbol_long_enable, "   Trim object names.");
+
+    fll_program_print_help_usage(output, context, fss_embedded_list_write_name, "");
+
+    fprintf(output.stream, "  The pipe uses the Backspace character '");
+    fl_color_print(output.stream, context.set.notable, "\\b");
+    fprintf(output.stream, "' (");
+    fl_color_print(output.stream, context.set.notable, "U+0008");
+    fprintf(output.stream, ") to designate the start of a Content.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The pipe uses the Form Feed character '");
+    fl_color_print(output.stream, context.set.notable, "\\f");
+    fprintf(output.stream, "' (");
+    fl_color_print(output.stream, context.set.notable, "U+000C");
+    fprintf(output.stream, ") to designate the end of the last Content.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The pipe uses the Vertical Line character '");
+    fl_color_print(output.stream, context.set.notable, "\\v");
+    fprintf(output.stream, "' (");
+    fl_color_print(output.stream, context.set.notable, "U+000B");
+    fprintf(output.stream, ") is used to ignore a content range (use this both before and after the range).%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  For the pipe, an Object is terminated by either a Backspace character '");
+    fl_color_print(output.stream, context.set.notable, "\\b");
+    fprintf(output.stream, "' (");
+    fl_color_print(output.stream, context.set.notable, "U+0008");
+    fprintf(output.stream, ") or a Form Feed character '");
+    fl_color_print(output.stream, context.set.notable, "\\f");
+    fprintf(output.stream, "' (");
+    fl_color_print(output.stream, context.set.notable, "U+000C");
+    fprintf(output.stream, ").%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The FSS-0008 (Embedded List) specification does not support quoted names, therefore the parameters '");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_single);
+    fprintf(output.stream, "' and '");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_double);
+    fprintf(output.stream, "' do nothing.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    fprintf(output.stream, "  The parameter '");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+    fprintf(output.stream, "' designates to not escape any valid nested Object or Content within some Content.%c", f_string_eol[0]);
+    fprintf(output.stream, "  This parameter requires two values.%c", f_string_eol[0]);
+    fprintf(output.stream, "  This parameter is not used for ignoring anything from the input pipe.%c", f_string_eol[0]);
+    fprintf(output.stream, "  This parameter must be specified after a '");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+    fprintf(output.stream, "' parameter and this applies only to the Content represented by that specific '");
+    fl_color_print(output.stream, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+    fprintf(output.stream, "' parameter.%c", f_string_eol[0]);
+
+    fprintf(output.stream, "%c", f_string_eol[0]);
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_write_print_help_
+
+#ifndef _di_fss_embedded_list_write_main_
+  f_return_status fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_data_t *data) {
+    f_status_t status = F_none;
+
+    {
+      const f_console_parameters_t parameters = f_macro_console_parameters_t_initialize(data->parameters, fss_embedded_list_write_total_parameters);
+
+      {
+        f_console_parameter_id_t ids[3] = { fss_embedded_list_write_parameter_no_color, fss_embedded_list_write_parameter_light, fss_embedded_list_write_parameter_dark };
+        const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 3);
+
+        status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+        data->error.context = data->context.set.error;
+        data->error.notable = data->context.set.notable;
+
+        if (F_status_is_error(status)) {
+          fss_embedded_list_write_delete_data(data);
+          return F_status_set_error(status);
+        }
+      }
+
+      // Identify priority of verbosity related parameters.
+      {
+        f_console_parameter_id_t ids[4] = { fss_embedded_list_write_parameter_verbosity_quiet, fss_embedded_list_write_parameter_verbosity_normal, fss_embedded_list_write_parameter_verbosity_verbose, fss_embedded_list_write_parameter_verbosity_debug };
+        f_console_parameter_id_t choice = 0;
+        const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 4);
+
+        status = f_console_parameter_prioritize_right(parameters, choices, &choice);
+
+        if (F_status_is_error(status)) {
+          fss_embedded_list_write_delete_data(data);
+          return status;
+        }
+
+        if (choice == fss_embedded_list_write_parameter_verbosity_quiet) {
+          data->error.verbosity = f_console_verbosity_quiet;
+        }
+        else if (choice == fss_embedded_list_write_parameter_verbosity_normal) {
+          data->error.verbosity = f_console_verbosity_normal;
+        }
+        else if (choice == fss_embedded_list_write_parameter_verbosity_verbose) {
+          data->error.verbosity = f_console_verbosity_verbose;
+        }
+        else if (choice == fss_embedded_list_write_parameter_verbosity_debug) {
+          data->error.verbosity = f_console_verbosity_debug;
+        }
+      }
+
+      status = F_none;
+    }
+
+    if (data->parameters[fss_embedded_list_write_parameter_help].result == f_console_result_found) {
+      fss_embedded_list_write_print_help(data->output, data->context);
+
+      fss_embedded_list_write_delete_data(data);
+      return status;
+    }
+
+    if (data->parameters[fss_embedded_list_write_parameter_version].result == f_console_result_found) {
+      fll_program_print_version(data->output, fss_embedded_list_write_version);
+
+      fss_embedded_list_write_delete_data(data);
+      return status;
+    }
+
+    f_file_t output = f_file_t_initialize;
+
+    output.id = f_type_descriptor_output;
+    output.stream = f_type_output;
+    output.flag = f_file_flag_create | f_file_flag_write_only | f_file_flag_append;
+
+    if (F_status_is_error_not(status)) {
+      if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_additional) {
+        if (data->parameters[fss_embedded_list_write_parameter_file].values.used > 1) {
+          if (data->error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_file);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]);
+          }
+
+          status = F_status_set_error(F_parameter);
+        }
+        else {
+          const f_string_length_t location = data->parameters[fss_embedded_list_write_parameter_file].values.array[0];
+
+          output.id = -1;
+          output.stream = 0;
+          status = f_file_stream_open(arguments.argv[location], 0, &output);
+
+          if (F_status_is_error(status)) {
+            fll_error_file_print(data->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file);
+          }
+        }
+      }
+      else if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_found) {
+        fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_file);
+        status = F_status_set_error(F_parameter);
+      }
+    }
+
+    if (F_status_is_error_not(status)) {
+      if (data->parameters[fss_embedded_list_write_parameter_object].locations.used || data->parameters[fss_embedded_list_write_parameter_content].locations.used) {
+        if (data->parameters[fss_embedded_list_write_parameter_object].locations.used) {
+          if (data->parameters[fss_embedded_list_write_parameter_object].locations.used != data->parameters[fss_embedded_list_write_parameter_object].values.used) {
+            fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+            status = F_status_set_error(F_parameter);
+          }
+          else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used != data->parameters[fss_embedded_list_write_parameter_content].values.used) {
+            fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+            status = F_status_set_error(F_parameter);
+          }
+          else if (data->parameters[fss_embedded_list_write_parameter_object].locations.used != data->parameters[fss_embedded_list_write_parameter_content].locations.used && data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_none) {
+            fss_embedded_list_write_error_parameter_same_times_print(*data);
+            status = F_status_set_error(F_parameter);
+          }
+          else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used && data->parameters[fss_embedded_list_write_parameter_partial].locations.used) {
+            if (data->parameters[fss_embedded_list_write_parameter_content].result == f_console_result_additional) {
+              if (data->error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+                fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+                fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+                fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '");
+                fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+                fl_color_print(data->error.to.stream, data->context.set.error, "' parameter or the '");
+                fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+                fl_color_print(data->error.to.stream, data->context.set.error, "' parameter, but not both.%c", f_string_eol[0]);
+              }
+
+              status = F_status_set_error(F_parameter);
+            }
+          }
+
+          if (F_status_is_error_not(status)) {
+            if (data->parameters[fss_embedded_list_write_parameter_content].result == f_console_result_additional) {
+              f_array_length_t location_object = 0;
+              f_array_length_t location_content = 0;
+              f_array_length_t location_sub_object = 0;
+              f_array_length_t location_sub_content = 0;
+
+              for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].locations.used; i++) {
+                location_object = data->parameters[fss_embedded_list_write_parameter_object].locations.array[i];
+                location_content = data->parameters[fss_embedded_list_write_parameter_content].locations.array[i];
+                location_sub_object = data->parameters[fss_embedded_list_write_parameter_object].locations_sub.array[i];
+                location_sub_content = data->parameters[fss_embedded_list_write_parameter_content].locations_sub.array[i];
+
+                if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) {
+                  if (data->error.verbosity != f_console_verbosity_quiet) {
+                    fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+                    fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error);
+                    fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+                    fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '");
+                    fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+                    fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+                  }
+
+                  status = F_status_set_error(F_parameter);
+                  break;
+                }
+              } // for
+            }
+          }
+        }
+        else if (data->parameters[fss_embedded_list_write_parameter_content].locations.used) {
+          if (data->parameters[fss_embedded_list_write_parameter_content].locations.used != data->parameters[fss_embedded_list_write_parameter_content].values.used) {
+            fss_embedded_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+            status = F_status_set_error(F_parameter);
+          }
+          else if (!data->parameters[fss_embedded_list_write_parameter_partial].locations.used) {
+            fss_embedded_list_write_error_parameter_same_times_print(*data);
+            status = F_status_set_error(F_parameter);
+          }
+        }
+      }
+      else if (!data->process_pipe) {
+        if (data->error.verbosity != f_console_verbosity_quiet) {
+          fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+        }
+
+        status = F_status_set_error(F_parameter);
+      }
+
+      if (F_status_is_error_not(status) && data->process_pipe) {
+        if (data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_found) {
+          if (data->error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]);
+          }
+
+          status = F_status_set_error(F_parameter);
+        }
+      }
+    }
+
+    if (F_status_is_error_not(status)) {
+      if (data->parameters[fss_embedded_list_write_parameter_prepend].result == f_console_result_found) {
+        if (data->error.verbosity != f_console_verbosity_quiet) {
+          fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+        }
+
+        status = F_status_set_error(F_parameter);
+      }
+      else if (data->parameters[fss_embedded_list_write_parameter_prepend].result == f_console_result_additional) {
+        const f_string_length_t index = data->parameters[fss_embedded_list_write_parameter_prepend].values.array[data->parameters[fss_embedded_list_write_parameter_prepend].values.used - 1];
+        const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+        if (length) {
+          f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+          data->prepend.string = arguments.argv[index];
+          data->prepend.used = length;
+          data->prepend.size = length;
+
+          for (; range.start < length; range.start++) {
+
+            status = f_fss_is_space(data->prepend, range);
+            if (F_status_is_error(status)) break;
+
+            if (status == F_false) {
+              if (data->error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+                fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+                fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+                fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+              }
+
+              status = F_status_set_error(F_parameter);
+              break;
+            }
+          } // for
+        }
+        else {
+          if (data->error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_prepend);
+            fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+          }
+
+          status = F_status_set_error(F_parameter);
+        }
+      }
+    }
+
+    if (F_status_is_error_not(status)) {
+      if (data->parameters[fss_embedded_list_write_parameter_ignore].result == f_console_result_found) {
+        if (data->error.verbosity != f_console_verbosity_quiet) {
+          fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no values were given.%c", f_string_eol[0]);
+        }
+
+        status = F_status_set_error(F_parameter);
+      }
+      else if (data->parameters[fss_embedded_list_write_parameter_ignore].result == f_console_result_additional) {
+        const f_array_length_t total_locations = data->parameters[fss_embedded_list_write_parameter_ignore].locations.used;
+        const f_array_length_t total_arguments = data->parameters[fss_embedded_list_write_parameter_ignore].values.used;
+
+        if (total_locations * 2 > total_arguments) {
+          fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+          fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+          fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_ignore);
+          fl_color_print(data->error.to.stream, data->context.set.error, "' requires two values.%c", f_string_eol[0]);
+
+          status = F_status_set_error(F_parameter);
+        }
+      }
+    }
+
+    f_fss_quote_t quote = f_fss_delimit_quote_double;
+
+    if (F_status_is_error_not(status)) {
+      if (data->parameters[fss_embedded_list_write_parameter_double].result == f_console_result_found) {
+        if (data->parameters[fss_embedded_list_write_parameter_single].result == f_console_result_found) {
+          if (data->parameters[fss_embedded_list_write_parameter_double].location < data->parameters[fss_embedded_list_write_parameter_single].location) {
+            quote = f_fss_delimit_quote_single;
+          }
+        }
+      }
+      else if (data->parameters[fss_embedded_list_write_parameter_single].result == f_console_result_found) {
+        quote = f_fss_delimit_quote_single;
+      }
+    }
+
+    f_string_dynamic_t buffer = f_string_dynamic_t_initialize;
+    f_string_dynamic_t object = f_string_dynamic_t_initialize;
+    f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+    if (F_status_is_error_not(status)) {
+      f_string_dynamic_t escaped = f_string_dynamic_t_initialize;
+      f_string_ranges_t ignore = f_string_ranges_t_initialize;
+
+      if (data->process_pipe) {
+        status = fss_embedded_list_write_process_pipe(*data, output, quote, &buffer, &ignore);
+
+        if (F_status_is_error(status)) {
+          if (data->error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe");
+            fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+          }
+        }
+
+        ignore.used = 0;
+      }
+
+      if (F_status_is_error_not(status)) {
+        if (data->parameters[fss_embedded_list_write_parameter_partial].result == f_console_result_found) {
+
+          if (data->parameters[fss_embedded_list_write_parameter_object].result == f_console_result_additional) {
+            for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].values.used; i++) {
+
+              object.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_object].values.array[i]];
+              object.used = strnlen(object.string, f_console_length_size);
+              object.size = object.used;
+
+              status = fss_embedded_list_write_process(*data, output, quote, &object, 0, 0, &buffer);
+              if (F_status_is_error(status)) break;
+            } // for
+          }
+          else {
+            for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_content].values.used; i++) {
+
+              status = fss_embedded_list_write_process_parameter_ignore(arguments, *data, data->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore);
+              if (F_status_is_error(status)) break;
+
+              content.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_content].values.array[i]];
+              content.used = strnlen(content.string, f_console_length_size);
+              content.size = content.used;
+
+              status = fss_embedded_list_write_process(*data, output, quote, 0, &content, &ignore, &buffer);
+              if (F_status_is_error(status)) break;
+            } // for
+          }
+        }
+        else {
+          for (f_array_length_t i = 0; i < data->parameters[fss_embedded_list_write_parameter_object].values.used; i++) {
+
+            status = fss_embedded_list_write_process_parameter_ignore(arguments, *data, data->parameters[fss_embedded_list_write_parameter_content].locations, i, &ignore);
+            if (F_status_is_error(status)) break;
+
+            object.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_object].values.array[i]];
+            object.used = strnlen(object.string, f_console_length_size);
+            object.size = object.used;
+
+            content.string = arguments.argv[data->parameters[fss_embedded_list_write_parameter_content].values.array[i]];
+            content.used = strnlen(content.string, f_console_length_size);
+            content.size = content.used;
+
+            status = fss_embedded_list_write_process(*data, output, quote, &object, &content, &ignore, &buffer);
+            if (F_status_is_error(status)) break;
+          } // for
+        }
+
+        if (F_status_is_error(status)) {
+          if (data->error.verbosity != f_console_verbosity_quiet) {
+            fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+            fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+            fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments");
+            fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+          }
+        }
+        else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_none) {
+
+          // ensure there is always a newline at the end, unless in quiet mode.
+          fprintf(data->output.stream, "%c", f_string_eol[0]);
+        }
+      }
+
+      f_macro_string_dynamic_t_delete_simple(escaped);
+      f_macro_string_ranges_t_delete_simple(ignore);
+
+      // object and content, though being a "dynamic" type, is being used statically, so clear them up to avoid invalid free().
+      object.string = 0;
+      object.used = 0;
+      object.size = 0;
+
+      content.string = 0;
+      content.used = 0;
+      content.size = 0;
+    }
+
+    if (data->parameters[fss_embedded_list_write_parameter_file].result == f_console_result_additional) {
+      if (output.id != -1) {
+        f_file_stream_close(F_true, &output);
+      }
+    }
+
+    // ensure a newline is always put at the end of the program execution, unless in quiet mode.
+    if (data->error.verbosity != f_console_verbosity_quiet) {
+      if (F_status_is_error(status)) {
+        fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+      }
+    }
+
+    f_macro_string_dynamic_t_delete_simple(buffer);
+    f_macro_string_dynamic_t_delete_simple(object);
+    f_macro_string_dynamic_t_delete_simple(content);
+    fss_embedded_list_write_delete_data(data);
+    return status;
+  }
+#endif // _di_fss_embedded_list_write_main_
+
+#ifndef _di_fss_embedded_list_write_delete_data_
+  f_return_status fss_embedded_list_write_delete_data(fss_embedded_list_write_data_t *data) {
+
+    for (f_string_length_t i = 0; i < fss_embedded_list_write_total_parameters; i++) {
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].locations);
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub);
+      f_macro_string_lengths_t_delete_simple(data->parameters[i].values);
+    } // for
+
+    f_macro_string_lengths_t_delete_simple(data->remaining);
+
+    f_macro_color_context_t_delete_simple(data->context);
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h
new file mode 100644 (file)
index 0000000..c3df671
--- /dev/null
@@ -0,0 +1,214 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This program provides FSS-0008 Embedded List write functionality.
+ */
+#ifndef _fss_embedded_list_write_h
+
+// libc includes
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/console.h>
+#include <level_0/file.h>
+#include <level_0/pipe.h>
+#include <level_0/print.h>
+
+// fll-1 includes
+#include <level_1/color.h>
+#include <level_1/console.h>
+#include <level_1/conversion.h>
+#include <level_1/fss_embedded_list.h>
+#include <level_1/status.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/error.h>
+#include <level_2/fss_status.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_version_
+  #define fss_embedded_list_write_major_version "0"
+  #define fss_embedded_list_write_minor_version "5"
+  #define fss_embedded_list_write_micro_version "2"
+  #define fss_embedded_list_write_version fss_embedded_list_write_major_version "." fss_embedded_list_write_minor_version "." fss_embedded_list_write_micro_version
+#endif // _di_fss_embedded_list_write_version_
+
+#ifndef _di_fss_embedded_list_write_name_
+  #define fss_embedded_list_write_name      "fss_embedded_list_write"
+  #define fss_embedded_list_write_name_long "FSS Embedded List Write"
+#endif // _di_fss_embedded_list_write_name_
+
+#ifndef _di_fss_embedded_list_write_defines_
+  #define fss_embedded_list_write_pipe_content_end    '\f'
+  #define fss_embedded_list_write_pipe_content_ignore '\v'
+  #define fss_embedded_list_write_pipe_content_start  '\b'
+
+  #define fss_embedded_list_write_short_file    "f"
+  #define fss_embedded_list_write_short_content "c"
+  #define fss_embedded_list_write_short_double  "d"
+  #define fss_embedded_list_write_short_ignore  "I"
+  #define fss_embedded_list_write_short_object  "o"
+  #define fss_embedded_list_write_short_partial "p"
+  #define fss_embedded_list_write_short_prepend "P"
+  #define fss_embedded_list_write_short_single  "s"
+  #define fss_embedded_list_write_short_trim    "T"
+
+  #define fss_embedded_list_write_long_file    "file"
+  #define fss_embedded_list_write_long_content "content"
+  #define fss_embedded_list_write_long_double  "double"
+  #define fss_embedded_list_write_long_ignore  "ignore"
+  #define fss_embedded_list_write_long_object  "object"
+  #define fss_embedded_list_write_long_partial "partial"
+  #define fss_embedded_list_write_long_prepend "prepend"
+  #define fss_embedded_list_write_long_single  "single"
+  #define fss_embedded_list_write_long_trim    "trim"
+
+  enum {
+    fss_embedded_list_write_parameter_help,
+    fss_embedded_list_write_parameter_light,
+    fss_embedded_list_write_parameter_dark,
+    fss_embedded_list_write_parameter_no_color,
+    fss_embedded_list_write_parameter_verbosity_quiet,
+    fss_embedded_list_write_parameter_verbosity_normal,
+    fss_embedded_list_write_parameter_verbosity_verbose,
+    fss_embedded_list_write_parameter_verbosity_debug,
+    fss_embedded_list_write_parameter_version,
+
+    fss_embedded_list_write_parameter_file,
+    fss_embedded_list_write_parameter_content,
+    fss_embedded_list_write_parameter_double,
+    fss_embedded_list_write_parameter_ignore,
+    fss_embedded_list_write_parameter_object,
+    fss_embedded_list_write_parameter_partial,
+    fss_embedded_list_write_parameter_prepend,
+    fss_embedded_list_write_parameter_single,
+    fss_embedded_list_write_parameter_trim,
+  };
+
+  #define fss_embedded_list_write_console_parameter_t_initialize \
+    { \
+      f_console_parameter_t_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, F_false, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_normal, f_console_standard_long_normal, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_debug, f_console_standard_long_debug, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_file, fss_embedded_list_write_long_file, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_content, fss_embedded_list_write_long_content, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_double, fss_embedded_list_write_long_double, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_ignore, fss_embedded_list_write_long_ignore, 0, 2, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_object, fss_embedded_list_write_long_object, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_partial, fss_embedded_list_write_long_partial, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_prepend, fss_embedded_list_write_long_prepend, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_single, fss_embedded_list_write_long_single, 0, 0, f_console_type_normal), \
+      f_console_parameter_t_initialize(fss_embedded_list_write_short_trim, fss_embedded_list_write_long_trim, 0, 0, f_console_type_normal), \
+    }
+
+  #define fss_embedded_list_write_total_parameters 18
+#endif // _di_fss_embedded_list_write_defines_
+
+#ifndef _di_fss_embedded_list_write_data_t_
+  typedef struct {
+    f_console_parameter_t parameters[fss_embedded_list_write_total_parameters];
+
+    f_string_lengths_t remaining;
+    bool process_pipe;
+
+    f_file_t output;
+    fll_error_print_t error;
+    f_string_static_t prepend;
+
+    f_color_context_t context;
+  } fss_embedded_list_write_data_t;
+
+  #define fss_embedded_list_write_data_t_initialize \
+    { \
+      fss_embedded_list_write_console_parameter_t_initialize, \
+      f_string_lengths_t_initialize, \
+      F_false, \
+      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      fll_error_print_t_initialize, \
+      f_string_static_t_initialize, \
+      f_color_context_t_initialize, \
+    }
+#endif // _di_fss_embedded_list_write_data_t_
+
+/**
+ * Print help.
+ *
+ * @param output
+ *   The file to print to.
+ * @param context
+ *   The color context settings.
+ *
+ * @return
+ *   F_none on success.
+ */
+#ifndef _di_fss_embedded_list_write_print_help_
+  extern f_return_status fss_embedded_list_write_print_help(const f_file_t output, const f_color_context_t context);
+#endif // _di_fss_embedded_list_write_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call fss_embedded_list_write_delete_data() after executing this.
+ *
+ * @param arguments
+ *   The parameters passed to the process.
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_write_delete_data()
+ */
+#ifndef _di_fss_embedded_list_write_main_
+  extern f_return_status fss_embedded_list_write_main(const f_console_arguments_t arguments, fss_embedded_list_write_data_t *data);
+#endif // _di_fss_embedded_list_write_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing fss_embedded_list_write_main().
+ *
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_embedded_list_write_main()
+ */
+#ifndef _di_fss_embedded_list_write_delete_data_
+  extern f_return_status fss_embedded_list_write_delete_data(fss_embedded_list_write_data_t *data);
+#endif // _di_fss_embedded_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _fss_embedded_list_write_h
diff --git a/level_3/fss_embedded_list_write/c/main.c b/level_3/fss_embedded_list_write/c/main.c
new file mode 100644 (file)
index 0000000..7db7189
--- /dev/null
@@ -0,0 +1,16 @@
+#include "fss_embedded_list_write.h"
+
+int main(const unsigned long argc, const f_string_t *argv) {
+  const f_console_arguments_t arguments = { argc, argv };
+  fss_embedded_list_write_data_t data = fss_embedded_list_write_data_t_initialize;
+
+  if (f_pipe_input_exists()) {
+    data.process_pipe = F_true;
+  }
+
+  if (F_status_is_error(fss_embedded_list_write_main(arguments, &data))) {
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.c
new file mode 100644 (file)
index 0000000..e3226df
--- /dev/null
@@ -0,0 +1,409 @@
+#include "fss_embedded_list_write.h"
+#include "private-fss_embedded_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_
+  void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_data_t data) {
+
+    if (data.error.verbosity == f_console_verbosity_quiet) {
+      return;
+    }
+
+    fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+    fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify both the '", fll_error_print_error);
+    fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_object);
+    fl_color_print(data.error.to.stream, data.context.set.error, "' parameter and the '");
+    fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_content);
+    fl_color_print(data.error.to.stream, data.context.set.error, "' parameter the same number of times when not specifying the ");
+    fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_embedded_list_write_long_partial);
+    fl_color_print(data.error.to.stream, data.context.set.error, "' parameter.%c", f_string_eol[0]);
+  }
+#endif // _di_fss_embedded_list_write_error_parameter_same_times_print_
+
+#ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+  void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_data_t data) {
+
+    if (data.error.verbosity == f_console_verbosity_quiet) {
+      return;
+    }
+
+    fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+    fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error);
+    fl_color_print(data.error.to.stream, data.context.set.notable, "\\n");
+    fl_color_print(data.error.to.stream, data.context.set.error, "' in objects.%c", f_string_eol[0]);
+  }
+#endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+
+#ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_
+  void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) {
+
+    if (data.error.verbosity == f_console_verbosity_quiet) {
+      return;
+    }
+
+    fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+    fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error);
+    fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter);
+    fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+  }
+#endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_
+
+#ifndef _di_fss_embedded_list_write_process_
+  f_return_status fss_embedded_list_write_process(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) {
+    f_status_t status = F_none;
+
+    f_string_range_t range = f_string_range_t_initialize;
+
+    if (object) {
+      uint8_t complete = f_fss_complete_none;
+
+      if (object->used) {
+        range.start = 0;
+        range.stop = object->used - 1;
+      }
+      else {
+        range.start = 1;
+        range.stop = 0;
+      }
+
+      if (content) {
+        if (data.parameters[fss_embedded_list_write_parameter_trim].result == f_console_result_found) {
+          complete = f_fss_complete_full_trim;
+        }
+        else {
+          complete = f_fss_complete_full;
+        }
+      }
+
+      status = fl_fss_embedded_list_object_write_string(*object, complete, &range, buffer);
+
+      if (F_status_set_fine(status) == F_none_eol) {
+        fss_embedded_list_write_error_parameter_unsupported_eol_print(data);
+
+        return F_status_set_error(F_unsupported);
+      }
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fl_fss_embedded_list_object_write_string", F_true);
+        return status;
+      }
+    }
+
+    if (content && content->used) {
+      range.start = 0;
+      range.stop = content->used - 1;
+
+      status = fl_fss_embedded_list_content_write_string(*content, object ? f_fss_complete_full : f_fss_complete_none, &data.prepend, ignore, &range, buffer);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fl_fss_embedded_list_content_write_string", F_true);
+        return status;
+      }
+    }
+
+    if (!object || !content) {
+      status = fl_string_append(f_string_eol, 1, buffer);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+        return status;
+      }
+    }
+
+    f_print_dynamic(output.stream, *buffer);
+
+    buffer->used = 0;
+    return status;
+  }
+#endif // _di_fss_embedded_list_write_process_
+
+#ifndef _di_fss_embedded_list_write_process_pipe_
+  f_return_status fss_embedded_list_write_process_pipe(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) {
+    f_status_t status = F_none;
+    f_status_t status_pipe = F_none;
+
+    f_file_t input = f_file_t_initialize;
+
+    input.id = f_type_descriptor_input;
+    input.size_read = 2048;
+
+    f_string_length_t total = 0;
+    f_string_length_t previous = 0;
+
+    f_string_range_t range = f_string_range_t_initialize;
+    f_string_range_t range_ignore = f_string_range_t_initialize;
+
+    f_string_dynamic_t block = f_string_dynamic_t_initialize;
+    f_string_dynamic_t object = f_string_dynamic_t_initialize;
+    f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+    // 0x0 = start new object/content set, 0x1 = processing object, 0x2 = processing content, 0x3 = end object/content set.
+    uint8_t state = 0;
+
+    for (;;) {
+
+      if (range.start > range.stop) {
+        if (status_pipe == F_none_eof) break;
+
+        block.used = 0;
+
+        status_pipe = f_file_read_block(input, &block);
+
+        if (F_status_is_error(status_pipe)) {
+          fll_error_print(data.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true);
+
+          status_pipe = F_status_set_error(F_pipe);
+          break;
+        }
+
+        if (!block.used) break;
+
+        range.start = 0;
+        range.stop = block.used - 1;
+      }
+
+      if (!state || state == 0x1) {
+        if (!state) {
+          object.used = 0;
+          content.used = 0;
+
+          state = 0x1;
+
+          range_ignore.start = 1;
+          range_ignore.stop = 0;
+        }
+
+        if (object.used + block.used > object.size) {
+          status = fl_string_dynamic_increase_by(block.used, &object);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_increase_by", F_true);
+            break;
+          }
+        }
+
+        for (; range.start <= range.stop; range.start++) {
+
+          if (block.string[range.start] == fss_embedded_list_write_pipe_content_start) {
+            state = 0x2;
+            range.start++;
+            break;
+          }
+
+          if (block.string[range.start] == fss_embedded_list_write_pipe_content_end) {
+            state = 0x3;
+            range.start++;
+            break;
+          }
+
+          if (block.string[range.start] == fss_embedded_list_write_pipe_content_ignore) {
+            // this is not used by objects.
+            continue;
+          }
+
+          object.string[object.used++] = block.string[range.start];
+        } // for
+
+        if (F_status_is_error(status)) break;
+
+        // if the start of content was not found, then fetch the next block.
+        if (state == 0x1) continue;
+
+        // if the end of the current block is reached, fetch the next block.
+        if (range.start > range.stop) continue;
+      }
+
+      if (state == 0x2) {
+        if (range.start <= range.stop) {
+          total = (range.stop - range.start) + 1;
+        }
+        else {
+          total = 0;
+        }
+
+        if (total) {
+          if (content.used + total > content.size) {
+            status = fl_string_dynamic_increase_by(total, &content);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_increase_by", F_true);
+              break;
+            }
+          }
+
+          for (; range.start <= range.stop; range.start++) {
+
+            if (block.string[range.start] == fss_embedded_list_write_pipe_content_start) {
+              if (data.error.verbosity != f_console_verbosity_quiet) {
+                fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+                fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]);
+              }
+
+              status = F_status_set_error(F_unsupported);
+              break;
+            }
+
+            if (block.string[range.start] == fss_embedded_list_write_pipe_content_end) {
+              state = 0x3;
+              range.start++;
+              break;
+            }
+
+            if (block.string[range.start] == fss_embedded_list_write_pipe_content_ignore) {
+              if (ignore) {
+                if (range_ignore.start > range_ignore.stop) {
+                  range_ignore.start = content.used;
+                  range_ignore.stop = content.used;
+                }
+                else {
+                  if (ignore->used + 1 > ignore->size) {
+                    if (ignore->size + f_fss_default_allocation_step > f_array_length_t_size) {
+                      if (ignore->size + 1 > f_array_length_t_size) {
+                        fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true);
+
+                        status = F_status_set_error(F_string_too_large);
+                        break;
+                      }
+
+                      f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + 1);
+                    }
+                    else {
+                      f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + f_fss_default_allocation_step);
+                    }
+
+                    if (F_status_is_error(status)) {
+                      fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_pipe", F_true);
+                      break;
+                    }
+                  }
+
+                  ignore->array[ignore->used].start = range_ignore.start;
+                  ignore->array[ignore->used++].stop = content.used - 1;
+
+                  range_ignore.start = 1;
+                  range_ignore.stop = 0;
+                }
+              }
+
+              continue;
+            }
+
+            content.string[content.used++] = block.string[range.start];
+          } // for
+
+          if (F_status_is_error(status)) break;
+        }
+        else {
+          state = 0x3;
+        }
+      }
+
+      if (state == 0x3) {
+        status = fss_embedded_list_write_process(data, output, quote, &object, &content, ignore, buffer);
+        if (F_status_is_error(status)) break;
+
+        state = 0;
+      }
+    } // for
+
+    // if the pipe ended before finishing, then attempt to wrap up.
+    if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) {
+      status = fss_embedded_list_write_process(data, output, quote, &object, &content, ignore, buffer);
+    }
+
+    f_macro_string_dynamic_t_delete_simple(block);
+    f_macro_string_dynamic_t_delete_simple(object);
+    f_macro_string_dynamic_t_delete_simple(content);
+    return status;
+  }
+#endif // _di_fss_embedded_list_write_process_pipe_
+
+#ifndef _di_fss_embedded_list_write_process_parameter_ignore_
+  f_return_status fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_data_t data, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) {
+    f_status_t status = F_none;
+
+    f_array_length_t i = 0;
+    f_array_length_t l = 0;
+    f_array_length_t index = 0;
+
+    f_string_range_t range = f_string_range_t_initialize;
+
+    f_number_unsigned_t number = 0;
+
+    range.start = 0;
+
+    for (; i < data.parameters[fss_embedded_list_write_parameter_ignore].locations.used; i++) {
+
+      l = data.parameters[fss_embedded_list_write_parameter_ignore].locations.array[i];
+
+      if (l < contents.array[location]) continue;
+      if (location + 1 < contents.used && l > contents.array[location + 1]) continue;
+
+      if (ignore->used + 1 > ignore->size) {
+        if (ignore->size + f_fss_default_allocation_step > f_array_length_t_size) {
+          if (ignore->size + 1 > f_array_length_t_size) {
+            fll_error_print(data.error, F_string_too_large, "fss_embedded_list_write_process_parameter_ignore", F_true);
+            return F_status_set_error(F_string_too_large);
+          }
+
+          f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + 1);
+        }
+        else {
+          f_macro_string_ranges_t_resize(status, (*ignore), ignore->size + f_fss_default_allocation_step);
+        }
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fss_embedded_list_write_process_parameter_ignore", F_true);
+          return status;
+        }
+      }
+
+      index = data.parameters[fss_embedded_list_write_parameter_ignore].values.array[i * 2];
+
+      range.start = 0;
+      range.stop = strnlen(arguments.argv[index], f_console_length_size) - 1;
+
+      // allow and ignore the positive sign.
+      if (range.stop > 0 && arguments.argv[index][0] == '+') {
+        range.start = 1;
+      }
+
+      status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &number, range);
+
+      if (F_status_is_error(status)) {
+        fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore, arguments.argv[index]);
+        return status;
+      }
+
+      ignore->array[ignore->used].start = number;
+
+      index = data.parameters[fss_embedded_list_write_parameter_ignore].values.array[(i * 2) + 1];
+
+      range.start = 0;
+      range.stop = strnlen(arguments.argv[index], f_console_length_size) - 1;
+
+      // allow and ignore the positive sign.
+      if (range.stop > 0 && arguments.argv[index][0] == '+') {
+        range.start = 1;
+      }
+
+      status = fl_conversion_string_to_number_unsigned(arguments.argv[index], &number, range);
+
+      if (F_status_is_error(status)) {
+        fll_error_parameter_integer_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true, fss_embedded_list_write_long_ignore, arguments.argv[index]);
+        return status;
+      }
+
+      ignore->array[ignore->used++].stop = number;
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fss_embedded_list_write_process_parameter_ignore_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h b/level_3/fss_embedded_list_write/c/private-fss_embedded_list_write.h
new file mode 100644 (file)
index 0000000..4fbd049
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_fss_embedded_list_write_h
+#define _PRIVATE_fss_embedded_list_write_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print an message about the object and content parameters not being specified the same number of times.
+ *
+ * @param data
+ *   The program data.
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_same_times_print_
+  void fss_embedded_list_write_error_parameter_same_times_print(const fss_embedded_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_same_times_print_
+
+/**
+ * Print an message about a parameter EOL being unsupported.
+ *
+ * @param data
+ *   The program data.
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+  void fss_embedded_list_write_error_parameter_unsupported_eol_print(const fss_embedded_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_unsupported_eol_print_
+
+/**
+ * Print an message about a parameter missing a value.
+ *
+ * @param data
+ *   The program data.
+ * @param symbol
+ *   The console symbol, such as "--" in "--help".
+ * @param parameter
+ *   The parameter name, such as "help" in "--help".
+ */
+#ifndef _di_fss_embedded_list_write_error_parameter_value_missing_print_
+  void fss_embedded_list_write_error_parameter_value_missing_print(const fss_embedded_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_error_parameter_value_missing_print_
+
+/**
+ * Process a given object and content, printing the FSS if valid or an error if invalid.
+ *
+ * @param data
+ *   The program data.
+ * @param output
+ *   The file to output to.
+ * @param quote
+ *   The quote character to use.
+ *   This is either single our double quote.
+ * @param object
+ *   The object to validate and print.
+ *   Set pointer address to 0 to not use.
+ * @param content
+ *   The content to escape and print.
+ *   Set pointer address to 0 to not use.
+ * @param ignore
+ *   An array of ranges within the Content to ignore.
+ *   Set pointer address to 0 to not use.
+ * @param buffer
+ *   The buffer array used as a cache to construct the output before printing.
+ *
+ * @return
+ *   F_none on success.
+ *   F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_
+  extern f_return_status fss_embedded_list_write_process(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, const f_string_ranges_t *ignore, f_string_dynamic_t *buffer) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_
+
+/**
+ * Process the pipe, reading from the pipe and writing to the output.
+ *
+ * @param data
+ *   The program data.
+ * @param output
+ *   The file to output to.
+ * @param quote
+ *   The quote character to use.
+ *   This is either single our double quote.
+ * @param buffer
+ *   The buffer array used as a cache to construct the output before printing.
+ * @param ignore
+ *   An array of ranges within the Content to ignore.
+ *   Set pointer address to 0 to not use.
+ *
+ * @return
+ *   F_none on success.
+ *   F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_pipe_
+  extern f_return_status fss_embedded_list_write_process_pipe(const fss_embedded_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer, f_string_ranges_t *ignore) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_pipe_
+
+/**
+ * Process the ignore parameter associated with a specific content parameter.
+ *
+ * @param arguments
+ *   The parameters passed to the process.
+ * @param data
+ *   The program data.
+ * @param contents
+ *   The console parameter locations array for the content parameter.
+ * @param location
+ *   The specific location within the contents locations array.
+ * @param ignore
+ *   An array of ranges within the Content to ignore.
+ *
+ * @return
+ *   F_none on success.
+ *   F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_embedded_list_write_process_parameter_ignore_
+  extern f_return_status fss_embedded_list_write_process_parameter_ignore(const f_console_arguments_t arguments, const fss_embedded_list_write_data_t data, const f_array_lengths_t contents, const f_array_length_t location, f_string_ranges_t *ignore) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_embedded_list_write_process_parameter_ignore_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_fss_embedded_list_write_h
diff --git a/level_3/fss_embedded_list_write/data/build/defines b/level_3/fss_embedded_list_write/data/build/defines
new file mode 100644 (file)
index 0000000..c665317
--- /dev/null
@@ -0,0 +1,2 @@
+# fss-0000
+
diff --git a/level_3/fss_embedded_list_write/data/build/dependencies b/level_3/fss_embedded_list_write/data/build/dependencies
new file mode 100644 (file)
index 0000000..35c97b5
--- /dev/null
@@ -0,0 +1,26 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_directory
+f_environment
+f_file
+f_fss
+f_pipe
+f_print
+fl_color
+fl_console
+fl_conversion
+fl_fss
+fl_status
+fl_string
+fll_error
+fll_execute
+fll_file
+fll_fss
+fll_program
diff --git a/level_3/fss_embedded_list_write/data/build/settings b/level_3/fss_embedded_list_write/data/build/settings
new file mode 100644 (file)
index 0000000..2ff7829
--- /dev/null
@@ -0,0 +1,57 @@
+# fss-0001
+
+project_name fss_embedded_list_write
+
+version_major 0
+version_minor 5
+version_micro 2
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default monolithic
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library fss_embedded_list_write.c private-fss_embedded_list_write.c
+build_sources_program main.c
+build_sources_headers fss_embedded_list_write.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_headers_preserve no
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
index 214b4aac1d94ab671d3e378559a5f01859b74ea8..791f2254f97e4ff81b23ebd5b3732d36fb78ce42 100644 (file)
@@ -5,7 +5,7 @@
  * API Version: 0.5
  * Licenses: lgplv2.1
  *
- * This program provides fss basic list write functionality.
+ * This program provides FSS-0003 Extended List write functionality.
  */
 #ifndef _fss_extended_list_write_h
 
@@ -51,7 +51,7 @@ extern "C" {
 
 #ifndef _di_fss_extended_list_write_name_
   #define fss_extended_list_write_name      "fss_extended_list_write"
-  #define fss_extended_list_write_name_long "FSS Basic List Write"
+  #define fss_extended_list_write_name_long "FSS Extended List Write"
 #endif // _di_fss_extended_list_write_name_
 
 #ifndef _di_fss_extended_list_write_defines_