From f75ee5607f5b6d5480938e999f2c76d19a8336d7 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 28 Jun 2020 19:09:25 -0500 Subject: [PATCH] Update: finish implementing IKI Read program. The resulting design made --expand redundant, so it is removed. Substitution is implemented and works independent of the --name parameter. Added a new macro to the FLL project called f_macro_memory_structure_macro_increment(). Too often do I have to create those structures, so here is a macro to perform the increment. I started to update the rest of the project and then decided not to spend time on that right now. This, therefore, primarily focuses on getting the macro working in IKI. IKI Read is now considered usable, except for the UTF-8 support. The UTF-8 support is dependent on updating a ton of UTF-8 codes. This will be done at a later time. The IKI Read program will eventually need to be reviewed for mistakes and cleanups. --- level_0/f_console/c/console.c | 3 +- level_0/f_console/c/console.h | 1 + level_0/f_directory/c/directory.c | 2 +- level_0/f_directory/c/directory.h | 1 + level_0/f_memory/c/memory-structure.h | 33 ++++ level_0/f_path/c/path.c | 128 ++---------- level_0/f_serialize/c/serialize.c | 12 +- level_0/f_serialize/c/serialize.h | 2 + level_1/fl_directory/c/private-directory.c | 32 +-- level_1/fl_directory/c/private-directory.h | 1 + level_2/fll_program/c/program.c | 6 +- level_2/fll_program/c/program.h | 1 + level_3/iki_read/c/iki_read.c | 36 +--- level_3/iki_read/c/iki_read.h | 63 +++--- level_3/iki_read/c/private-iki_read.c | 300 ++++++++++++++++++++++------- level_3/iki_read/c/private-iki_read.h | 46 +++++ 16 files changed, 378 insertions(+), 289 deletions(-) diff --git a/level_0/f_console/c/console.c b/level_0/f_console/c/console.c index 58e054c..0ac63da 100644 --- a/level_0/f_console/c/console.c +++ b/level_0/f_console/c/console.c @@ -286,8 +286,7 @@ extern "C" { if (!found) { // populate list of remaining parameters.parameter not associated with anything. if (remaining->used >= remaining->size) { - f_macro_string_lengths_resize(status, (*remaining), remaining->size + f_console_default_allocation_step); - + f_macro_memory_structure_macro_increment(status, (*remaining), 1, f_console_default_allocation_step, f_macro_string_lengths_resize, F_buffer_too_large); if (F_status_is_error(status)) { f_macro_string_lengths_delete_simple(needs_additional); return status; diff --git a/level_0/f_console/c/console.h b/level_0/f_console/c/console.h index 62129f7..1d151ba 100644 --- a/level_0/f_console/c/console.h +++ b/level_0/f_console/c/console.h @@ -327,6 +327,7 @@ extern "C" { * @return * F_none on success. * F_data_not if "additional" parameters were expected but not found. + * F_buffer_too_large (with error bit) if a buffer would exceed max length. * F_failure (with error bit) if width is not long enough to convert when processing arguments as UTF-8. * F_parameter (with error bit) if a parameter is invalid. * F_utf (with error bit) if character is an invalid UTF-8 character, when processing arguments. diff --git a/level_0/f_directory/c/directory.c b/level_0/f_directory/c/directory.c index 5a10089..b37bf20 100644 --- a/level_0/f_directory/c/directory.c +++ b/level_0/f_directory/c/directory.c @@ -191,7 +191,7 @@ extern "C" { } if (names->used >= names->size) { - f_macro_string_dynamics_resize(status, (*names), names->size + f_directory_default_allocation_step); + f_macro_memory_structure_macro_increment(status, (*names), 1, f_directory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); if (F_status_is_error(status)) break; } diff --git a/level_0/f_directory/c/directory.h b/level_0/f_directory/c/directory.h index 493300f..f66ff92 100644 --- a/level_0/f_directory/c/directory.h +++ b/level_0/f_directory/c/directory.h @@ -284,6 +284,7 @@ extern "C" { * @return * F_none on success. * F_data_not if directory is empty. + * F_buffer_too_large (with error bit) if the directory buffer max length would be exceeded. * F_failure (with error bit) if failed to read directory information. * F_memory_reallocation (with error bit) on memory reallocation error. * F_parameter (with error bit) if a parameter is invalid. diff --git a/level_0/f_memory/c/memory-structure.h b/level_0/f_memory/c/memory-structure.h index d8a583f..e330133 100644 --- a/level_0/f_memory/c/memory-structure.h +++ b/level_0/f_memory/c/memory-structure.h @@ -328,6 +328,39 @@ extern "C" { } #endif // _di_f_macro_memory_structures_adjust_ +/** + * Provide a macro for calling other macros for incrementing a buffer. + * + * If the used + step is greater than size, then increase by step_default. + * If step_default exceeds f_array_length_size, then attempt to increment by step. + * If step exceeds f_array_length_size, set status to error_too_large. + * + * Be sure to check size for error after calling this. + * + * status: the status to return. + * structures: the structures to operate on. + * step: the step to increase by, must be less than or equal to step_default. + * step_default: the default step to increase by if memory allows. + * macro_resize: the resize structure macro to call that excepts the exact arguments: (status, structure, new_length). + * error_too_large: the error status to return when f_array_length_size would be exceeded. + */ +#ifndef _di_f_macro_memory_structure_macro_increment_ + #define f_macro_memory_structure_macro_increment(status, structure, step, step_default, macro_resize, error_too_large) \ + if (structure.used + step > structure.size) { \ + if (structure.used + step_default > f_array_length_size) { \ + if (structure.used + step > structure.size > f_array_length_size) { \ + status = F_status_set_error(error_too_large); \ + } \ + else { \ + macro_resize(status, structure, structure.size + step); \ + } \ + } \ + else { \ + macro_resize(status, structure, structure.size + step_default); \ + } \ + } +#endif // _di_f_macro_memory_structure_macro_increment_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_path/c/path.c b/level_0/f_path/c/path.c index 3ec5dec..634e3b4 100644 --- a/level_0/f_path/c/path.c +++ b/level_0/f_path/c/path.c @@ -17,20 +17,8 @@ extern "C" { if (length == 0) { // When PATH is "", this is actually a valid search path for PWD. // Therefore append an equivalent representation of PWD (string used length is 0). - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; f_macro_string_dynamic_clear(paths->array[paths->used]); paths->used++; @@ -44,20 +32,8 @@ extern "C" { for (i = 0; i <= length; i++) { if (i == length || path[i] == f_path_separator_variable[0]) { - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (i == 0) { f_macro_string_dynamic_clear(paths->array[paths->used]); @@ -115,20 +91,8 @@ extern "C" { if (path.used == 0) { // When PATH is "", this is actually a valid search path for PWD. // Therefore append an equivalent representation of PWD (string used length is 0). - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; f_macro_string_dynamic_clear(paths->array[paths->used]); paths->used++; @@ -145,20 +109,8 @@ extern "C" { for (i = 0; i <= path.used; i++) { if (i == path.used || path.string[i] == f_path_separator_variable[0]) { - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (i == 0) { f_macro_string_dynamic_clear(paths->array[paths->used]); @@ -216,20 +168,8 @@ extern "C" { if (length == 0) { // When PATH is "", this is actually a valid search path for PWD. // Therefore append an equivalent representation of PWD (string used length is 0). - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; paths->array[paths->used].string = 0; paths->array[paths->used].used = 0; @@ -250,20 +190,8 @@ extern "C" { j--; if (j == 0 || path[j] == f_path_separator_variable[0]) { - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (path[j] == f_path_separator_variable[0]) { total = last - i; @@ -335,20 +263,8 @@ extern "C" { if (path.used == 0) { // When PATH is "", this is actually a valid search path for PWD. // Therefore append an equivalent representation of PWD (string used length is 0). - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; f_macro_string_dynamic_clear(paths->array[paths->used]); paths->used++; @@ -368,20 +284,8 @@ extern "C" { j--; if (j == 0 || path.string[j] == f_path_separator_variable[0]) { - if (paths->used + 1 > paths->size) { - if (paths->size + f_memory_default_allocation_step > f_array_length_size) { - if (paths->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (path.string[j] == f_path_separator_variable[0]) { total = last - i; diff --git a/level_0/f_serialize/c/serialize.c b/level_0/f_serialize/c/serialize.c index 9afea81..86324bf 100644 --- a/level_0/f_serialize/c/serialize.c +++ b/level_0/f_serialize/c/serialize.c @@ -50,10 +50,8 @@ extern "C" { width = f_macro_utf_byte_width(serialize.string[i]); if (serialize.string[i] == f_serialize_simple_splitter || i + 1 >= serialize.used) { - if (strings->used >= strings->size) { - f_macro_string_dynamics_resize(status, (*strings), strings->size + f_serialize_default_allocation_step); - if (F_status_is_error(status)) return status; - } + f_macro_memory_structure_macro_increment(status, (*strings), 1, f_serialize_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (start == i) { strings->array[strings->used].used = 0; @@ -118,10 +116,8 @@ extern "C" { width = f_macro_utf_byte_width(serialize.string[i]); if (serialize.string[i] == f_serialize_simple_splitter || i + 1 >= serialize.used) { - if (locations->used >= locations->size) { - f_macro_string_ranges_resize(status, (*locations), locations->size + f_serialize_default_allocation_step); - if (F_status_is_error(status)) return status; - } + f_macro_memory_structure_macro_increment(status, (*locations), 1, f_serialize_default_allocation_step, f_macro_string_ranges_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; if (start == i) { // provide an invalid start to stop range to communicate that there is no data. diff --git a/level_0/f_serialize/c/serialize.h b/level_0/f_serialize/c/serialize.h index 959f649..1012cb1 100644 --- a/level_0/f_serialize/c/serialize.h +++ b/level_0/f_serialize/c/serialize.h @@ -83,6 +83,7 @@ extern "C" { * @return * F_none on success. * F_incomplete_utf_eos if end of sting is reached before a complete UTF-8 character can be processed. + * F_buffer_too_large (with error bit) if a buffer would exceed maximum length. * F_memory_reallocation (with error bit) on memory reallocation error. * F_parameter (with error bit) if a parameter is invalid. */ @@ -108,6 +109,7 @@ extern "C" { * @return * F_none on success. * F_incomplete_utf_eos if end of sting is reached before a complete UTF-8 character can be processed. + * F_buffer_too_large (with error bit) if a buffer would exceed memory max length. * F_memory_reallocation (with error bit) on memory reallocation error. * F_parameter (with error bit) if a parameter is invalid. */ diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index c70276d..5959657 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -165,20 +165,8 @@ extern "C" { const f_status status_failure = status; - if (failures->used + 1 > failures->size) { - if (failures->size + f_memory_default_allocation_step > f_array_length_size) { - if (failures->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_directory_statuss_resize(status, (*failures), failures->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_directory_statuss_resize(status, (*failures), failures->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; f_directory_status failure = f_directory_status_initialize; f_string_length size = 0; @@ -387,20 +375,8 @@ extern "C" { const f_status status_failure = status; - if (failures->used + 1 > failures->size) { - if (failures->size + f_memory_default_allocation_step > f_array_length_size) { - if (failures->size + 1 > f_array_length_size) { - return F_status_set_error(F_buffer_too_large); - } - - f_macro_directory_statuss_resize(status, (*failures), failures->used + 1); - if (F_status_is_error(status)) return status; - } - else { - f_macro_directory_statuss_resize(status, (*failures), failures->used + f_memory_default_allocation_step); - if (F_status_is_error(status)) return status; - } - } + f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; f_directory_status failure = f_directory_status_initialize; f_string_length size = 0; diff --git a/level_1/fl_directory/c/private-directory.h b/level_1/fl_directory/c/private-directory.h index 529928a..003a234 100644 --- a/level_1/fl_directory/c/private-directory.h +++ b/level_1/fl_directory/c/private-directory.h @@ -96,6 +96,7 @@ extern "C" { * @return * F_none on success. * F_data_not if directory is empty. + * F_buffer_too_large (with error bit) if a buffer would exceed max length. * F_directory_descriptor (with error bit) on directory file descriptor error. * F_directory_open (with error bit) on directory open error. * F_directory_stream (with error bit) on directory stream error. diff --git a/level_2/fll_program/c/program.c b/level_2/fll_program/c/program.c index deeed71..ce2fa61 100644 --- a/level_2/fll_program/c/program.c +++ b/level_2/fll_program/c/program.c @@ -271,10 +271,8 @@ extern "C" { status = F_none; } else { - if (destination->used >= destination->size) { - f_macro_string_dynamics_resize(status, (*destination), destination->size + f_console_default_allocation_step); - if (F_status_is_error(status)) return status; - } + f_macro_memory_structure_macro_increment(status, (*destination), 1, f_console_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) break; destination->array[destination->used] = ripped; destination->used++; diff --git a/level_2/fll_program/c/program.h b/level_2/fll_program/c/program.h index 226f129..4afe1cb 100644 --- a/level_2/fll_program/c/program.h +++ b/level_2/fll_program/c/program.h @@ -246,6 +246,7 @@ extern "C" { * @return * F_none on success. * F_data_not if nothing to rip, no allocations or reallocations are performed. + * F_buffer_too_large (with error bit) if a buffer would exceed max length. * F_memory_allocation (with error bit) on memory allocation error. * F_memory_reallocation (with error bit) on memory reallocation error. * F_parameter (with error bit) if a parameter is invalid. diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c index 6d8fbe0..ee6decc 100644 --- a/level_3/iki_read/c/iki_read.c +++ b/level_3/iki_read/c/iki_read.c @@ -33,7 +33,6 @@ extern "C" { 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 variables into their respective content."); fll_program_print_help_usage(context, iki_read_name, "filename(s)"); @@ -50,25 +49,25 @@ extern "C" { printf(" option, requires 3 additional parameters: "); fl_color_print(f_type_output, context.notable, context.reset, "<"); - printf("%s", iki_read_replacement_vocabulary); + printf("%s", iki_read_substitution_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); + printf("%s", iki_read_substitution_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); + printf("%s", iki_read_substitution_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); + fl_color_print(f_type_output, context.notable, context.reset, " %s", iki_read_substitution_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); + fl_color_print(f_type_output, context.notable, context.reset, " %s", iki_read_substitution_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); + fl_color_print(f_type_output, context.notable, context.reset, " %s", iki_read_substitution_with); printf(": The new string to use as the substitute.%c", f_string_eol[0]); printf("%c", f_string_eol[0]); @@ -77,14 +76,6 @@ extern "C" { printf("%c", f_string_eol[0]); - printf(" All substitution is applied before any expansion when both the ", f_string_eol[0]); - fl_color_print(f_type_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_substitute); - printf(" option and the "); - fl_color_print(f_type_output, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, iki_read_long_expand); - printf(" option are specified.%c", f_string_eol[0]); - - printf("%c", f_string_eol[0]); - printf(" The default behavior is to only display content portion of the IKI variable.%c", f_string_eol[0]); printf("%c", f_string_eol[0]); @@ -255,21 +246,6 @@ extern "C" { } } - if (data->parameters[iki_read_parameter_expand].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_expand); - 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."); - } - - status = 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) { diff --git a/level_3/iki_read/c/iki_read.h b/level_3/iki_read/c/iki_read.h index fdaa1e1..3b97178 100644 --- a/level_3/iki_read/c/iki_read.h +++ b/level_3/iki_read/c/iki_read.h @@ -76,7 +76,6 @@ extern "C" { }; #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" @@ -86,7 +85,6 @@ extern "C" { #define iki_read_short_whole "w" #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" @@ -105,7 +103,6 @@ extern "C" { iki_read_parameter_version, iki_read_parameter_at, - iki_read_parameter_expand, iki_read_parameter_line, iki_read_parameter_literal, iki_read_parameter_name, @@ -125,7 +122,6 @@ extern "C" { 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), \ @@ -135,64 +131,61 @@ extern "C" { f_console_parameter_initialize(iki_read_short_total, iki_read_long_total, 0, 0, f_console_type_normal), \ } - #define iki_read_total_parameters 16 + #define iki_read_total_parameters 15 #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" +#ifndef _di_iki_read_substitution_ + #define iki_read_substitution_vocabulary "vocabulary" + #define iki_read_substitution_replace "replace" + #define iki_read_substitution_with "with" typedef struct { - f_string_static vocabulary; f_string_static replace; f_string_static with; - } iki_read_replacement; + } iki_read_substitution; - #define iki_read_replacement_initialize \ + #define iki_read_substitution_initialize \ { \ f_string_static_initialize, \ f_string_static_initialize, \ - f_string_static_initialize, \ } - #define macro_iki_read_replacement_initialize(vocabulary, replace, with) \ + #define macro_iki_read_substitution_initialize(replace, with) \ { \ - f_macro_string_static_initialize(vocabulary), \ f_macro_string_static_initialize(replace), \ f_macro_string_static_initialize(with), \ } -#endif // _di_iki_read_replacement_ +#endif // _di_iki_read_substitution_ -#ifndef _di_iki_read_replacements_ +#ifndef _di_iki_read_substitutions_ typedef struct { - iki_read_replacement *array; + iki_read_substitution *array; f_array_length size; f_array_length used; - } iki_read_replacements; + } iki_read_substitutions; - #define iki_read_replacements_initialize {0, 0, 0} + #define iki_read_substitutions_initialize {0, 0, 0} - #define macro_iki_read_replacements_clear(replacements) f_macro_memory_structure_clear(replacements) + #define macro_iki_read_substitutions_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_substitutions_new(status, replacements, length) f_macro_memory_structure_new(status, replacements, iki_read_substitution, length) - #define macro_iki_read_replacements_delete_simple(replacements) \ + #define macro_iki_read_substitutions_delete_simple(replacements) \ replacements.used = replacements.size; \ while (replacements.used > 0) { \ replacements.used--; \ } \ - if (replacements.used == 0) f_macro_memory_structure_delete_simple(replacements, iki_read_replacement) + if (replacements.used == 0) f_macro_memory_structure_delete_simple(replacements, iki_read_substitution) - #define macro_iki_read_replacements_destroy_simple(replacements) \ + #define macro_iki_read_substitutions_destroy_simple(replacements) \ replacements.used = replacements.size; \ while (replacements.used > 0) { \ replacements.used--; \ } \ - if (replacements.used == 0) f_macro_memory_structure_destroy_simple(replacements, iki_read_replacement) + if (replacements.used == 0) f_macro_memory_structure_destroy_simple(replacements, iki_read_substitution) - #define macro_iki_read_replacements_resize(status, replacements, new_length) \ + #define macro_iki_read_substitutions_resize(status, replacements, new_length) \ status = F_none; \ if (new_length < replacements.size) { \ f_array_length i = replacements.size - new_length; \ @@ -200,19 +193,19 @@ extern "C" { 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) status = f_memory_resize((void **) & replacements.array, sizeof(iki_read_substitution), 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)); \ + memset(&replacements.array[i], 0, sizeof(iki_read_substitution)); \ } \ } \ replacements.size = new_length; \ if (replacements.used > replacements.size) replacements.used = new_length; \ } - #define macro_iki_read_replacements_adjust(status, replacements, new_length) \ + #define macro_iki_read_substitutions_adjust(status, replacements, new_length) \ status = F_none; \ if (new_length < replacements.size) { \ f_array_length i = replacements.size - new_length; \ @@ -220,18 +213,18 @@ extern "C" { 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) status = f_memory_adjust((void **) & replacements.array, sizeof(iki_read_substitution), 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)); \ + memset(&replacements.array[i], 0, sizeof(iki_read_substitution)); \ } \ } \ replacements.size = new_length; \ if (replacements.used > replacements.size) replacements.used = new_length; \ } -#endif // _di_iki_read_replacements_ +#endif // _di_iki_read_substitutions_ #ifndef _di_iki_read_data_ typedef struct { @@ -248,7 +241,7 @@ extern "C" { f_string_dynamic buffer; - iki_read_replacements replacements; + iki_read_substitutions replacements; fl_color_context context; } iki_read_data; @@ -263,7 +256,7 @@ extern "C" { 0, \ 0, \ f_string_dynamic_initialize, \ - iki_read_replacements_initialize, \ + iki_read_substitutions_initialize, \ fl_color_context_initialize, \ } #endif // _di_iki_read_data_ diff --git a/level_3/iki_read/c/private-iki_read.c b/level_3/iki_read/c/private-iki_read.c index 04ac184..d421093 100644 --- a/level_3/iki_read/c/private-iki_read.c +++ b/level_3/iki_read/c/private-iki_read.c @@ -402,13 +402,31 @@ extern "C" { return status; } + bool content_only = data->mode == iki_read_mode_content; + + iki_read_substitutions substitutionss[variable->used]; + + memset(substitutionss, 0, sizeof(iki_read_substitutions) * variable->used); + + if (data->mode == iki_read_mode_literal || data->mode == iki_read_mode_content) { + status = iki_read_substitutions_identify(arguments, file_name, data, vocabulary, substitutionss); + if (F_status_is_error(status)) { + iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_substitutions_identify", F_true); + + for (f_array_length i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + + return status; + } + } + if (data->parameters[iki_read_parameter_name].result == f_console_result_additional) { f_string_dynamic name = f_string_dynamic_initialize; f_array_length index = 0; f_array_length i = 0; f_array_length j = 0; - buffer_range->start = 0; for (; i < data->parameters[iki_read_parameter_name].additional.used; i++) { @@ -419,6 +437,10 @@ extern "C" { if (F_status_is_error(status)) { iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "fl_string_append_nulless", F_true); + for (f_array_length i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + f_macro_string_dynamic_delete_simple(name); return status; } @@ -431,7 +453,13 @@ extern "C" { if (status == F_equal_to) { unmatched = F_false; - f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); + if (substitutionss[j].used) { + iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, content_only); + } + else { + f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); + } + printf("%c", f_string_eol[0]); } } // for @@ -439,19 +467,36 @@ extern "C" { f_macro_string_dynamic_delete_simple(name); - if (unmatched) return F_data_not; + if (unmatched) status = F_data_not; + else status = F_none; } else if (ranges->used) { - for (f_array_length i = 0; i < ranges->used; i++) { - f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[i]); + f_array_length i = 0; + f_string_length j = 0; + + for (; i < ranges->used; i++) { + + if (substitutionss[i].used) { + iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[i], i, content_only); + } + else { + f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[i]); + } + printf("%c", f_string_eol[0]); } // for + + status = F_none; } else { - return F_data_not; + status = F_data_not; } - return F_none; + for (f_array_length i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + + return status; } #endif // _di_iki_read_process_buffer_ranges_ @@ -471,10 +516,31 @@ extern "C" { return F_none; } + iki_read_substitutions substitutionss[variable->used]; + + memset(substitutionss, 0, sizeof(iki_read_substitutions) * variable->used); + + if (data->mode == iki_read_mode_literal || data->mode == iki_read_mode_content) { + status = iki_read_substitutions_identify(arguments, file_name, data, vocabulary, substitutionss); + if (F_status_is_error(status)) { + iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_substitutions_identify", F_true); + + for (f_array_length i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + + return status; + } + } + f_string_dynamics names = f_string_dynamics_initialize; f_string_range name_range = f_string_range_initialize; + f_string_range substitution_range = f_string_range_initialize; + bool name_missed = F_true; + substitution_range.start = 0; + if (data->parameters[iki_read_parameter_name].result == f_console_result_additional) { f_array_length i = 0; f_array_length j = 0; @@ -494,97 +560,106 @@ extern "C" { } // for if (name_missed) { - if (names.used + 1 > names.size) { - if (names.used + f_iki_default_allocation_step > f_array_length_size) { - if (names.used + 1 > names.size > f_array_length_size) { - iki_read_print_error(data->context, data->verbosity, F_buffer_too_large, "iki_read_process_buffer_ranges_whole", F_true); - - f_macro_string_dynamics_delete_simple(names); - return F_status_set_error(F_buffer_too_large); - } - else { - f_macro_string_dynamics_resize(status, names, names.used + 1); - } - } - else { - f_macro_string_dynamics_resize(status, names, names.used + f_iki_default_allocation_step); - } - - if (F_status_is_error(status)) { - iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_process_buffer_ranges_whole", F_true); - - f_macro_string_dynamics_delete_simple(names); - return status; - } + f_macro_memory_structure_macro_increment(status, names, 1, f_iki_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) { + iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "iki_read_process_buffer_ranges_whole", F_true); + break; } status = fl_string_append_nulless(arguments.argv[index], length_argument, &names.array[names.used]); if (F_status_is_error(status)) { iki_read_print_error(data->context, data->verbosity, F_status_set_fine(status), "fl_string_append_nulless", F_true); - - f_macro_string_dynamics_delete_simple(names); - return status; + break; } names.used++; } } // for + + if (F_status_is_error(status)) { + for (i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + + f_macro_string_dynamics_delete_simple(names); + return status; + } } - f_string_length i = buffer_range.start; - f_array_length j = 0; - f_array_length k = 0; + { + f_string_length i = buffer_range.start; + f_array_length j = 0; + f_array_length k = 0; - range = buffer_range; - name_range.start = 0; + range = buffer_range; + name_range.start = 0; - while (i <= range.stop && j < variable->used) { - if (i < variable->array[j].start) { - range.stop = variable->array[j].start - 1; + while (i <= range.stop && j < variable->used) { + if (i < variable->array[j].start) { + range.stop = variable->array[j].start - 1; - f_print_string_dynamic_partial(f_type_output, data->buffer, range); + f_print_string_dynamic_partial(f_type_output, data->buffer, range); - range.start = variable->array[j].stop + 1; - range.stop = buffer_range.stop; + range.start = variable->array[j].stop + 1; + range.stop = buffer_range.stop; - i = variable->array[j].start; - } + i = variable->array[j].start; + } - // @todo handle expansion and substitution. - if (names.used) { - name_missed = F_true; + if (names.used) { + name_missed = F_true; - for (k = 0; k < names.used; k++) { - name_range.stop = names.array[k].used - 1; + for (k = 0; k < names.used; k++) { + name_range.stop = names.array[k].used - 1; - status = fl_string_dynamic_partial_compare(data->buffer, names.array[k], vocabulary->array[j], name_range); + status = fl_string_dynamic_partial_compare(data->buffer, names.array[k], vocabulary->array[j], name_range); - if (status == F_equal_to) { - name_missed = F_false; - break; - } - } // for + if (status == F_equal_to) { + name_missed = F_false; + break; + } + } // for - if (name_missed) { - f_print_string_dynamic_partial(f_type_output, data->buffer, variable->array[j]); + if (name_missed) { + if (substitutionss[j].used) { + iki_read_substitutions_print(*data, *variable, *content, *variable, substitutionss[j], j, F_false); + } + else { + f_print_string_dynamic_partial(f_type_output, data->buffer, variable->array[j]); + } + } + else { + if (substitutionss[j].used) { + iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, F_true); + } + else { + f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); + } + } } else { - f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); + if (substitutionss[j].used) { + iki_read_substitutions_print(*data, *variable, *content, *ranges, substitutionss[j], j, F_true); + } + else { + f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); + } } - } - else { - f_print_string_dynamic_partial(f_type_output, data->buffer, ranges->array[j]); - } - i = variable->array[j].stop + 1; - j++; - } // while + i = variable->array[j].stop + 1; + j++; + } // while - if (i <= buffer_range.stop) { - range.start = i; - f_print_string_dynamic_partial(f_type_output, data->buffer, range); + if (i <= buffer_range.stop) { + range.start = i; + f_print_string_dynamic_partial(f_type_output, data->buffer, range); + } } + for (f_array_length i = 0; i < variable->used; i++) { + macro_iki_read_substitutions_delete_simple(substitutionss[i]); + } // for + f_macro_string_dynamics_delete_simple(names); return F_none; } @@ -658,6 +733,93 @@ extern "C" { } #endif // _di_iki_read_process_buffer_total_ +#ifndef _di_iki_read_substitutions_identify_ + f_return_status iki_read_substitutions_identify(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_vocabulary *vocabulary, iki_read_substitutions *substitutionss) { + if (data->parameters[iki_read_parameter_substitute].result != f_console_result_additional) return F_none; + + f_status status = F_none; + + f_array_length i = 0; + f_array_length j = 0; + + f_array_length index = 0; + f_array_length index_2 = 0; + + f_string_length length = 0; + + f_console_parameter *parameter = &data->parameters[iki_read_parameter_substitute]; + + for (; i < parameter->additional.used; i += 3) { + index = parameter->additional.array[i]; + length = strnlen(arguments.argv[index], f_console_length_size); + + for (j = 0; j < vocabulary->used; j++) { + status = fl_string_compare(arguments.argv[index], data->buffer.string + vocabulary->array[j].start, length, (vocabulary->array[j].stop - vocabulary->array[j].start) + 1); + + if (status == F_equal_to) { + f_macro_memory_structure_macro_increment(status, substitutionss[j], 1, f_iki_default_allocation_step, macro_iki_read_substitutions_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + index = parameter->additional.array[i + 1]; + index_2 = substitutionss[j].used; + substitutionss[j].array[index_2].replace.string = arguments.argv[index]; + substitutionss[j].array[index_2].replace.used = strnlen(arguments.argv[index], f_console_length_size); + substitutionss[j].array[index_2].replace.size = substitutionss[j].array[index_2].replace.used; + + index = parameter->additional.array[i + 2]; + substitutionss[j].array[index_2].with.string = arguments.argv[index]; + substitutionss[j].array[index_2].with.used = strnlen(arguments.argv[index], f_console_length_size); + substitutionss[j].array[index_2].with.size = substitutionss[j].array[index_2].with.used; + + substitutionss[j].used++; + } + } // for + } // for + + return F_none; + } +#endif // _di_iki_read_substitutions_identify_ + +#ifndef _di_iki_read_substitutions_print_ + void iki_read_substitutions_print(const iki_read_data data, const f_iki_variable variable, const f_iki_content content, const f_string_ranges ranges, const iki_read_substitutions substitutions, const f_string_length index, const bool content_only) { + f_status status = F_none; + + f_string_length i = 0; + f_string_range range = f_string_range_initialize; + + range.start = 0; + + for (; i < substitutions.used; i++) { + range.stop = substitutions.array[i].replace.used - 1; + + status = fl_string_dynamic_partial_compare(substitutions.array[i].replace, data.buffer, range, content.array[index]); + if (status == F_equal_to) break; + } // for + + if (status == F_equal_to) { + if (content_only) { + f_print_string_dynamic(f_type_output, substitutions.array[i].with); + } + else { + range.start = variable.array[index].start; + range.stop = content.array[index].start - 1; + + f_print_string_dynamic_partial(f_type_output, data.buffer, range); + + f_print_string_dynamic(f_type_output, substitutions.array[i].with); + + range.start = content.array[index].stop + 1; + range.stop = variable.array[index].stop; + + f_print_string_dynamic_partial(f_type_output, data.buffer, range); + } + } + else { + f_print_string_dynamic_partial(f_type_output, data.buffer, ranges.array[index]); + } + } +#endif // _di_iki_read_substitutions_print_ + #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 index 437ed93..0860b8b 100644 --- a/level_3/iki_read/c/private-iki_read.h +++ b/level_3/iki_read/c/private-iki_read.h @@ -223,6 +223,52 @@ extern "C" { extern f_return_status iki_read_process_buffer_total(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_variable *variable, f_iki_vocabulary *vocabulary, f_iki_content *content) f_gcc_attribute_visibility_internal; #endif // _di_iki_read_process_buffer_total_ +/** + * Process the arguments, associating substitions with a given vocabulary. + * + * @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. + * @param vocabulary + * The ranges representing a vocabulary. + * @param substitutionss + * An array of substitutionss with each index representing an index for in the respective vocabulary array. + * + * @return + * F_none on success. + * + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_iki_read_substitutions_identify_ + extern f_return_status iki_read_substitutions_identify(const f_console_arguments arguments, const f_string file_name, iki_read_data *data, f_iki_vocabulary *vocabulary, iki_read_substitutions *substitutionss) f_gcc_attribute_visibility_internal; +#endif // _di_iki_read_substitutions_identify_ + +/** + * Print any applicable substition and if there is non then print the given range at the given index. + * + * @param data + * The program specific data. + * @param variable + * The ranges representing a variable. + * @param content + * The ranges representing a content. + * @param ranges + * The ranges containing the desired range to print as specified by index. + * @param substitutions + * The substitions associated with the variable for the given range at the given index to use for potential printing. + * @param index + * The index used to identify the desired range in variable, content, and ranges. + * @param content_only + * Set to TRUE to only print the content when printing substituted text. + * Set to FALSE to print the entire variable when printing substituted text. + */ +#ifndef _di_iki_read_substitutions_print_ + extern void iki_read_substitutions_print(const iki_read_data data, const f_iki_variable variable, const f_iki_content content, const f_string_ranges ranges, const iki_read_substitutions substitutions, const f_string_length index, const bool content_only) f_gcc_attribute_visibility_internal; +#endif // _di_iki_read_substitutions_print_ + #ifdef __cplusplus } // extern "C" #endif -- 1.8.3.1