From e938bdffa80e72cf1a680cc6047757aad78c7b75 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 22 Jun 2020 22:54:54 -0500 Subject: [PATCH] Progress: Featureless Make. Begin working on integrating IKI into Fake. I took advantage of the current code to do some testing with IKI and left some of the testing code for now. In addition to IKI, I am thinking that I need to add another project for exploding a string into separate arguments with support for escapable single and double quotes. --- level_3/fake/c/fake.h | 2 + level_3/fake/c/private-make.c | 179 ++++++++++++++++++++++++++++++++--- level_3/fake/c/private-make.h | 13 ++- level_3/fake/data/build/defines | 1 - level_3/fake/data/build/dependencies | 2 + level_3/fake/data/build/fakefile | 2 +- level_3/fake/data/build/settings | 2 +- 7 files changed, 183 insertions(+), 18 deletions(-) diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index e15b698..20390aa 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -55,12 +55,14 @@ #include #include #include +#include #include // fll-1 includes #include #include #include +#include #include // fll-2 includes diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 530791e..12637c3 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -228,7 +228,7 @@ extern "C" { fake_make_load_setting(data, &data_make, &status); - fake_make_operate_section(data, data_make, data_make.main, &list_stack, &status); + fake_make_operate_section(data, data_make.main, &data_make, &list_stack, &status); f_macro_string_lengths_delete_simple(list_stack); fake_macro_make_data_delete_simple(data_make); @@ -238,8 +238,9 @@ extern "C" { #endif // _di_fake_make_operate_ #ifndef _di_fake_make_operation_expand_ - void fake_make_operation_expand(const fake_data data, const fake_make_data data_make, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, f_string_dynamics *arguments, f_status *status) { + void fake_make_operation_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) { if (F_status_is_error(*status)) return; + if (content.used == 0) return; if (data.verbosity == fake_verbosity_verbose) { fl_color_print(f_type_output, data.context.standout, data.context.reset, "Expanding content values for section operation '"); @@ -250,21 +251,162 @@ extern "C" { fl_color_print_line(f_type_output, data.context.standout, data.context.reset, "'."); } + + // pre-allocate the known arguments size. + if (arguments->used + content.used > arguments->size) { + if (arguments->used + content.used > F_buffer_too_large) { + *status = F_status_set_error(F_buffer_too_large); + } + else { + f_macro_string_dynamics_resize((*status), (*arguments), arguments->used + content.used); + } + + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "f_macro_string_dynamics_resize", F_true); + return; + } + } + + f_iki_variable iki_variable = f_iki_variable_initialize; + f_iki_vocabulary iki_vocabulary = f_iki_vocabulary_initialize; + f_iki_content iki_content = f_iki_content_initialize; + f_string_range range = f_string_range_initialize; + + for (f_array_length i = 0; i < content.used; i++) { + if (content.array[i].start > content.array[i].stop) { + continue; + } + + range = content.array[i]; + + *status = fl_iki_read(&data_make->buffer, &range, &iki_variable, &iki_vocabulary, &iki_content); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_iki_read", F_true); + break; + } + + if (arguments->used + 1 > arguments->size) { + if (arguments->used + f_memory_default_allocation_step <= F_buffer_too_large) { + f_macro_string_dynamics_resize((*status), (*arguments), arguments->used + f_memory_default_allocation_step); + } + else if (arguments->used + 1 <= F_buffer_too_large) { + f_macro_string_dynamics_resize((*status), (*arguments), arguments->used + 1); + } + else { + *status = F_status_set_error(F_buffer_too_large); + } + + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "f_macro_string_dynamics_resize", F_true); + return; + } + } + + if (iki_variable.used) { + if (content.array[i].start < iki_variable.array[0].start) { + range.start = content.array[i].start; + range.stop = iki_variable.array[0].start - 1; + + *status = fl_string_dynamic_partial_append_nulless(data_make->buffer, range, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_partial_append_nulless", F_true); + break; + } + + *status = fl_string_append_assure(" ", 1, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true); + break; + } + } + + for (f_array_length j = 0; j < iki_variable.used; j++) { + if (j > 0) { + *status = fl_string_append_assure(" ", 1, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true); + break; + } + } + + // @todo: compare vocabulary name against known set. + // then use that value to determine how to substitute. + + // these next few blocks are just examples for testing. + *status = fl_string_append_assure("@todo:", 6, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true); + break; + } + + range.start = iki_content.array[j].start; + range.stop = iki_content.array[j].stop; + + *status = fl_string_dynamic_partial_append_nulless(data_make->buffer, range, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_partial_append_nulless", F_true); + break; + } + } // for + + if (iki_variable.array[iki_variable.used - 1].stop < content.array[i].stop) { + *status = fl_string_append_assure(" ", 1, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true); + break; + } + + range.start = iki_variable.array[iki_variable.used - 1].stop + 1; + range.stop = content.array[i].stop; + + *status = fl_string_dynamic_partial_append_nulless(data_make->buffer, range, &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_partial_append_nulless", F_true); + break; + } + } + + // @todo there needs to always expand into multiple values using whitespace to determine separation, by supporting single and double quote detection (and escaping). + } + else { + *status = fl_string_dynamic_partial_append_nulless(data_make->buffer, content.array[i], &arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_nulless", F_true); + break; + } + } + + *status = fl_string_dynamic_terminate_after(&arguments->array[arguments->used]); + if (F_status_is_error(*status)) { + fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_terminate_after", F_true); + break; + } + + arguments->used++; + + f_macro_iki_variable_delete_simple(iki_variable); + f_macro_iki_vocabulary_delete_simple(iki_vocabulary); + f_macro_iki_content_delete_simple(iki_content); + } // for + + f_macro_iki_variable_delete_simple(iki_variable); + f_macro_iki_vocabulary_delete_simple(iki_vocabulary); + f_macro_iki_content_delete_simple(iki_content); } #endif // _di_fake_make_operation_expand_ #ifndef _di_fake_make_operate_section_ - void fake_make_operate_section(const fake_data data, const fake_make_data data_make, const f_array_length section_id, f_string_lengths *section_stack, f_status *status) { + void fake_make_operate_section(const fake_data data, const f_array_length section_id, fake_make_data *data_make, f_string_lengths *section_stack, f_status *status) { if (F_status_is_error(*status)) return; - if (section_id > data_make.fakefile.used) { + if (section_id > data_make->fakefile.used) { *status = F_status_set_error(F_parameter); fake_print_error(data.context, data.verbosity, F_parameter, "fake_make_operate_section", F_true); return; } - const f_fss_named *section = &data_make.fakefile.array[section_id]; + const f_fss_named *section = &data_make->fakefile.array[section_id]; if (data.verbosity != fake_verbosity_quiet) { printf("%c", f_string_eol[0]); @@ -272,7 +414,7 @@ extern "C" { fl_color_print(f_type_output, data.color_section_set, data.color_section_reset, "Processing Section '"); fl_color_print_code(f_type_output, data.context.notable); - f_print_string_dynamic_partial(f_type_output, data_make.buffer, section->name); + f_print_string_dynamic_partial(f_type_output, data_make->buffer, section->name); fl_color_print_code(f_type_output, data.context.reset); fl_color_print_line(f_type_output, data.color_section_set, data.color_section_reset, "'."); @@ -366,13 +508,15 @@ extern "C" { memset(operations, 0, sizeof(f_array_length) * section->objects.used); memset(arguments, 0, sizeof(f_string_dynamics) * section->objects.used); + bool has_error = F_false; + // pre-process the list to identify invalid commands so that nothing is processed if any operation is invalid. for (; i < section->objects.used; i++) { operation = 0; operation_name = 0; for (j = 0; j < fake_make_operation_total; j++) { - if (fl_string_dynamic_partial_compare(operations_name[j], data_make.buffer, operations_range[j], section->objects.array[i]) == F_equal_to) { + if (fl_string_dynamic_partial_compare(operations_name[j], data_make->buffer, operations_range[j], section->objects.array[i]) == F_equal_to) { operation = operations_type[j]; operation_name = &operations_name[j]; break; @@ -380,28 +524,41 @@ extern "C" { } // for if (operation == 0) { - fake_print_error_fakefile_section_operation_unknown(data.context, data.verbosity, data_make.buffer, section->name, section->objects.array[i]); + fake_print_error_fakefile_section_operation_unknown(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i]); *status = F_status_set_error(F_invalid); } else if (operation == fake_make_operation_type_operate) { if (section_stack->used + 1 > fake_make_section_stack_max) { - fake_print_error_fakefile_section_operation_stack_max(data.context, data.verbosity, data_make.buffer, section->name, section->objects.array[i], fake_make_section_stack_max); + fake_print_error_fakefile_section_operation_stack_max(data.context, data.verbosity, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max); *status = F_status_set_error(F_recurse); } } // find and report all unknown operations before exiting. - if (F_status_is_error(*status)) continue; + if (F_status_is_error(*status)) { + has_error = F_true; + *status = F_none; + continue; + } operations[i] = operation; - fake_make_operation_expand(data, data_make, section->name, operation, *operation_name, section->contents.array[i], &arguments[i], status); + fake_make_operation_expand(data, section->name, operation, *operation_name, section->contents.array[i], data_make, &arguments[i], status); + if (F_status_is_error(*status)) { + has_error = F_true; + *status = F_none; + continue; + } //fake_make_operation_validate(); } // for + if (F_status_is_fine(*status) && has_error) { + *status = F_status_set_error(F_failure); + } + if (F_status_is_error(*status)) { for (i = 0; i < section->objects.used; i++) { f_macro_string_dynamics_delete_simple(arguments[i]); diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index b483c91..c0d8bdc 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -281,8 +281,13 @@ extern "C" { * * @param data * The program data. + * @param section_name + * @param operation + * @param operation_name + * @param content * @param data_make * All make related setting data, including data from the fakefile and optionally build settings file. + * @param arguments * @param section_id * The array location id within the fakefile of the section to operate on. * @param status @@ -291,7 +296,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operation_expand_ - extern void fake_make_operation_expand(const fake_data data, const fake_make_data data_make, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, f_string_dynamics *arguments, f_status *status) f_gcc_attribute_visibility_internal; + extern void fake_make_operation_expand(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_fss_content content, fake_make_data *data_make, f_string_dynamics *arguments, f_status *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operation_expand_ /** @@ -299,10 +304,10 @@ extern "C" { * * @param data * The program data. - * @param data_make - * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_id * The array location id within the fakefile of the section to operate on. + * @param data_make + * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_stack * The current operation stack. * @param status @@ -312,7 +317,7 @@ extern "C" { * F_recurse (with error bit set) is returned if unable to recurse to another operation section (usually max stack depth reached). */ #ifndef _di_fake_make_operate_section_ - void fake_make_operate_section(const fake_data data, const fake_make_data data_make, const f_array_length section_id, f_string_lengths *section_stack, f_status *status) f_gcc_attribute_visibility_internal; + void fake_make_operate_section(const fake_data data, const f_array_length section_id, fake_make_data *data_make, f_string_lengths *section_stack, f_status *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operate_section_ #ifdef __cplusplus diff --git a/level_3/fake/data/build/defines b/level_3/fake/data/build/defines index c665317..4f13080 100644 --- a/level_3/fake/data/build/defines +++ b/level_3/fake/data/build/defines @@ -1,2 +1 @@ # fss-0000 - diff --git a/level_3/fake/data/build/dependencies b/level_3/fake/data/build/dependencies index d4c7810..a473180 100644 --- a/level_3/fake/data/build/dependencies +++ b/level_3/fake/data/build/dependencies @@ -12,12 +12,14 @@ f_directory f_environment f_fss f_file +f_iki f_path f_print fl_color fl_console fl_directory fl_fss +fl_iki fl_status fl_string fl_utf diff --git a/level_3/fake/data/build/fakefile b/level_3/fake/data/build/fakefile index 2abaf02..49ebd75 100644 --- a/level_3/fake/data/build/fakefile +++ b/level_3/fake/data/build/fakefile @@ -15,7 +15,7 @@ main: invalid - print This is another line. + print This is another line. 'parameter\:"verbose" parameter:"verbose2\""' parameter:'verbose3\\' another invalid diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index 090e911..9b06103 100644 --- a/level_3/fake/data/build/settings +++ b/level_3/fake/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_language c build_linker ar build_libraries -lc -build_libraries-individual -lfll_program -lfll_execute -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_fss -lfl_directory -lfl_console -lfl_color -lf_print -lf_path -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory +build_libraries-individual -lfll_program -lfll_execute -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c -- 1.8.3.1