From 18ba59d6faeb15c92781d899978dbcd27d9fb2c3 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 4 Jul 2022 20:17:48 -0500 Subject: [PATCH] Feature: The fake progam is supposed to support a piped fakefile. I thought I implemented this already. I just tried to use it and found it that I had not implemented. This feature is supposed to be in the stable release. --- level_3/fake/c/common.h | 1 + level_3/fake/c/fake.c | 130 ++++++++++++++++++---------- level_3/fake/c/fake.h | 1 + level_3/fake/c/main.c | 4 + level_3/fake/c/private-fake.c | 50 +++++++++++ level_3/fake/c/private-fake.h | 19 ++++ level_3/fake/c/private-make-load_fakefile.c | 8 +- level_3/fake/data/build/dependencies | 1 + level_3/fake/data/build/settings | 2 +- 9 files changed, 166 insertions(+), 50 deletions(-) diff --git a/level_3/fake/c/common.h b/level_3/fake/c/common.h index 594c504..dffac95 100644 --- a/level_3/fake/c/common.h +++ b/level_3/fake/c/common.h @@ -75,6 +75,7 @@ extern "C" { * Set to at least 4 to provide a UTF-8 friendly allocation step. */ #ifndef _di_fake_default_allocation_ + #define fake_default_allocation_pipe_d 16384 #define fake_default_allocation_large_d 64 #define fake_default_allocation_small_d 8 #endif // _di_fake_default_allocation_ diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c index c7d95cc..fcabf8e 100644 --- a/level_3/fake/c/fake.c +++ b/level_3/fake/c/fake.c @@ -77,6 +77,9 @@ extern "C" { fl_print_format(" '%[%r%r ./my_fakefile%]' the fakefile at", file.stream, context.set.notable, f_console_symbol_long_enable_s, fake_long_fakefile_s, context.set.notable); fl_print_format(" '%[./my_fakefile%]' would be used.%r%r", file.stream, context.set.notable, context.set.notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" When piping data this this program, the piped data is treated as a %[%r%].%r", file.stream, context.set.notable, fake_make_parameter_variable_fakefile_s, context.set.notable, f_string_eol_s); + fl_print_format(" Only the %[%r%] operation is supported when using piped data.%r%r", file.stream, context.set.notable, fake_other_operation_make_s, context.set.notable, f_string_eol_s, f_string_eol_s); + funlockfile(file.stream); return F_none; @@ -158,6 +161,18 @@ extern "C" { } } + if (main->parameters.array[fake_parameter_help_e].result == f_console_result_found_e) { + fake_print_help(main->output.to, main->context); + + return F_none; + } + + if (main->parameters.array[fake_parameter_version_e].result == f_console_result_found_e) { + fll_program_print_version(main->output.to, fake_program_version_s); + + return F_none; + } + status = F_none; fake_data_t data = fake_data_t_initialize; @@ -252,7 +267,7 @@ extern "C" { else if (operations_length) { operations[0] = fake_operation_make_e; } - else { + else if (!main->process_pipe) { status = F_status_set_error(F_parameter); if (main->error.verbosity != f_console_verbosity_quiet_e) { @@ -260,20 +275,20 @@ extern "C" { } } - if (main->parameters.array[fake_parameter_help_e].result == f_console_result_found_e) { - fake_print_help(main->output.to, main->context); - - fake_data_delete(&data); + if (F_status_is_error_not(status) && main->process_pipe) { + if (operations_length > 1 || operations[0] != fake_operation_make_e) { + status = F_status_set_error(F_parameter); - return F_none; - } - - if (main->parameters.array[fake_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fake_program_version_s); + if (main->error.verbosity != f_console_verbosity_quiet_e) { + flockfile(main->error.to.stream); - fake_data_delete(&data); + fl_print_format("%r%[%QWhen using an input pipe, only the '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context); + fl_print_format("%[%r%]", main->error.to.stream, main->error.notable, fake_other_operation_make_s, main->error.notable); + fl_print_format("%[' operation is supported.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s); - return F_none; + funlockfile(main->error.to.stream); + } + } } if (F_status_is_error_not(status)) { @@ -294,46 +309,64 @@ extern "C" { { uint8_t i = 0; - // Pre-process and perform validation when "clean" is before a "build" or "make" command as a safety check. - for (uint8_t has_clean = F_false; i < operations_length; ++i) { + if (main->process_pipe) { + data.file_data_build_fakefile.used = 0; - if (operations[i] == fake_operation_clean_e) { - has_clean = F_true; + status = f_string_dynamic_append(f_string_ascii_minus_s, &data.file_data_build_fakefile); + + if (F_status_is_error_not(status)) { + data.fakefile.used = 0; + + status = f_string_dynamic_append(f_string_ascii_minus_s, &data.fakefile); } - else if (operations[i] == fake_operation_build_e || operations[i] == fake_operation_make_e) { - // If the first operation is clean and a make or build operation exists, then the clean operation requires the appropriate settings file or fakefile file. - if (has_clean) { - operations_name = fake_other_operation_clean_s; - data.operation = operations[i]; + if (F_status_is_error(status)) { + fll_error_print(data.main->error, F_status_set_fine(status), "f_string_dynamic_append", F_true); + } + } + else { - status = fake_validate_parameter_paths(&data); + // Pre-process and perform validation when "clean" is before a "build" or "make" command as a safety check. + for (uint8_t has_clean = F_false; i < operations_length; ++i) { - if (F_status_is_error_not(status)) { - f_string_static_t *path = 0; + if (operations[i] == fake_operation_clean_e) { + has_clean = F_true; + } + else if (operations[i] == fake_operation_build_e || operations[i] == fake_operation_make_e) { - if (operations[i] == fake_operation_build_e) { - path = &data.file_data_build_settings; - } - else { - path = &data.file_data_build_fakefile; - } + // If the first operation is clean and a make or build operation exists, then the clean operation requires the appropriate settings file or fakefile file. + if (has_clean) { + operations_name = fake_other_operation_clean_s; + data.operation = operations[i]; - status = f_file_is(*path, F_file_type_regular_d, F_false); + status = fake_validate_parameter_paths(&data); - if (status == F_false) { - status = F_status_set_error(F_file_not); - } + if (F_status_is_error_not(status)) { + f_string_static_t *path = 0; + + if (operations[i] == fake_operation_build_e) { + path = &data.file_data_build_settings; + } + else { + path = &data.file_data_build_fakefile; + } + + status = f_file_is(*path, F_file_type_regular_d, F_false); - if (F_status_is_error(status)) { - fll_error_file_print(data.main->error, F_status_set_fine(status), "f_file_is", F_true, *path, fake_common_file_path_access_s, fll_error_file_type_file_e); + if (status == F_false) { + status = F_status_set_error(F_file_not); + } + + if (F_status_is_error(status)) { + fll_error_file_print(data.main->error, F_status_set_fine(status), "f_file_is", F_true, *path, fake_common_file_path_access_s, fll_error_file_type_file_e); + } } } - } - break; - } - } // for + break; + } + } // for + } if (F_status_is_error_not(status)) { for (i = 0; i < operations_length; ++i) { @@ -419,19 +452,20 @@ extern "C" { } if (main->error.verbosity != f_console_verbosity_quiet_e) { - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_interrupt) { - fflush(main->output.to.stream); - } - - fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - } - else if (status != F_child) { + if (F_status_is_error_not(status) && status != F_child) { fll_print_format("%rAll operations complete.%r%r", main->output.to.stream, f_string_eol_s, f_string_eol_s, f_string_eol_s); } } } + if (F_status_is_error(status) && main->error.verbosity != f_console_verbosity_quiet_e) { + if (F_status_set_fine(status) == F_interrupt) { + fflush(main->output.to.stream); + } + + fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + } + fake_data_delete(&data); return status; diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index 8d5fea3..d1be40a 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -66,6 +66,7 @@ #include #include #include +#include #include #include diff --git a/level_3/fake/c/main.c b/level_3/fake/c/main.c index 7a68ce0..dff0537 100644 --- a/level_3/fake/c/main.c +++ b/level_3/fake/c/main.c @@ -23,6 +23,10 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { data.parameters.array = parameters; data.parameters.used = fake_total_parameters_d; + if (f_pipe_input_exists()) { + data.process_pipe = F_true; + } + fll_program_standard_setup(&data.signal); f_file_umask_get(&data.umask); diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index cdf0600..171d7c9 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -154,6 +154,51 @@ extern "C" { } #endif // _di_fake_file_buffer_ +#ifndef _di_fake_pipe_buffer_ + f_status_t fake_pipe_buffer(fake_data_t * const data, f_string_dynamic_t * const buffer) { + + f_status_t status = F_none; + f_file_t file = f_file_t_initialize; + + file.id = F_type_descriptor_input_d; + file.stream = F_type_input_d; + file.size_read = fake_default_allocation_pipe_d; + + buffer->used = 0; + status = f_string_dynamic_increase_by(fake_common_initial_buffer_max_d, buffer); + + if (F_status_is_error(status)) { + const f_string_static_t message = macro_f_string_static_t_initialize("allocate buffer size for", 0, 24); + fll_error_file_print(data->main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true, f_string_ascii_minus_s, message, fll_error_file_type_file_e); + + f_string_dynamic_resize(0, buffer); + + return status; + } + + do { + if (fll_program_standard_signal_received(data->main)) { + f_string_dynamic_resize(0, buffer); + + fake_print_signal_received(data); + + return F_status_set_error(F_interrupt); + } + + status = f_file_stream_read_block(file, buffer); + + } while (F_status_is_fine(status) && status != F_interrupt && status != F_none_eof); + + if (F_status_is_error(status)) { + fll_error_file_print(data->main->error, F_status_set_fine(status), "f_file_stream_read_block", F_true, f_string_ascii_minus_s, f_file_operation_read_s, fll_error_file_type_file_e); + + f_string_dynamic_resize(0, buffer); + } + + return status; + } +#endif // _di_fake_pipe_buffer_ + #ifndef _di_fake_process_console_parameters_ f_status_t fake_process_console_parameters(fake_data_t * const data) { @@ -513,6 +558,11 @@ extern "C" { #ifndef _di_fake_validate_parameter_paths_ f_status_t fake_validate_parameter_paths(fake_data_t * const data) { + // Only perform these checks when not a pipe. + if (data->main->process_pipe) { + return F_none; + } + if (fll_program_standard_signal_received(data->main)) { fake_print_signal_received(data); diff --git a/level_3/fake/c/private-fake.h b/level_3/fake/c/private-fake.h index e6f98b0..7a954fb 100644 --- a/level_3/fake/c/private-fake.h +++ b/level_3/fake/c/private-fake.h @@ -60,6 +60,25 @@ extern "C" { #endif // _di_fake_file_buffer_ /** + * Load the contents of the standard input pipe into the given buffer, handling all potential errors. + * + * @param data + * The program data. + * @param buffer + * A buffer containing the contents of the file. + * + * @return + * F_none on success. + * + * F_interrupt (with error bit) on receiving a terminate process signal, such as an interrupt signal. + * + * Status codes (with error bit) are returned on any problem. + */ +#ifndef _di_fake_pipe_buffer_ + extern f_status_t fake_pipe_buffer(fake_data_t * const data, f_string_dynamic_t * const buffer) F_attribute_visibility_internal_d; +#endif // _di_fake_pipe_buffer_ + +/** * Validate console arguments and print any relating error messages. * * @param data diff --git a/level_3/fake/c/private-make-load_fakefile.c b/level_3/fake/c/private-make-load_fakefile.c index c62bd82..5518b41 100644 --- a/level_3/fake/c/private-make-load_fakefile.c +++ b/level_3/fake/c/private-make-load_fakefile.c @@ -29,7 +29,13 @@ extern "C" { data_make->fakefile.used = 0; - *status = fake_file_buffer(data_make->data, data_make->data->file_data_build_fakefile, &data_make->buffer); + if (data_make->main->process_pipe) { + *status = fake_pipe_buffer(data_make->data, &data_make->buffer); + } + else { + *status = fake_file_buffer(data_make->data, data_make->data->file_data_build_fakefile, &data_make->buffer); + } + if (F_status_is_error(*status)) return; if (!data_make->buffer.used) { diff --git a/level_3/fake/data/build/dependencies b/level_3/fake/data/build/dependencies index 618799c..416c95d 100644 --- a/level_3/fake/data/build/dependencies +++ b/level_3/fake/data/build/dependencies @@ -18,6 +18,7 @@ f_fss f_file f_iki f_path +f_pipe f_print f_signal fl_control_group diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index 4c5614f..9a58887 100644 --- a/level_3/fake/data/build/settings +++ b/level_3/fake/data/build/settings @@ -23,7 +23,7 @@ build_language c build_libraries -lc -lcap build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_path -lfll_print -lfll_program build_libraries-individual -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_string -build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_print -lf_signal -lf_status_string -lf_string -lf_thread -lf_type_array -lf_utf +build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_status_string -lf_string -lf_thread -lf_type_array -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -- 1.8.3.1