]> Kevux Git Server - fll/commitdiff
Progress: IKI Read
authorKevin Day <thekevinday@gmail.com>
Wed, 24 Jun 2020 05:19:31 +0000 (00:19 -0500)
committerKevin Day <thekevinday@gmail.com>
Wed, 24 Jun 2020 05:19:31 +0000 (00:19 -0500)
Begin the process of adding the IKI Read program.

level_3/iki_read/c/iki_read.c [new file with mode: 0644]
level_3/iki_read/c/iki_read.h [new file with mode: 0644]
level_3/iki_read/c/main.c [new file with mode: 0644]
level_3/iki_read/c/private-iki_read.c [new file with mode: 0644]
level_3/iki_read/c/private-iki_read.h [new file with mode: 0644]
level_3/iki_read/data/build/defines [new file with mode: 0644]
level_3/iki_read/data/build/dependencies [new file with mode: 0644]
level_3/iki_read/data/build/settings [new file with mode: 0644]

diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c
new file mode 100644 (file)
index 0000000..32c6ba9
--- /dev/null
@@ -0,0 +1,424 @@
+#include <level_3/iki_read.h>
+#include "private-iki_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_read_print_help_
+  f_return_status iki_read_print_help(const fl_color_context context) {
+    fll_program_print_help_header(context, iki_read_name_long, iki_read_version);
+
+    fll_program_print_help_option(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(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(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(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(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(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(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.");
+
+    printf("%c", f_string_eol[0]);
+
+    fll_program_print_help_option(context, iki_read_short_at, iki_read_long_at, f_console_symbol_short_enable, f_console_symbol_long_enable, "  Select variable at this numeric index.");
+    fll_program_print_help_option(context, iki_read_short_line, iki_read_long_line, f_console_symbol_short_enable, f_console_symbol_long_enable, "Print only the variables at the given line.");
+    fll_program_print_help_option(context, iki_read_short_name, iki_read_long_name, f_console_symbol_short_enable, f_console_symbol_long_enable, "Select variables with this name.");
+
+    printf("%c", f_string_eol[0]);
+
+    fll_program_print_help_option(context, iki_read_short_literal, iki_read_long_literal, f_console_symbol_short_enable, f_console_symbol_long_enable, "Print the entire variable instead of the content.");
+    fll_program_print_help_option(context, iki_read_short_object, iki_read_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print the variable name instead of the variable content.");
+    fll_program_print_help_option(context, iki_read_short_raw, iki_read_long_raw, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Print the raw data instead of the variable data.");
+    fll_program_print_help_option(context, iki_read_short_total, iki_read_long_total, f_console_symbol_short_enable, f_console_symbol_long_enable, "  Print the total number of variables.");
+
+    printf("%c", f_string_eol[0]);
+
+    fll_program_print_help_option(context, iki_read_short_substitute, iki_read_long_substitute, f_console_symbol_short_enable, f_console_symbol_long_enable,"Substitute the entire variable for the given name and content value with the given string.");
+    fll_program_print_help_option(context, iki_read_short_expand, iki_read_long_expand, f_console_symbol_short_enable, f_console_symbol_long_enable, "    Expand all values.");
+
+    fll_program_print_help_usage(context, iki_read_name, "filename(s)");
+
+    fl_color_print(f_type_output, context.important, context.reset, " Notes:");
+
+    printf("%c", f_string_eol[0], f_string_eol[0]);
+
+    printf("  This program will find and print all content following the IKI standard, without focusing on any particular vocabulary specification.%c", f_string_eol[0]);
+
+    printf("%c", f_string_eol[0]);
+
+    printf("  The ");
+    fl_color_print(f_type_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_substitute);
+    printf(" option, requires 3 additional parameters: ");
+
+    fl_color_print(f_type_output, context.notable, context.reset, "<");
+    printf("%s", iki_read_replacement_vocabulary);
+    fl_color_print(f_type_output, context.notable, context.reset, ">");
+    printf(" ");
+    fl_color_print(f_type_output, context.notable, context.reset, "<");
+    printf("%s", iki_read_replacement_replace);
+    fl_color_print(f_type_output, context.notable, context.reset, ">");
+    printf(" ");
+    fl_color_print(f_type_output, context.notable, context.reset, "<");
+    printf("%s", iki_read_replacement_with);
+    fl_color_print(f_type_output, context.notable, context.reset, ">");
+    printf(".%c", f_string_eol[0]);
+
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_vocabulary);
+    printf(": The name of the vocabulary whose content is to be substituted.%c", f_string_eol[0]);
+
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_replace);
+    printf(":    The content matching this exact string will be substituted.%c", f_string_eol[0]);
+
+    fl_color_print(f_type_output, context.notable, context.reset, "    %s", iki_read_replacement_with);
+    printf(":       The new string to use as the substitute.%c", f_string_eol[0]);
+
+    printf("%c", f_string_eol[0]);
+
+    printf("  The vocabulary and replacement are case-sensitive and must exactly match.%c", f_string_eol[0]);
+
+    printf("%c", f_string_eol[0]);
+
+    return F_none;
+  }
+#endif // _di_iki_read_print_help_
+
+#ifndef _di_iki_read_main_
+  f_return_status iki_read_main(const f_console_arguments arguments, iki_read_data *data) {
+    f_status status = F_none;
+
+    {
+      f_console_parameters parameters = { data->parameters, iki_read_total_parameters };
+      f_console_parameter_id ids[3] = { iki_read_parameter_no_color, iki_read_parameter_light, iki_read_parameter_dark };
+      f_console_parameter_ids choices = { ids, 3 };
+
+      status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+      if (F_status_is_error(status)) {
+        iki_read_delete_data(data);
+        return F_status_set_error(status);
+      }
+
+      status = F_none;
+    }
+
+    if (data->parameters[iki_read_parameter_help].result == f_console_result_found) {
+      iki_read_print_help(data->context);
+
+      iki_read_delete_data(data);
+      return status;
+    }
+    else if (data->parameters[iki_read_parameter_version].result == f_console_result_found) {
+      fll_program_print_version(iki_read_version);
+
+      iki_read_delete_data(data);
+      return status;
+    }
+
+    if (data->parameters[iki_read_parameter_verbose].result == f_console_result_found) {
+      if (data->parameters[iki_read_parameter_quiet].result == f_console_result_found) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+        fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, f_console_standard_long_verbose);
+        fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+        fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, f_console_standard_long_quiet);
+        fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+      }
+
+      data->verbosity = iki_read_verbosity_verbose;
+    }
+    else if (data->parameters[iki_read_parameter_quiet].result == f_console_result_found) {
+      data->verbosity = iki_read_verbosity_quiet;
+    }
+    else {
+      data->verbosity = iki_read_verbosity_normal;
+    }
+
+    if (data->remaining.used > 0 || data->process_pipe) {
+      if (data->parameters[iki_read_parameter_at].result == f_console_result_found) {
+        if (data->verbosity != iki_read_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+          fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_at);
+          fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' requires a positive number.");
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+        }
+
+        iki_read_delete_data(data);
+        return F_status_set_error(F_parameter);
+      }
+
+      if (data->parameters[iki_read_parameter_line].result == f_console_result_found) {
+        if (data->verbosity != iki_read_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+          fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_line);
+          fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' requires a positive number.");
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+        }
+
+        iki_read_delete_data(data);
+        return F_status_set_error(F_parameter);
+      }
+      else if (data->parameters[iki_read_parameter_line].result == f_console_result_additional) {
+        const f_string_length index = data->parameters[iki_read_parameter_line].additional.array[data->parameters[iki_read_parameter_line].additional.used - 1];
+
+        status = fl_console_parameter_to_number_unsigned(arguments.argv[index], &data->line);
+        if (F_status_is_error(status)) {
+          iki_read_print_error_number_argument(data->context, data->verbosity, F_status_set_fine(status), "fl_console_parameter_to_number_unsigned", iki_read_long_line, arguments.argv[index]);
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        // additional
+      }
+
+      if (data->parameters[iki_read_parameter_name].result == f_console_result_found) {
+        if (data->verbosity != iki_read_verbosity_quiet) {
+          fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+          fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_name);
+          fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' requires a string.");
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+        }
+
+        iki_read_delete_data(data);
+        return F_status_set_error(F_parameter);
+      }
+
+      if (data->parameters[iki_read_parameter_substitute].result != f_console_result_none) {
+        if (data->parameters[iki_read_parameter_substitute].result == f_console_result_found || data->parameters[iki_read_parameter_substitute].additional.used % 3 != 0) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The parameter '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_substitute);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' requires 3 strings.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+      }
+
+      if (data->parameters[iki_read_parameter_literal].result == f_console_result_found) {
+        if (data->parameters[iki_read_parameter_object].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_literal);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_object);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        if (data->parameters[iki_read_parameter_raw].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_literal);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_raw);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        if (data->parameters[iki_read_parameter_total].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_literal);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_total);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        data->mode = iki_read_mode_literal;
+      }
+      else if (data->parameters[iki_read_parameter_object].result == f_console_result_found) {
+        if (data->parameters[iki_read_parameter_raw].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_object);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_raw);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        if (data->parameters[iki_read_parameter_total].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_object);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_total);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        data->mode = iki_read_mode_object;
+      }
+      else if (data->parameters[iki_read_parameter_raw].result == f_console_result_found) {
+        if (data->parameters[iki_read_parameter_total].result == f_console_result_found) {
+          if (data->verbosity != iki_read_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: Cannot specify the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_raw);
+            fl_color_print(f_type_error, data->context.error, data->context.reset, "' parameter with the '");
+            fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_total);
+            fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' parameter.");
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+          }
+
+          iki_read_delete_data(data);
+          return F_status_set_error(F_parameter);
+        }
+
+        data->mode = iki_read_mode_raw;
+      }
+      else if (data->parameters[iki_read_parameter_total].result == f_console_result_found) {
+        data->mode = iki_read_mode_total;
+      }
+      else {
+        data->mode = iki_read_mode_content;
+      }
+
+      if (data->process_pipe) {
+        f_file file = f_file_initialize;
+
+        file.id = f_type_descriptor_input;
+
+        status = f_file_read(file, &data->buffer);
+
+        if (F_status_is_error(status)) {
+          iki_read_print_error_file(data->context, data->verbosity, F_status_set_fine(status), "f_file_read", "-", "process", F_true, F_true);
+
+          iki_read_delete_data(data);
+          return status;
+        }
+
+        status = iki_read_main_process_file(arguments, "-", data);
+        if (F_status_is_error(status)) {
+          iki_read_delete_data(data);
+          return status;
+        }
+
+        // Clear buffers before continuing.
+        f_macro_string_dynamic_delete_simple(data->buffer);
+      }
+
+      if (data->remaining.used > 0) {
+        f_string_length i = 0;
+        f_string_length total = 0;
+        f_file file = f_file_initialize;
+
+        for (; i < data->remaining.used; i++) {
+          f_macro_file_reset(file);
+          total = 0;
+
+          status = f_file_open(arguments.argv[data->remaining.array[i]], 0, &file);
+          if (F_status_is_error(status)) {
+            iki_read_print_error_file(data->context, data->verbosity, F_status_set_fine(status), "f_file_open", arguments.argv[data->remaining.array[i]], "process", F_true, F_true);
+
+            iki_read_delete_data(data);
+            return status;
+          }
+
+          status = f_file_size_by_id(file.id, &total);
+          if (F_status_is_error(status)) {
+            iki_read_print_error_file(data->context, data->verbosity, F_status_set_fine(status), "f_file_size_by_id", arguments.argv[data->remaining.array[i]], "process", F_true, F_true);
+
+            f_file_close(&file.id);
+
+            iki_read_delete_data(data);
+            return status;
+          }
+
+          // Skip past empty files.
+          if (total == 0) {
+            f_file_close(&file.id);
+            continue;
+          }
+
+          status = f_file_read_until(file, &data->buffer, total);
+
+          f_file_close(&file.id);
+
+          if (F_status_is_error(status)) {
+            iki_read_print_error_file(data->context, data->verbosity, F_status_set_fine(status), "f_file_read_until", arguments.argv[data->remaining.array[i]], "process", F_true, F_true);
+
+            iki_read_delete_data(data);
+            return status;
+          }
+
+          status = iki_read_main_process_file(arguments, arguments.argv[data->remaining.array[i]], data);
+          if (F_status_is_error(status)) {
+            iki_read_delete_data(data);
+            return status;
+          }
+
+          // Clear buffers before repeating the loop.
+          f_macro_string_dynamic_delete_simple(data->buffer);
+        } // for
+      }
+    }
+    else {
+      if (data->verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print_line(f_type_error, data->context.error, data->context.reset, "ERROR: you failed to specify one or more files.");
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+      }
+
+      status = F_status_set_error(F_parameter);
+    }
+
+    iki_read_delete_data(data);
+    return status;
+  }
+#endif // _di_iki_read_main_
+
+#ifndef _di_iki_read_delete_data_
+  f_return_status iki_read_delete_data(iki_read_data *data) {
+    f_status status = F_none;
+    f_string_length i = 0;
+
+    while (i < iki_read_total_parameters) {
+      f_macro_string_lengths_delete_simple(data->parameters[i].locations);
+      f_macro_string_lengths_delete_simple(data->parameters[i].additional);
+      i++;
+    } // while
+
+    f_macro_string_lengths_delete_simple(data->remaining);
+    f_macro_string_dynamic_delete_simple(data->buffer);
+    fl_macro_color_context_delete_simple(data->context);
+
+    return F_none;
+  }
+#endif // _di_iki_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_read/c/iki_read.h b/level_3/iki_read/c/iki_read.h
new file mode 100644 (file)
index 0000000..2cc6434
--- /dev/null
@@ -0,0 +1,330 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: IKI
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This is the FSS Basic 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 iki_read_data.
+ *
+ * This processes in accordance to the FSS-0000 Basic specification.
+ */
+#ifndef _iki_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/string.h>
+#include <level_0/console.h>
+#include <level_0/conversion.h>
+#include <level_0/file.h>
+#include <level_0/iki.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/iki.h>
+#include <level_1/print.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/file.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_read_version_
+  #define iki_read_major_version "0"
+  #define iki_read_minor_version "5"
+  #define iki_read_micro_version "0"
+  #define iki_read_version iki_read_major_version "." iki_read_minor_version "." iki_read_micro_version
+#endif // _di_iki_read_version_
+
+#ifndef _di_iki_read_name_
+  #define iki_read_name      "IKI_read"
+  #define iki_read_name_long "IKI Read"
+#endif // _di_iki_read_name_
+
+#ifndef _di_iki_read_defines_
+  enum {
+    iki_read_mode_content = 1,
+    iki_read_mode_literal,
+    iki_read_mode_object,
+    iki_read_mode_raw,
+    iki_read_mode_total,
+  };
+
+  enum {
+    iki_read_verbosity_quiet = 1,
+    iki_read_verbosity_normal,
+    iki_read_verbosity_verbose,
+    iki_read_verbosity_debug,
+  };
+
+  #define iki_read_short_at         "a"
+  #define iki_read_short_expand     "e"
+  #define iki_read_short_line       "l"
+  #define iki_read_short_literal    "L"
+  #define iki_read_short_name       "n"
+  #define iki_read_short_object     "o"
+  #define iki_read_short_raw        "r"
+  #define iki_read_short_substitute "s"
+  #define iki_read_short_total      "t"
+
+  #define iki_read_long_at         "at"
+  #define iki_read_long_expand     "expand"
+  #define iki_read_long_line       "line"
+  #define iki_read_long_literal    "literal"
+  #define iki_read_long_name       "name"
+  #define iki_read_long_object     "object"
+  #define iki_read_long_raw        "raw"
+  #define iki_read_long_substitute "substitute"
+  #define iki_read_long_total      "total"
+
+  enum {
+    iki_read_parameter_help,
+    iki_read_parameter_light,
+    iki_read_parameter_dark,
+    iki_read_parameter_no_color,
+    iki_read_parameter_quiet,
+    iki_read_parameter_verbose,
+    iki_read_parameter_version,
+
+    iki_read_parameter_at,
+    iki_read_parameter_expand,
+    iki_read_parameter_line,
+    iki_read_parameter_literal,
+    iki_read_parameter_name,
+    iki_read_parameter_object,
+    iki_read_parameter_raw,
+    iki_read_parameter_substitute,
+    iki_read_parameter_total,
+  };
+
+  #define f_console_parameter_initialize_iki_read \
+    { \
+      f_console_parameter_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+      f_console_parameter_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+      f_console_parameter_initialize(iki_read_short_at, iki_read_long_at, 0, 1, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_expand, iki_read_long_expand, 0, 0, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_line, iki_read_long_line, 0, 1, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_literal, iki_read_long_literal, 0, 0, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_name, iki_read_long_name, 0, 1, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_object, iki_read_long_object, 0, 0, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_raw, iki_read_long_raw, 0, 0, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_substitute, iki_read_long_substitute, 0, 3, f_console_type_normal), \
+      f_console_parameter_initialize(iki_read_short_total, iki_read_long_total, 0, 0, f_console_type_normal), \
+    }
+
+  #define iki_read_total_parameters 16
+#endif // _di_iki_read_defines_
+
+#ifndef _di_iki_read_replacement_
+  #define iki_read_replacement_vocabulary "vocabulary"
+  #define iki_read_replacement_replace    "replace"
+  #define iki_read_replacement_with       "with"
+
+  typedef struct {
+    f_string_dynamic vocabulary;
+    f_string_dynamic replace;
+    f_string_dynamic with;
+  } iki_read_replacement;
+
+  #define iki_read_replacement_initialize \
+    { \
+      f_string_dynamic_initialize, \
+      f_string_dynamic_initialize, \
+      f_string_dynamic_initialize, \
+    }
+
+  #define macro_iki_read_replacement_delete_simple(replacement) \
+    f_macro_string_dynamic_delete_simple(replacement.vocabulary); \
+    f_macro_string_dynamic_delete_simple(replacement.replace); \
+    f_macro_string_dynamic_delete_simple(replacement.with);
+
+  #define macro_iki_read_replacement_destroy_simple(replacement) \
+    f_macro_string_dynamic_destroy_simple(replacement.vocabulary); \
+    f_macro_string_dynamic_destroy_simple(replacement.replace); \
+    f_macro_string_dynamic_destroy_simple(replacement.with);
+#endif // _di_iki_read_replacement_
+
+#ifndef _di_iki_read_replacements_
+  typedef struct {
+    iki_read_replacement *array;
+
+    f_array_length size;
+    f_array_length used;
+  } iki_read_replacements;
+
+  #define iki_read_replacements_initialize {0, 0, 0}
+
+  #define macro_iki_read_replacements_clear(replacements) f_macro_memory_structure_clear(replacements)
+
+  #define macro_iki_read_replacements_new(status, replacements, length) f_macro_memory_structure_new(status, replacements, iki_read_replacement, length)
+
+  #define macro_iki_read_replacements_delete_simple(replacements) \
+    replacements.used = replacements.size; \
+    while (replacements.used > 0) { \
+      replacements.used--; \
+      macro_iki_read_replacement_delete_simple(replacements.array[replacements.used]); \
+    } \
+    if (replacements.used == 0) f_macro_memory_structure_delete_simple(replacements, iki_read_replacement)
+
+  #define macro_iki_read_replacements_destroy_simple(replacements) \
+    replacements.used = replacements.size; \
+    while (replacements.used > 0) { \
+      replacements.used--; \
+      macro_iki_read_replacement_destroy_simple(replacements.array[replacements.used]); \
+    } \
+    if (replacements.used == 0) f_macro_memory_structure_destroy_simple(replacements, iki_read_replacement)
+
+  #define macro_iki_read_replacements_resize(status, replacements, new_length) \
+    status = F_none; \
+    if (new_length < replacements.size) { \
+      f_array_length i = replacements.size - new_length; \
+      for (; i < replacements.size; i++) { \
+        macro_iki_read_replacement_delete(status, replacements.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_resize((void **) & replacements.array, sizeof(iki_read_replacement), replacements.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > replacements.size) { \
+        f_array_length i = replacements.size; \
+        for (; i < new_length; i++) { \
+          memset(&replacements.array[i], 0, sizeof(iki_read_replacement)); \
+        } \
+      } \
+      replacements.size = new_length; \
+      if (replacements.used > replacements.size) replacements.used = new_length; \
+    }
+
+  #define macro_iki_read_replacements_adjust(status, replacements, new_length) \
+    status = F_none; \
+    if (new_length < replacements.size) { \
+      f_array_length i = replacements.size - new_length; \
+      for (; i < replacements.size; i++) { \
+        macro_iki_read_replacement_delete(status, replacements.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_adjust((void **) & replacements.array, sizeof(iki_read_replacement), replacements.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > replacements.size) { \
+        f_array_length i = replacements.size; \
+        for (; i < new_length; i++) { \
+          memset(&replacements.array[i], 0, sizeof(iki_read_replacement)); \
+        } \
+      } \
+      replacements.size = new_length; \
+      if (replacements.used > replacements.size) replacements.used = new_length; \
+    }
+#endif // _di_iki_read_replacements_
+
+#ifndef _di_iki_read_data_
+  typedef struct {
+    f_console_parameter parameters[iki_read_total_parameters];
+
+    f_string_lengths remaining;
+    bool process_pipe;
+
+    f_number_unsigned line;
+
+    uint8_t mode;
+    uint8_t verbosity;
+
+    f_string_dynamic buffer;
+
+    iki_read_replacements replacements;
+
+    fl_color_context context;
+  } iki_read_data;
+
+  #define iki_read_data_initialize \
+    { \
+      f_console_parameter_initialize_iki_read, \
+      f_string_lengths_initialize, \
+      F_false, \
+      0, \
+      0, \
+      0, \
+      f_string_dynamic_initialize, \
+      iki_read_replacements_initialize, \
+      fl_color_context_initialize, \
+    }
+#endif // _di_iki_read_data_
+
+/**
+ * Print help to standard output.
+ *
+ * @param context
+ *   The color context settings.
+ *
+ * @return
+ *   F_none on success.
+ */
+#ifndef _di_iki_read_print_help_
+  extern f_return_status iki_read_print_help(const fl_color_context context);
+#endif // _di_iki_read_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call iki_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 iki_read_delete_data()
+ */
+#ifndef _di_iki_read_main_
+  extern f_return_status iki_read_main(const f_console_arguments arguments, iki_read_data *data);
+#endif // _di_iki_read_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing iki_read_main().
+ *
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see iki_read_main()
+ */
+#ifndef _di_iki_read_delete_data_
+  extern f_return_status iki_read_delete_data(iki_read_data *data);
+#endif // _di_iki_read_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _iki_read_h
diff --git a/level_3/iki_read/c/main.c b/level_3/iki_read/c/main.c
new file mode 100644 (file)
index 0000000..5d682de
--- /dev/null
@@ -0,0 +1,18 @@
+#include <level_3/iki_read.h>
+
+int main(const unsigned long argc, const f_string *argv) {
+  const f_console_arguments arguments = { argc, argv };
+  iki_read_data data = iki_read_data_initialize;
+
+  if (f_pipe_input_exists()) {
+    data.process_pipe = F_true;
+  }
+
+  f_status status = iki_read_main(arguments, &data);
+
+  if (F_status_is_error(status)) {
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/level_3/iki_read/c/private-iki_read.c b/level_3/iki_read/c/private-iki_read.c
new file mode 100644 (file)
index 0000000..c284af5
--- /dev/null
@@ -0,0 +1,298 @@
+#include <level_3/iki_read.h>
+#include "private-iki_read.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_iki_read_print_error_
+  f_return_status iki_read_print_error(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const bool fallback) {
+
+    if (status == F_parameter) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Invalid parameter when calling function ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+        fl_color_print_line(f_type_error, context.error, context.reset, "().");
+      }
+
+      return F_none;
+    }
+
+    if (status == F_memory_allocation || status == F_memory_reallocation) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Unable to allocate memory in function ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+        fl_color_print_line(f_type_error, context.error, context.reset, "().");
+      }
+
+      return F_none;
+    }
+
+    if (fallback && verbosity != iki_read_verbosity_quiet) {
+      fprintf(f_type_error, "%c", f_string_eol[0]);
+      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
+      fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
+      fl_color_print(f_type_error, context.error, context.reset, ") in function ");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+      fl_color_print_line(f_type_error, context.error, context.reset, "().");
+    }
+
+    return F_unknown;
+  }
+#endif // _di_iki_read_print_error_
+
+#ifndef _di_iki_read_print_error_file_
+  bool iki_read_print_error_file(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string name, const f_string operation, const bool is_file, const bool fallback) {
+    const f_string file_or_directory = is_file ? "file" : "directory";
+
+    if (status == F_file_found_not) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: failed to find %s '", file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_file_found) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: the %s '", file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "' already exists.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_parameter) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+        fl_color_print(f_type_error, context.error, context.reset, "() for the %s '", file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_name) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Invalid %s name '", file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_memory_out) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "CRITICAL ERROR: Unable to allocate memory, while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_number_overflow) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Overflow while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_directory) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Invalid directory while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_access_denied) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Access denied while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_loop) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Loop while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_prohibited) {
+      if (verbosity != iki_read_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: Prohibited by system while trying to %s %s '", operation, file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (is_file) {
+      if (status == F_directory_found_not) {
+        if (verbosity != iki_read_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, context.error, context.reset, "ERROR: failed to %s %s '", operation, file_or_directory);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+          fl_color_print_line(f_type_error, context.error, context.reset, "' due to an invalid directory in the path.");
+        }
+
+        return F_false;
+      }
+    }
+    else {
+      if (status == F_directory_found_not) {
+        if (verbosity != iki_read_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, context.error, context.reset, "ERROR: failed to %s %s '", operation, file_or_directory);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+          fl_color_print_line(f_type_error, context.error, context.reset, "' due to an invalid directory in the path.");
+        }
+
+        return F_false;
+      }
+
+      if (status == F_failure) {
+        if (verbosity != iki_read_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, context.error, context.reset, "ERROR: failed to %s %s '", operation, file_or_directory);
+          fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+          fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+        }
+
+        return F_false;
+      }
+    }
+
+    if (iki_read_print_error(context, verbosity, status, function, F_false) == F_unknown && fallback && verbosity != iki_read_verbosity_quiet) {
+      fprintf(f_type_error, "%c", f_string_eol[0]);
+      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
+      fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
+      fl_color_print(f_type_error, context.error, context.reset, ") occurred while trying to %s %s '", operation, file_or_directory);
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+
+    return F_true;
+  }
+#endif // _di_iki_read_print_error_file_
+
+#ifndef _di_iki_read_print_error_number_argument_
+  void iki_read_print_error_number_argument(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string parameter, const f_string argument) {
+    if (verbosity == iki_read_verbosity_quiet) return;
+
+    fprintf(f_type_error, "%c", f_string_eol[0]);
+
+    if (status == F_parameter) {
+      fl_color_print(f_type_error, context.error, context.reset, "INTERNAL ERROR: Invalid parameter when calling ");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s()", function);
+      fl_color_print_line(f_type_error, context.error, context.reset, ".");
+    }
+    else if (status == F_number) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The argument '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print(f_type_error, context.error, context.reset, "' is not a valid number for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+    else if (status == F_number_underflow) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The argument '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print(f_type_error, context.error, context.reset, "' is too small for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+    else if (status == F_number_overflow) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The argument '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print(f_type_error, context.error, context.reset, "' is too large for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+    else if (status == F_number_negative) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The argument '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print(f_type_error, context.error, context.reset, "' is negative, which is not allowed for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+    else if (status == F_number_positive) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The argument '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print(f_type_error, context.error, context.reset, "' contains a '");
+      fl_color_print(f_type_error, context.notable, context.reset, "+");
+      fl_color_print(f_type_error, context.error, context.reset, "', which is not allowed for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+    else if (status == F_data_not) {
+      fl_color_print(f_type_error, context.error, context.reset, "ERROR: The parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print_line(f_type_error, context.error, context.reset, "' must not be an empty string.");
+    }
+    else {
+      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
+      fl_color_print(f_type_error, context.notable, context.reset, "%llu", status);
+      fl_color_print(f_type_error, context.error, context.reset, ") has occurred while calling ");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s()", function);
+      fl_color_print(f_type_error, context.error, context.reset, "' for the parameter '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+      fl_color_print(f_type_error, context.error, context.reset, "' with the value '");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", argument);
+      fl_color_print_line(f_type_error, context.error, context.reset, "'.");
+    }
+  }
+#endif // _di_iki_read_print_error_number_argument_
+
+#ifndef _di_iki_read_main_process_file_
+  f_return_status iki_read_main_process_file(const f_console_arguments arguments, const f_string filename, iki_read_data *data) {
+    f_status status = F_none;
+
+    f_iki_variable variable = f_iki_variable_initialize;
+    f_iki_vocabulary vocabulary = f_iki_vocabulary_initialize;
+    f_iki_content content = f_iki_content_initialize;
+
+    // @todo
+
+    f_macro_iki_variable_delete_simple(variable);
+    f_macro_iki_vocabulary_delete_simple(vocabulary);
+    f_macro_iki_content_delete_simple(content);
+
+    return F_none;
+  }
+#endif // _di_iki_read_main_process_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/iki_read/c/private-iki_read.h b/level_3/iki_read/c/private-iki_read.h
new file mode 100644 (file)
index 0000000..9679c91
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_iki_read_h
+#define _PRIVATE_iki_read_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print generic error messages.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The status code representing an error.
+ * @param function
+ *   The name of the function where the error happened.
+ * @param fallback
+ *   Set to F_true to print the fallback error message for unknown errors.
+ *
+ * @return
+ *   F_none is returned on successful print of known errors.
+ *   F_unknown is returned if the status code has no print message.
+ */
+#ifndef _di_iki_read_print_error_
+  extern f_return_status iki_read_print_error(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const bool fallback) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_print_error_
+
+/**
+ * Print file/directory error messages.
+ *
+ * @todo the fll_file_error_print() needs to be reviewed and possibly changed.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The error status code to report on.
+ * @param function
+ *   The function call that returned the error.
+ * @param name
+ *   The name of the file or directory.
+ * @param operation
+ *   The operation that fails, such as 'create' or 'access'.
+ * @param is_file
+ *   Set to TRUE if this is a file and FALSE if this is a directory.
+ * @param fallback
+ *   Set to F_true to print the fallback error message for unknown errors.
+ *
+ * @return
+ *   F_true is returned if the status code has no print message.
+ *   F_false is returned on successful print of known errors.
+ */
+#ifndef _di_iki_read_print_error_file_
+  extern bool iki_read_print_error_file(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string name, const f_string operation, const bool is_file, const bool fallback) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_print_error_file_
+
+/**
+ * Print number argument errors.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The error status code to report on.
+ * @param function
+ *   The function call that returned the error.
+ * @param parameter
+ *   The parameter name.
+ * @param argument
+ *   The argument value.
+ *
+ * @return
+ *   F_true is returned if the status code has no print message.
+ *   F_false is returned on successful print of known errors.
+ */
+#ifndef _di_iki_read_print_error_number_argument_
+  extern void iki_read_print_error_number_argument(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string parameter, const f_string argument) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_print_error_number_argument_
+
+/**
+ * Process a given file.
+ *
+ * @param arguments
+ *   The console arguments passed to the program.
+ * @param file_name
+ *   The name of the file being processed.
+ * @param data
+ *   The program specific data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_iki_read_main_process_file_
+  extern f_return_status iki_read_main_process_file(const f_console_arguments arguments, const f_string file_name, iki_read_data *data) f_gcc_attribute_visibility_internal;
+#endif // _di_iki_read_main_process_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_iki_read_h
diff --git a/level_3/iki_read/data/build/defines b/level_3/iki_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/iki_read/data/build/dependencies b/level_3/iki_read/data/build/dependencies
new file mode 100644 (file)
index 0000000..7de6d34
--- /dev/null
@@ -0,0 +1,19 @@
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_conversion
+f_file
+f_iki
+f_pipe
+f_print
+fl_color
+fl_console
+fl_iki
+fl_string
+fl_utf
+fll_file
+fll_program
diff --git a/level_3/iki_read/data/build/settings b/level_3/iki_read/data/build/settings
new file mode 100644 (file)
index 0000000..9599f41
--- /dev/null
@@ -0,0 +1,54 @@
+# fss-0001
+
+project_name iki_read
+
+version_major 0
+version_minor 5
+version_micro 0
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default individual
+
+build_compiler gcc
+build_language c
+build_linker ar
+build_libraries -lc
+build_libraries-individual -lfll_program -lfll_file -lfl_string -lfl_status -lfl_print -lfl_iki -lfl_fss -lfl_console -lfl_color -lf_print -lf_pipe -lf_path -lf_iki -lf_fss -lf_file -lf_environment -lf_conversion -lf_console -lf_utf -lf_memory
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library iki_read.c private-iki_read.c
+build_sources_program main.c
+build_sources_headers iki_read.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE